BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_review.h
Go to the documentation of this file.
1/// @file bsls_review.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_review.h -*-C++-*-
8#ifndef INCLUDED_BSLS_REVIEW
9#define INCLUDED_BSLS_REVIEW
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_review bsls_review
15/// @brief Provide assertion macros to safely identify contract violations.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_review
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_review-purpose"> Purpose</a>
25/// * <a href="#bsls_review-classes"> Classes </a>
26/// * <a href="#bsls_review-macros"> Macros </a>
27/// * <a href="#bsls_review-description"> Description </a>
28/// * <a href="#bsls_review-detailed-behavior"> Detailed Behavior </a>
29/// * <a href="#bsls_review-review-levels-and-build-modes"> Review Levels and Build Modes </a>
30/// * <a href="#bsls_review-runtime-configurable-review-failure-behavior"> Runtime-Configurable Review-Failure Behavior </a>
31/// * <a href="#bsls_review-conditional-compilation"> Conditional Compilation </a>
32/// * <a href="#bsls_review-validating-disabled-macro-expressions"> Validating Disabled Macro Expressions </a>
33/// * <a href="#bsls_review-uses-for-ref-bsls_review"> Uses for @ref bsls_review </a>
34/// * <a href="#bsls_review-adding-new-ref-bsls_assert-checks-to-new-code"> Adding New @ref bsls_assert Checks To New Code </a>
35/// * <a href="#bsls_review-adding-assertions-with-ref-bsls_review"> Adding Assertions With @ref bsls_review </a>
36/// * <a href="#bsls_review-reducing-the-assertion-level-for-existing-ref-bsls_assert-macros"> Reducing The Assertion Level For Existing @ref bsls_assert Macros </a>
37/// * <a href="#bsls_review-increasing-deployed-assertion-levels-with-bsls_review_level_"> Increasing Deployed Assertion Levels With BSLS_REVIEW_LEVEL_ </a>
38/// * <a href="#bsls_review-checking-library-usage-before-changing-it-with-ref-bsls_review"> Checking Library Usage Before Changing it With @ref bsls_review </a>
39/// * <a href="#bsls_review-concerns-when-adding-reviews-or-assertions"> Concerns When Adding Reviews or Assertions </a>
40/// * <a href="#bsls_review-usage"> Usage </a>
41/// * <a href="#bsls_review-example-1-adding-bsls_assert-to-an-existing-function"> Example 1: Adding BSLS_ASSERT To An Existing Function </a>
42///
43/// # Purpose {#bsls_review-purpose}
44/// Provide assertion macros to safely identify contract violations.
45///
46/// # Classes {#bsls_review-classes}
47///
48/// - bsls::Review: namespace for "review" management functions
49/// - bsls::ReviewFailureHandlerGuard: scoped guard for changing handlers safely
50/// - bsls::ReviewViolation: attributes describing a failed review check
51///
52/// # Macros {#bsls_review-macros}
53///
54/// - BSLS_REVIEW: runtime check typically enabled in all non-opt build modes
55/// - BSLS_REVIEW_SAFE: runtime check typically only enabled in safe build modes
56/// - BSLS_REVIEW_OPT: runtime check typically enabled in all build modes
57/// - BSLS_REVIEW_INVOKE: immediately invoke the current review handler
58///
59/// @see bsls_assert
60///
61/// # Description {#bsls_review-description}
62/// This component provides three "assert-like" macros,
63/// `BSLS_REVIEW`, `BSLS_REVIEW_SAFE`, and `BSLS_REVIEW_OPT`, that can be used
64/// to enable optional *redundant* runtime checks in corresponding build modes
65/// that are designed to log their failures so production systems can be safely
66/// monitored for contract violations.
67///
68/// This component is designed to allow apparently working production software,
69/// which nonetheless may harbor contract violations, to increase the number of
70/// precondition checks used to catch such bugs without negatively impacting the
71/// existing behavior of the software. The assumption is that any contract
72/// violations uncovered through these checks in stable software is (at least
73/// for the moment) benign. This component should *not* be used for assertions
74/// added to new code; new code should rely on @ref bsls_assert , as any contract
75/// violations discovered in new code may not be benign and the resulting
76/// behavior may be much worse than the task terminating (as would happen using
77/// @ref bsls_assert ).
78///
79/// If the argument of a review macro evaluates to 0, a runtime-configurable
80/// "handler" function is invoked with a `bsls::ReviewViolation`, a
81/// value-semantic class that encapsulates the current filename, line number,
82/// level of failed check, (0-valued expression) argument text, and a count of
83/// how many times that check has already failed. The default handler logs that
84/// a failure has occurred and then allows processing to continue, thus not
85/// adversely impacting the running program. The class `bsls::Review` provides
86/// functions for manipulating the globally configured "handler". A scoped
87/// guard for setting and restoring the review handler is provided by
88/// `bsls::ReviewFailureHandlerGuard`.
89///
90/// An additional macro, `BSLS_REVIEW_INVOKE`, is included for directly invoking
91/// the current review handler as if an assertion had failed on the current
92/// line.
93///
94/// ### Detailed Behavior {#bsls_review-detailed-behavior}
95///
96///
97/// If a review fires (i.e., due to a 0-valued expression argument in a review
98/// macro that is enabled), there is a violation of the contract that the review
99/// is checking. For such a failing review, the program is in an undefined
100/// state but it is deemed inadvisable to immediately abort without further
101/// analysis. It is the goal of the review to be sure to log that a contract
102/// was violated so the issue (in either the calling code or the contract) can
103/// be addressed.
104///
105/// Reviews are enabled or disabled at compile time based on the review level,
106/// assertion level, and build mode flags that have been defined. It is also
107/// possible that assert macros (see @ref bsls_assert ) can be configured in review
108/// mode, and so they may behave exactly as would review macros with appropriate
109/// build flags.
110///
111/// When enabled, the review macros will all do essentially the same thing: Each
112/// macro tests the predicate expression `X`, and if `!(X)` is `true`, tracks a
113/// count of how many times this particular review has failed and invokes the
114/// currently installed review handler. An instance of `bsls::ReviewViolation`
115/// will be created and populated with a textual rendering of the predicate
116/// (`#X`), the current `__FILE__`, the current `__LINE__`, a string
117/// representing which particular type of review or assertion has failed, and
118/// the current count of how many times this predicate has failed (used
119/// primarily to throttle repeated logging of violations from the same
120/// location). This `violation` is then passed to the currently installed
121/// review failure handler, a function pointer with the type
122/// `bsls::Review::ViolationHandler` having the signature:
123/// @code
124/// void(const bsls::ReviewViolation&)
125/// @endcode
126///
127/// ### Review Levels and Build Modes {#bsls_review-review-levels-and-build-modes}
128///
129///
130/// There are a few macros available to control which of the review macros are
131/// actually enabled. These macros are for the compilation and build
132/// environment to provide and are not themselves defined by BDE code -- e.g.,
133/// by supplying one or more of these macros with `-D` options on the compiler
134/// command line. In general, these macros are used to determine a
135/// `REVIEW_LEVEL` that can be `NONE`, `REVIEW_OPT`, `REVIEW`, or `REVIEW_SAFE`.
136/// Depending on the review level, different review macros will be enabled. For
137/// "safer" review configurations, more macros are enabled and all lower-level
138/// (and presumably lower cost) macros are kept enabled. The `NONE` level is
139/// primarily provided for testing to ensure that the `REVIEW_OPT` level doesn't
140/// actually introduce any side-effects or incur measurable overhead when
141/// enabled, though in practice it should not be deployed.
142/// @code
143/// ==================================================
144/// "REVIEW" Macro Instantiation Based on Review Level
145/// ==================================================
146/// BSLS_REVIEW_LEVEL BSLS_REVIEW_OPT BSLS_REVIEW BSLS_REVIEW_SAFE
147/// ----------------- --------------- ----------- ----------------
148/// NONE
149/// REVIEW_OPT ENABLED
150/// REVIEW ENABLED ENABLED
151/// REVIEW_SAFE ENABLED ENABLED ENABLED
152/// @endcode
153/// The logic for the determination of the review level checks a few different
154/// macros. The first check is for one of the 4 mutually exclusive
155/// `BSLS_REVIEW_LEVEL` macros that can explicitly set the review level:
156/// @code
157/// MACRO BSLS_REVIEW_LEVEL
158/// ----- ----------------
159/// BSLS_REVIEW_LEVEL_NONE NONE
160/// BSLS_REVIEW_LEVEL_REVIEW_OPT REVIEW_OPT
161/// BSLS_REVIEW_LEVEL_REVIEW REVIEW
162/// BSLS_REVIEW_LEVEL_REVIEW_SAFE REVIEW_SAFE
163/// @endcode
164/// If none of those macros are defined, the review level is implemented to be
165/// exactly the same as the assertion level (see @ref bsls_assert ). This is so
166/// that any introduced review macro will still be enabled (and become an
167/// assertion) when it is textually replaced with a `BSLS_ASSERT`. This means
168/// that first one of the 7 mutually exclusive `BSLS_ASSERT_LEVEL` macros are
169/// checked to determine the review level:
170/// @code
171/// MACRO BSLS_REVIEW_LEVEL
172/// ----- ----------------
173/// BSLS_ASSERT_LEVEL_ASSUME_SAFE NONE
174/// BSLS_ASSERT_LEVEL_ASSUME_ASSERT NONE
175/// BSLS_ASSERT_LEVEL_ASSUME_OPT NONE
176/// BSLS_ASSERT_LEVEL_NONE NONE
177/// BSLS_ASSERT_LEVEL_ASSERT_OPT REVIEW_OPT
178/// BSLS_ASSERT_LEVEL_ASSERT REVIEW
179/// BSLS_ASSERT_LEVEL_ASSERT_SAFE REVIEW_SAFE
180/// @endcode
181/// Finally, the default review (and assert) level, if none of the overriding
182/// review or assert level macros above are defined, is determined by the build
183/// mode. With "safer" build modes we incorporate higher-level defensive
184/// program checks. A particular build mode is implied by the relevant (BDE)
185/// build targets that are defined at compilation (preprocessing) time. The
186/// following table shows the three (BDE) build targets that can affect the
187/// assertion and review levels (note that `BDE_BUILD_TARGET_DBG` plays no
188/// role):
189/// @code
190/// (BDE) Build Targets
191/// -----------------------
192/// (A) BDE_BUILD_TARGET_SAFE_2
193/// (B) BDE_BUILD_TARGET_SAFE
194/// (C) BDE_BUILD_TARGET_OPT
195/// @endcode
196/// *Any* of the 8 possible combinations of the three build targets is valid;
197/// e.g., `BDE_BUILD_TARGET_OPT` and `BDE_BUILD_TARGET_SAFE_2` may both be
198/// defined. The following table shows the review level that is set depending
199/// on which combination of build target macros have been set:
200/// @code
201/// =========================================================
202/// "REVIEW" Level Set With no Level-Overriding Flags defined
203/// =========================================================
204/// --- BDE_BUILD_TARGET ---- BSLS_REVIEW_LEVEL
205/// _SAFE_2 _SAFE _OPT
206/// ------- ------- ------- -----------------
207/// REVIEW
208/// DEFINED REVIEW_OPT
209/// DEFINED REVIEW_SAFE
210/// DEFINED DEFINED REVIEW_SAFE
211/// DEFINED REVIEW_SAFE
212/// DEFINED DEFINED REVIEW_SAFE
213/// DEFINED DEFINED REVIEW_SAFE
214/// DEFINED DEFINED DEFINED REVIEW_SAFE
215/// @endcode
216/// As the table above illustrates, with no build target explicitly defined the
217/// review level defaults to `REVIEW`. If only `BDE_BUILD_TARGET_OPT` is
218/// defined, the review level will be set to `REVIEW_OPT`. If either
219/// `BDE_BUILD_TARGET_SAFE` or `BDE_BUILD_TARGET_SAFE_2` is defined then the
220/// review level is set to `REVIEW_SAFE` and ALL review macros will be enabled.
221///
222/// ### Runtime-Configurable Review-Failure Behavior {#bsls_review-runtime-configurable-review-failure-behavior}
223///
224///
225/// In addition to the three (BSLS) "REVIEW" macros, `BSLS_REVIEW`,
226/// `BSLS_REVIEW_SAFE`, and `BSLS_REVIEW_OPT`, and the immediate invocation
227/// macro `BSLS_REVIEW_INVOKE`, this component provides (1) an `invokeHandler`
228/// method used (primarily) to implement these "REVIEW" macros and enable their
229/// runtime configuration, (2) administrative methods to configure, at runtime,
230/// the behavior resulting from a review failure (i.e., by installing an
231/// appropriate review-failure handler function), and (3) a suite of standard
232/// ("off-the-shelf") review-failure handler functions, to be installed via the
233/// methods (if desired), and invoked by the `invokeHandler` method of a review
234/// failure.
235///
236/// When an enabled review fails, the currently installed *failure* *handler*
237/// ("callback") function is invoked. The default handler is the (`static`)
238/// `bsls::Review::failByLog` method, which will log the failure and the current
239/// callstack when invoked for the first time, and exponentially less frequently
240/// as additional failures of the same review site occur. A user may replace
241/// this default handler by using the (`static`)
242/// `bsls::Review::setViolationHandler` administrative method and passing it
243/// (the address of) a function whose signature conforms to the
244/// `bsls::Review::ViolationHandler` `typedef`. This handler may be one of the
245/// other handler methods provided in `bsls::Review`, or a "custom" function
246/// written by the user.
247///
248/// One additional provided class, `bsls::ReviewFailureHandlerGuard`, can be
249/// used to override the review handler within a specific block of code. Note
250/// that this is primarily intended for testing and should be instantiated at a
251/// non-granular level, as the setting and resetting of the handler done by this
252/// RAII class has no provisions in it to handle being used concurrently by
253/// multiple threads.
254///
255/// The primary uses for setting the review handler to a non-default handler are
256/// to get all reviews to behave like some kind of an assertion, or to get
257/// reviews to throw exceptions to facilitate testing. Both of these scenarios
258/// are primarily encountered in test drivers, and the general workflows for
259/// reviews and assertions depend on a policy where deployed production tasks
260/// use the default handlers.
261///
262/// ### Conditional Compilation {#bsls_review-conditional-compilation}
263///
264///
265/// To recap, there are three (mutually compatible) general *build* *targets*:
266/// * `BDE_BUILD_TARGET_OPT`
267/// * `BDE_BUILD_TARGET_SAFE`
268/// * `BDE_BUILD_TARGET_SAFE_2`
269/// seven (mutually exclusive) component-specific *assertion* *levels*:
270/// * `BSLS_ASSERT_LEVEL_ASSERT_SAFE`
271/// * `BSLS_ASSERT_LEVEL_ASSERT`
272/// * `BSLS_ASSERT_LEVEL_ASSERT_OPT`
273/// * `BSLS_ASSERT_LEVEL_NONE`
274/// * `BSLS_ASSERT_LEVEL_ASSUME_OPT`
275/// * `BSLS_ASSERT_LEVEL_ASSUME_ASSERT`
276/// * `BSLS_ASSERT_LEVEL_ASSUME_SAFE`
277/// and four (mutually exclusive) component-specific *review* *levels*:
278/// * `BSLS_REVIEW_LEVEL_REVIEW_SAFE`
279/// * `BSLS_REVIEW_LEVEL_REVIEW`
280/// * `BSLS_REVIEW_LEVEL_REVIEW_OPT`
281/// * `BSLS_REVIEW_LEVEL_NONE`
282/// The above macros can be defined (externally) by the build environment to
283/// affect which of the three *review* *macros*:
284/// * `BSLS_REVIEW_SAFE(boolean-valued expression)`
285/// * `BSLS_REVIEW(boolean-valued expression)`
286/// * `BSLS_REVIEW_OPT(boolean-valued expression)`
287/// will be enabled (i.e., instantiated).
288///
289/// The public interface of this component also provides some additional
290/// intermediate macros to identify how the various `BSLS_REVIEW` macros have
291/// been instantiated. These exist for each level and have the following
292/// suffixes and meanings:
293/// * `IS_ACTIVE`: Defined if the corresponding level is enabled.
294/// * `IS_USED`: Defined if the expressions for the corresponding level need to
295/// be valid (i.e., if they are"'ODR-used").
296///
297/// Putting that together, these 3 macros are defined if the corresponding macro
298/// is enabled:
299/// * `BSLS_REVIEW_SAFE_IS_ACTIVE`
300/// * `BSLS_REVIEW_IS_ACTIVE`
301/// * `BSLS_REVIEW_OPT_IS_ACTIVE`
302///
303/// Finally, three more macros with the `IS_USED` suffix are defined when the
304/// expression for the corresponding macro is going to be compiled. This will
305/// be true if the macro is enabled or if `BSLS_REVIEW_VALIDATE_DISABLED_MACROS`
306/// has been defined.
307/// * `BSLS_REVIEW_SAFE_IS_USED`
308/// * `BSLS_REVIEW_IS_USED`
309/// * `BSLS_REVIEW_OPT_IS_USED`
310///
311/// All of these additional "predicate" macros can be used directly by clients
312/// of this component to conditionally compile code other than just (BSLS)
313/// reviews, but that should be done with care to be sure code compiles and is
314/// compatible across all build modes.
315///
316/// ### Validating Disabled Macro Expressions {#bsls_review-validating-disabled-macro-expressions}
317///
318///
319/// An additional external macro, `BSLS_REVIEW_VALIDATE_DISABLED_MACROS`, can be
320/// defined to control the compile time behavior of @ref bsls_review . Enabling
321/// this macro configures all *disabled* review macros to still instantiate
322/// their predicates (in a non-evaluated context) to be sure that the predicate
323/// is still syntactically valid. This can be used to ensure reviews that are
324/// rarely enabled have valid expressions.
325///
326/// ### Uses for @ref bsls_review {#bsls_review-uses-for-ref-bsls_review}
327///
328///
329/// @ref bsls_review exists primarily as a step towards adding or modifying
330/// instances of @ref bsls_assert macros in code that are already running in
331/// production. New @ref bsls_assert macros are risky to add, and enabled
332/// @ref bsls_assert macros that were not previously enabled is equally risky.
333///
334/// Given code that is already running and deployed, but not "breaking" in
335/// obvious ways, the review process provides a way to see if contracts are
336/// being met in those running processes without risking unexpected aborts
337/// happening in those systems. The contracts that might be getting violated in
338/// already deployed applications need to be fixed and avoided, BUT there exists
339/// no evidence that these violations are currently crashing the system.
340///
341/// In general, @ref bsls_review can also be considered as a way to identify if
342/// deployed code is violating function contracts in some way. Once calling
343/// applications and library code have been altered so all contracts are being
344/// met, uses of @ref bsls_review macros are then changed into the corresponding
345/// @ref bsls_assert macros, which enforce the contracts instead of simply
346/// monitoring them. In some cases, the @ref bsls_review macros can also be
347/// replaced by new behavior, e.g., widening narrow contracts without risking
348/// breaking the expectations of existing applications.
349///
350/// ### Adding New @ref bsls_assert Checks To New Code {#bsls_review-adding-new-ref-bsls_assert-checks-to-new-code}
351///
352///
353/// @ref bsls_review is not appropriate for "new" code that has not yet been
354/// deployed to a production environment; use @ref bsls_assert instead.
355///
356/// ### Adding Assertions With @ref bsls_review {#bsls_review-adding-assertions-with-ref-bsls_review}
357///
358///
359/// The introduction of a new assertion using @ref bsls_review should follow these
360/// steps:
361/// 1. Add the appropriate @ref bsls_review macros to your code.
362/// 2. Commit these changes and make sure all processes using your code get
363/// rebuilt and deployed to production.
364/// 3. Monitor relevant log files for "BSLS_REVIEW failure" messages citing the
365/// location of these reviews.
366/// 4. If any failures occurred, fix the calling code, or widen the contract
367/// being violated (which should be rare).
368/// 5. Wait for sufficient time to pass to be confident that the contract is not
369/// being violated by the current version of the software in production.
370/// 6. Replace `BSLS_REVIEW` with `BSLS_ASSERT` and redeploy.
371///
372/// ### Reducing The Assertion Level For Existing @ref bsls_assert Macros {#bsls_review-reducing-the-assertion-level-for-existing-ref-bsls_assert-macros}
373///
374///
375/// In order to reduce the level of an existing assertion, such as changing a
376/// `BSLS_ASSERT_SAFE` into a `BSLS_ASSERT`, or a `BSLS_ASSERT` into a
377/// `BSLS_ASSERT_OPT`, you should follow a very similar process to the process
378/// for adding a new assertion of that level. There are two possible approaches
379/// that largely depend on how widely deployed the code is that is already built
380/// with the old assertions enabled.
381/// 1. If the existing assertion is not enabled in deployed production code,
382/// such as a `BSLS_ASSERT_SAFE` where client code rarely or never deploys
383/// safe builds, then simply remove the old assertion and start the process
384/// described above of adding in the higher level assertion as if it was a
385/// newly added assertion. Here changing a `BSLS_ASSERT_SAFE` to a
386/// `BSLS_ASSERT` would then begin with changing the `BSLS_ASSERT_SAFE` into
387/// a `BSLS_REVIEW` and continuing as above.
388/// 2. If the existing assertion is depended on in released production code then
389/// the process involved needs to maintain the assertion at the existing
390/// level while adding in the review at the higher level, eventually
391/// including only the assert at the higher level when the process is
392/// complete.
393///
394/// Therefore, the "safest" way to increase an assertion level is to follow
395/// these steps:
396/// 1. Given an existing `BSLS_ASSERT` such as this:
397/// ..
398/// BSLS_ASSERT(some_test());
399/// ..
400/// You can duplicate the test as a `BSLS_REVIEW_OPT`, if the test is very
401/// negligible, like this:
402/// ..
403/// BSLS_ASSERT(some_test());
404/// BSLS_REVIEW_OPT(some_test());
405/// ..
406/// If the duplicated check is unacceptably expensive (which should make you
407/// question making this assertion a `BSLS_ASSERT_OPT` in the first place),
408/// then you can opt for the more cumbersome:
409/// ..
410/// #ifdef BSLS_ASSERT_IS_ACTIVE
411/// BSLS_ASSERT(some_test());
412/// #else
413/// BSLS_REVIEW_OPT(some_test());
414/// #endif
415/// ..
416/// 2. Commit these changes and make sure all processes built at the higher
417/// assertion level are rebuilt and deployed, thus beginning the review
418/// process for this changed assertion.
419/// 3. Follow steps 3-5 of the {Adding Assertions With @ref bsls_review } workflow.
420/// 4. When complete, replace all changes made in step 1 with:
421/// ..
422/// BSLS_ASSERT_OPT(some_test());
423/// ..
424/// 5. Revel in the more widespread use of your existing assertion.
425///
426/// ### Increasing Deployed Assertion Levels With BSLS_REVIEW_LEVEL_ {#bsls_review-increasing-deployed-assertion-levels-with-bsls_review_level_}
427///
428///
429/// A common situation in deployed tasks is that they are built with only
430/// `BSLS_ASSERT_OPT` enabled. To improve the robustness of these applications,
431/// there is then a desire to run them with `BSLS_ASSERT` enabled, or even
432/// `BSLS_ASSERT_SAFE`. Enabling these assertions, however, brings in the same
433/// risks of hard failures for contract violations that adding new assertions
434/// does. `BSLS_REVIEW` provides a process for making this change without
435/// risking aborting processes that were previously "running just fine".
436///
437/// Any explicit setting of the `BSLS_REVIEW_LEVEL` ("review level") to a level
438/// higher than the `BSLS_ASSERT_LEVEL` ("assert level") will not only enable
439/// the `BSLS_REVIEW` macros at that level, but it will turn all `BSLS_ASSERT`
440/// macros at that level into reviews as well, and disable any assumption of
441/// `BSLS_ASSERT` assertions. Given a task that is built with an assertion
442/// level of `OPT`, if you set the review level to `REVIEW` you will then get
443/// logs and notifications of any failed `BSLS_ASSERT` checks, but those failing
444/// checks will not immediately abort your application.
445///
446/// So the process for deploying an application with a higher assertion level is
447/// to follow these steps:
448/// 1. Rebuild the task with the review level set to the desired assertion
449/// level, using `BSLS_REVIEW_LEVEL_REVIEW_OPT`, `BSLS_REVIEW_LEVEL_REVIEW`,
450/// or `BSLS_REVIEW_LEVEL_REVIEW_SAFE`.
451/// 2. Deploy the task.
452/// 3. Monitor relevant log files for "BSLS_REVIEW failure" messages citing the
453/// location of these reviews.
454/// 4. Once all review failures have been addressed and no failures are logged
455/// for a "sufficient" time, remove the explicitly set `BSLS_REVIEW_LEVEL`
456/// from your build and change to set an explicit `BSLS_ASSERT_LEVEL` at your
457/// new level.
458/// 5. Deploy your newly built application with increased enabled defensive
459/// checks.
460/// 6. Revel in the comfort of taking advantage of the additional defensive
461/// checks now enabled in your code.
462///
463/// ### Checking Library Usage Before Changing it With @ref bsls_review {#bsls_review-checking-library-usage-before-changing-it-with-ref-bsls_review}
464///
465///
466/// Occasionally, given code that is in use in production, you may come across a
467/// case that makes no sense but that you want to reimplement with altered
468/// behavior. The previous behavior might have been out of contract or just
469/// seemingly nonsensical, but you are not confident that no one is actually
470/// running code that executes that behavior and relies on it.
471///
472/// @ref bsls_review here provides a way to insert a review that checks if the code
473/// in question is ever being invoked. To do that, follow these steps:
474/// 1. Depending on the structure of the code you want to monitor, add a
475/// `BSLS_REVIEW_INVOKE` or a `BSLS_REVIEW_OPT` with a check that will fail
476/// on the condition you want to monitor. Use these macros as they will be
477/// enabled in almost all build modes.
478/// 2. Commit your changes and get the applications using your code deployed.
479/// 3. If any code hits your review, assess it for why and fix the calling code
480/// or re-assess the behavior you want to change.
481/// 4. Once "sufficient" time has passed with no review failures, remove the
482/// @ref bsls_review checks entirely.
483/// 5. Make changes to your code's behavior that impact only those states where
484/// previously your review would have failed. Check in and deploy those
485/// changes.
486/// 6. Revel in safely having deployed a Liskov-substitutable version of your
487/// library with exciting and new behavior.
488///
489/// ### Concerns When Adding Reviews or Assertions {#bsls_review-concerns-when-adding-reviews-or-assertions}
490///
491///
492/// 1. Performance: In general, a new @ref bsls_review check will perform exactly
493/// the same as a @ref bsls_assert with the same predicate. One subtle
494/// difference is that apparently working software can contain failing
495/// @ref bsls_review checks logging failures that may be ignored (whereas
496/// @ref bsls_assert failures are designed to be hard to ignore). Handling
497/// these failures requires maintaining the failure count using atomic
498/// operations that may negatively impact performance if checks are failing
499/// (and ignored) in performance-sensitive code. Failing checks should
500/// always be addressed as promptly as possible.
501/// 2. Downstream Linking: For a library developer, part of the review rollout
502/// process will rely heavily on users of your library relinking multiple
503/// times during the process of adding reviews. One might assume that this
504/// means the verification that a review is not failing can extend an
505/// indefinite amount of time. The better overall policy is to realize that,
506/// just like library users can opt-in to rebuilding their tasks more often,
507/// the stability benefits of being involved in the review process by
508/// relinking and rolling out more often are opt-in as well. For tasks that
509/// are rebuilt very infrequently, they will simply have to accept that
510/// library misuse on their end might result in crashes due to asserts that
511/// were introduced between their own too-infrequent releases.
512/// 3. Unit Testing with Reviews: In general, unit test log files are rarely
513/// monitored or read, so a failing `BSLS_REVIEW` is unlikely to be caught
514/// during unit tests. Test drivers should almost always set the review
515/// handler to the abort handler so any failed reviews are caught immediately
516/// as test failures.
517/// 4. Sufficient Time: All of the review-related workflows mention running
518/// reviewed code for "sufficient" time to know the check is not failing.
519/// "Sufficient" time will vary by application.
520///
521/// ## Usage {#bsls_review-usage}
522///
523///
524///
525/// ### Example 1: Adding BSLS_ASSERT To An Existing Function {#bsls_review-example-1-adding-bsls_assert-to-an-existing-function}
526///
527///
528/// Suppose you have an existing function, already deployed to production, that
529/// was not written with defensive programming in mind. In order to increase
530/// robustness, you would like to add `BSLS_ASSERT` macros to this function that
531/// match the contract originally written when this function was initially
532/// released.
533///
534/// For example, consider the function `myFunc` in the class `FunctionsV1` that
535/// was implemented like this:
536/// @code
537/// my_functions.h
538/// ...
539///
540/// class FunctionsV1 {
541/// // ...
542/// public:
543/// // ...
544///
545/// static int myFunc(int x, int y);
546/// // Do something with the specified positive integers 'x' and 'y'.
547/// };
548///
549/// inline int FunctionsV1::myFunc(int x, int y)
550/// {
551/// int output = 0;
552/// // ... do stuff with 'x' and 'y'.
553/// return output;
554/// }
555/// @endcode
556/// Notice that there are no checks on `x` and `y` within `myFunc` and no
557/// assertions to detect use of `myFunc` outside of its contract. On the other
558/// hand, `myFunc` is part of legacy code that has been in use extensively for
559/// years or decades, so clearly this is not causing a problem (yet).
560///
561/// Upon reviewing this class you realize that `myFunc` produces random results
562/// for values of `x` or `y` less than 0. You, however, do not have enough
563/// information to conclude that no one is calling it with negative values and
564/// just using the bad results unknowingly. There are a number of possibilities
565/// for how the result of this undefined behavior might be going unnoticed.
566/// * The invalid value might be discarded by a bounds check later in the
567/// process.
568/// * The invalid value may only result in a small glitch the users have not
569/// noticed or ignored.
570/// * The resulting value may actually be valid, but allowing negative input
571/// for `x` and `y` may preclude potential future development in ways we do
572/// not want to allow.
573/// All of these are bad, but adding in checks with `BSLS_ASSERT` that would
574/// replace these bad behaviors by process termination would turn silent errors
575/// into loud errors (potentially worse). On the other hand, by not adding
576/// `BSLS_ASSERT` checks we permit future misuses of this function, which may
577/// not be innocuous, to potentially reach production systems. `BSLS_REVIEW`
578/// here serves as a bridge, from the current state of `myFunc` (entirely
579/// unchecked) to the ideal state of `myFunc` (where misuse is caught loudly and
580/// immediately through `BSLS_ASSERT`), following a path that doesn't risk
581/// turning an un-noticed or irrelevant error into one that will significantly
582/// hinder ongoing business.
583///
584/// The solution to this is to *initially* reimplement `myFunc` using
585/// `BSLS_REVIEW` like this:
586/// @code
587/// my_functions.h
588/// ...
589/// #include <bsls_review.h>
590/// ...
591///
592/// class FunctionsV2 {
593/// // ...
594/// public:
595/// // ...
596///
597/// static int myFunc(int x, int y);
598/// // Do something with the specified 'x' and 'y'. The behavior is
599/// // undefined unless 'x > 0' and 'y > 0'.
600/// };
601///
602/// inline int FunctionsV2::myFunc(int x, int y)
603/// {
604/// BSLS_REVIEW(x > 0);
605/// BSLS_REVIEW(y > 0);
606/// int output = 0;
607/// // ... do stuff with 'x' and 'y'.
608/// return output;
609/// }
610/// @endcode
611/// Now you can deploy this code to production and then begin reviewing logs.
612/// The log messages you should look for are those produced by `bsls::Review`s
613/// default review failure handler and will be similar to:
614/// @code
615/// ERROR myfunction.h::17 BSLS_REVIEW failure (level:R-DBG): 'x > 0'
616/// Please run "/bb/bin/showfunc.tsk ...
617/// @endcode
618/// `showfunc.tsk` is a Bloomberg application that can be used (along with the
619/// task binary) to convert the reported stack addresses to a more traditional
620/// stack trace with a function call stack.
621///
622/// It is important to note that `BSLS_REVIEW` is purely informative, and adding
623/// a review will not adversely affect behavior, and may in fact alert the
624/// library author to common client misconceptions about the intended behavior.
625///
626/// For example, let's say actual usage makes it clear that users expect 0 to be
627/// valid values for the arguments to `myFunc`, and nothing in the
628/// implementation prevents us from accepting 0 as input and producing the
629/// answer clients expect. Instead of changing all the clients, we may instead
630/// choose to change the function contract (and implemented checks):
631/// @code
632/// my_functions.h
633/// ...
634/// #include <bsls_review.h>
635/// ...
636///
637/// class FunctionsV3 {
638/// // ...
639/// public:
640/// // ...
641///
642/// static int myFunc(int x, int y);
643/// // Do something with the specified 'x' and 'y'. The behavior is
644/// // undefined unless 'x >= 0' and 'y >= 0'.
645/// };
646///
647/// inline int FunctionsV3::myFunc(int x, int y)
648/// {
649/// BSLS_REVIEW(x >= 0);
650/// BSLS_REVIEW(y >= 0);
651/// int output = 0;
652/// // ... do stuff with 'x' and 'y'.
653/// return output;
654/// }
655/// @endcode
656/// Finally, at some point, the implementation of `myFunc` using `BSLS_REVIEW`
657/// has been running a suitable amount of time that you are comfortable
658/// transitioning the use of @ref bsls_review to @ref bsls_assert . We now use our
659/// favorite text editor or script to replace "BSLS_REVIEW" with "BSLS_ASSERT":
660/// @code
661/// my_functions.h
662/// ...
663/// #include <bsls_assert.h>
664/// ...
665///
666/// class FunctionsV4 {
667/// // ...
668/// public:
669/// // ...
670///
671/// static int myFunc(int x, int y);
672/// // Do something with the specified 'x' and 'y'. The behavior is
673/// // undefined unless 'x >= 0' and 'y >= 0'.
674/// };
675///
676/// inline int FunctionsV4::myFunc(int x, int y)
677/// {
678/// BSLS_ASSERT(x >= 0);
679/// BSLS_ASSERT(y >= 0);
680/// int output = 0;
681/// // ... do stuff with 'x' and 'y'.
682/// return output;
683/// }
684/// @endcode
685/// At this point, any contract violations in the use of `myFunc` in new code
686/// will be caught immediately (i.e., in appropriate build modes).
687/// @}
688/** @} */
689/** @} */
690
691/** @addtogroup bsl
692 * @{
693 */
694/** @addtogroup bsls
695 * @{
696 */
697/** @addtogroup bsls_review
698 * @{
699 */
700
701#include <bsls_assertimputil.h>
703#include <bsls_buildtarget.h>
705#include <bsls_keyword.h>
706#include <bsls_performancehint.h>
707#include <bsls_platform.h>
708
709#ifdef BSLS_ASSERT_USE_CONTRACTS
710#include <contract>
711#endif
712
713 // =============================
714 // Checks for Pre-Defined macros
715 // =============================
716
717#if defined(BSLS_REVIEW)
718#error BSLS_REVIEW is already defined!
719#endif
720
721#if defined(BSLS_REVIEW_REVIEW_IMP)
722#error BSLS_REVIEW_REVIEW_IMP is already defined!
723#endif
724
725#if defined(BSLS_REVIEW_REVIEW_COUNT_IMP)
726#error BSLS_REVIEW_REVIEW_COUNT_IMP is already defined!
727#endif
728
729#if defined(BSLS_REVIEW_DISABLED_IMP)
730#error BSLS_REVIEW_DISABLED_IMP is already defined!
731#endif
732
733#if defined(BSLS_REVIEW_INVOKE)
734#error BSLS_REVIEW_INVOKE is already defined!
735#endif
736
737#if defined(BSLS_REVIEW_IS_ACTIVE)
738#error BSLS_REVIEW_IS_ACTIVE is already defined!
739#endif
740
741#if defined(BSLS_REVIEW_IS_USED)
742#error BSLS_REVIEW_IS_USED is already defined!
743#endif
744
745#if defined(BSLS_REVIEW_OPT)
746#error BSLS_REVIEW_OPT is already defined!
747#endif
748
749#if defined(BSLS_REVIEW_OPT_IS_ACTIVE)
750#error BSLS_REVIEW_OPT_IS_ACTIVE is already defined!
751#endif
752
753#if defined(BSLS_REVIEW_OPT_IS_USED)
754#error BSLS_REVIEW_OPT_IS_USED is already defined!
755#endif
756
757#if defined(BSLS_REVIEW_SAFE)
758#error BSLS_REVIEW_SAFE is already defined!
759#endif
760
761#if defined(BSLS_REVIEW_SAFE_IS_ACTIVE)
762#error BSLS_REVIEW_SAFE_IS_ACTIVE is already defined!
763#endif
764
765#if defined(BSLS_REVIEW_SAFE_IS_USED)
766#error BSLS_REVIEW_SAFE_IS_USED is already defined!
767#endif
768
769 // =================================
770 // (BSLS) "REVIEW" Macro Definitions
771 // =================================
772
773// Implementation Note: We wrap the 'if' statement below in a (seemingly
774// redundant) do-while-false loop to require, syntactically, a trailing
775// semicolon, and to ensure that the macro behaves properly in an if-then-else
776// context -- even if one forgets to wrap, with curly braces, the body of an
777// 'if' having just a single 'BSLS_REVIEW*' statement.
778
779 // =============================================
780 // Factored Implementation for Internal Use Only
781 // =============================================
782
783#if !(defined(BSLS_REVIEW_LEVEL_REVIEW_SAFE) || \
784 defined(BSLS_REVIEW_LEVEL_REVIEW) || \
785 defined(BSLS_REVIEW_LEVEL_REVIEW_OPT) || \
786 defined(BSLS_REVIEW_LEVEL_NONE))
787// In order to replicate the control logic of 'BSLS_ASSERT', if there has been
788// no explicit review level set we check to see if there has been an explicit
789// assert level set. If so, we act as though the review level has been
790// explicitly set to the same thing (instead of just basing the review level
791// off of only the build mode).
792 #if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE)
793 #define BSLS_REVIEW_LEVEL_REVIEW_SAFE
794 #define BSLS_REVIEW_NO_REVIEW_MACROS_DEFINED 0
795 #elif defined(BSLS_ASSERT_LEVEL_ASSERT)
796 #define BSLS_REVIEW_LEVEL_REVIEW
797 #define BSLS_REVIEW_NO_REVIEW_MACROS_DEFINED 0
798 #elif defined(BSLS_ASSERT_LEVEL_ASSERT_OPT)
799 #define BSLS_REVIEW_LEVEL_REVIEW_OPT
800 #define BSLS_REVIEW_NO_REVIEW_MACROS_DEFINED 0
801 #elif defined(BSLS_ASSERT_LEVEL_NONE) || \
802 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE) || \
803 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT) || \
804 defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)
805 #define BSLS_REVIEW_LEVEL_NONE
806 #define BSLS_REVIEW_NO_REVIEW_MACROS_DEFINED 0
807 #else
808 // Only here, with no explicit review level OR assertion level, does
809 // this macro finally get set to true, which will trigger
810 // buildtarget-based logic for macro configuration
811 #define BSLS_REVIEW_NO_REVIEW_MACROS_DEFINED 1
812 #endif
813#else
814 #define BSLS_REVIEW_NO_REVIEW_MACROS_DEFINED 0
815#endif
816
817 // ============================
818 // BSLS_REVIEW_REVIEW_COUNT_IMP
819 // ============================
820
821// This macro is defined in order to maintain a static 'count' where a
822// 'BSLS_REVIEW' is used. When possible, this is done inside a lamba (which
823// will only be invoked when a violation happens) in order to facilitate use
824// within 'constexpr' functions.
825
826#ifdef BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP14
827 #define BSLS_REVIEW_REVIEW_COUNT_IMP \
828 int lastCount = BloombergLP::bsls::Review::updateCount( \
829 []{ \
830 static BloombergLP::bsls::Review::Count count = {0}; \
831 return &count; \
832 }() );
833#else
834 #define BSLS_REVIEW_REVIEW_COUNT_IMP \
835 static BloombergLP::bsls::Review::Count count = {0}; \
836 int lastCount = BloombergLP::bsls::Review::updateCount(&count);
837#endif
838
839 // ======================
840 // BSLS_REVIEW_REVIEW_IMP
841 // ======================
842
843#ifdef BSLS_ASSERT_USE_CONTRACTS
844#define BSLS_REVIEW_REVIEW_IMP(X,LVL) [[ assert check_maybe_continue : X ]]
845
846#ifdef BSLS_REVIEW_VALIDATE_DISABLED_MACROS
847#define BSLS_REVIEW_DISABLED_IMP(X,LVL) [[ assert ignore : X ]]
848#else
849#define BSLS_REVIEW_DISABLED_IMP(X,LVL)
850#endif
851
852#else // BSLS_ASSERT_USE_CONTRACTS
853
854#define BSLS_REVIEW_REVIEW_IMP(X,LVL) do { \
855 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!(X))) { \
856 BSLS_PERFORMANCEHINT_UNLIKELY_HINT; \
857 BSLS_REVIEW_REVIEW_COUNT_IMP; \
858 BloombergLP::bsls::ReviewViolation violation( \
859 #X, \
860 BSLS_ASSERTIMPUTIL_FILE, \
861 BSLS_ASSERTIMPUTIL_LINE, \
862 LVL, \
863 lastCount); \
864 BloombergLP::bsls::Review::invokeHandler(violation); \
865 } \
866 } while (false)
867
868#ifdef BSLS_REVIEW_VALIDATE_DISABLED_MACROS
869#define BSLS_REVIEW_DISABLED_IMP(X,LVL) (void)sizeof((X)?true:false)
870#else
871#define BSLS_REVIEW_DISABLED_IMP(X,LVL)
872#endif
873
874#endif
875
876 // ==================
877 // BSLS_REVIEW_INVOKE
878 // ==================
879
880// 'BSLS_REVIEW_INVOKE' is always active.
881#define BSLS_REVIEW_INVOKE(X) do { \
882 BSLS_REVIEW_REVIEW_COUNT_IMP; \
883 BloombergLP::bsls::ReviewViolation violation( \
884 X, \
885 BSLS_ASSERTIMPUTIL_FILE, \
886 BSLS_ASSERTIMPUTIL_LINE, \
887 BloombergLP::bsls::Review::k_LEVEL_INVOKE, \
888 lastCount); \
889 BloombergLP::bsls::Review::invokeHandler(violation); \
890 } while (false)
891
892 // ================
893 // BSLS_REVIEW_SAFE
894 // ================
895
896// Determine if 'BSLS_REVIEW_SAFE' should be active.
897
898#if defined(BSLS_REVIEW_LEVEL_REVIEW_SAFE) \
899 || BSLS_REVIEW_NO_REVIEW_MACROS_DEFINED && ( \
900 defined(BDE_BUILD_TARGET_SAFE_2) || \
901 defined(BDE_BUILD_TARGET_SAFE) )
902
903 #define BSLS_REVIEW_SAFE_IS_ACTIVE // also usable directly in client code
904#endif
905
906// Indicate when 'BSLS_REVIEW_SAFE' arguments will be ODR-used.
907#if defined(BSLS_REVIEW_SAFE_IS_ACTIVE) || \
908 defined(BSLS_REVIEW_VALIDATE_DISABLED_MACROS)
909 #define BSLS_REVIEW_SAFE_IS_USED
910#endif
911
912// Define 'BSLS_REVIEW_SAFE' accordingly.
913
914#if defined(BSLS_REVIEW_SAFE_IS_ACTIVE)
915 #define BSLS_REVIEW_SAFE(X) BSLS_REVIEW_REVIEW_IMP( \
916 X, \
917 BloombergLP::bsls::Review::k_LEVEL_SAFE)
918#else
919 #define BSLS_REVIEW_SAFE(X) BSLS_REVIEW_DISABLED_IMP( \
920 X, \
921 BloombergLP::bsls::Review::k_LEVEL_SAFE)
922#endif
923
924 // ===========
925 // BSLS_REVIEW
926 // ===========
927
928// Determine if 'BSLS_REVIEW' should be active.
929
930#if defined(BSLS_REVIEW_LEVEL_REVIEW_SAFE) || \
931 defined(BSLS_REVIEW_LEVEL_REVIEW) \
932 || BSLS_REVIEW_NO_REVIEW_MACROS_DEFINED && ( \
933 defined(BDE_BUILD_TARGET_SAFE_2) || \
934 defined(BDE_BUILD_TARGET_SAFE) || \
935 !defined(BDE_BUILD_TARGET_OPT) )
936
937 #define BSLS_REVIEW_IS_ACTIVE // also usable directly in client code
938#endif
939
940// Indicate when 'BSLS_REVIEW' arguments will be ODR-used.
941#if defined(BSLS_REVIEW_IS_ACTIVE) || \
942 defined(BSLS_REVIEW_VALIDATE_DISABLED_MACROS)
943 #define BSLS_REVIEW_IS_USED
944#endif
945
946// Define 'BSLS_REVIEW' accordingly.
947
948#if defined(BSLS_REVIEW_IS_ACTIVE)
949 #define BSLS_REVIEW(X) BSLS_REVIEW_REVIEW_IMP( \
950 X, \
951 BloombergLP::bsls::Review::k_LEVEL_REVIEW)
952#else
953 #define BSLS_REVIEW(X) BSLS_REVIEW_DISABLED_IMP( \
954 X, \
955 BloombergLP::bsls::Review::k_LEVEL_REVIEW)
956#endif
957
958 // ===============
959 // BSLS_REVIEW_OPT
960 // ===============
961
962// Determine if 'BSLS_REVIEW_OPT' should be active.
963
964#if !defined(BSLS_REVIEW_LEVEL_NONE)
965 #define BSLS_REVIEW_OPT_IS_ACTIVE // also usable directly in client code
966#endif
967
968// Indicate when 'BSLS_REVIEW_OPT' arguments will be ODR-used.
969#if defined(BSLS_REVIEW_OPT_IS_ACTIVE) || \
970 defined(BSLS_REVIEW_VALIDATE_DISABLED_MACROS)
971 #define BSLS_REVIEW_OPT_IS_USED
972#endif
973
974// Define 'BSLS_REVIEW_OPT' accordingly.
975
976#if defined(BSLS_REVIEW_OPT_IS_ACTIVE)
977 #define BSLS_REVIEW_OPT(X) BSLS_REVIEW_REVIEW_IMP( \
978 X, \
979 BloombergLP::bsls::Review::k_LEVEL_OPT)
980#else
981 #define BSLS_REVIEW_OPT(X) BSLS_REVIEW_DISABLED_IMP( \
982 X, \
983 BloombergLP::bsls::Review::k_LEVEL_OPT)
984#endif
985
986// A nested include guard is needed to support the test driver implementation.
987#ifndef BSLS_REVIEW_RECURSIVELY_INCLUDED_TESTDRIVER_GUARD
988#define BSLS_REVIEW_RECURSIVELY_INCLUDED_TESTDRIVER_GUARD
989
990
991namespace bsls {
992
993 // =====================
994 // class ReviewViolation
995 // =====================
996
997/// This class is an unconstrained *in-core* value-semantic class that
998/// characterizes the details of a review failure that has occurred.
999///
1000/// See @ref bsls_review
1002
1003 // DATA
1004 const char *d_comment_p; // the comment associated with the violation,
1005 // generally representing the expression that
1006 // failed
1007
1008 const char *d_fileName_p; // the name of the file where the violation
1009 // occurred
1010
1011 int d_lineNumber; // the line number where the violation
1012 // occurred
1013
1014 const char *d_reviewLevel_p; // the level and type of the violation that
1015 // occurred, generally one of the 'k_LEVEL'
1016 // constants defined in 'bsls::Review' or
1017 // 'bsls::Assert'
1018
1019 int d_count; // the number of times that a particular
1020 // failure has happened in the running
1021 // process
1022
1023 public:
1024 // CREATORS
1025
1026 /// Create a `ReviewViolation` with the specified `comment`, `fileName`,
1027 /// `lineNumber`, `reviewLevel`, and `count`. Note that the supplied
1028 /// `reviewLevel` will usually be one of the `k_LEVEL` constants defined
1029 /// in `bsls::Review` (or see `bsls::Assert` for the levels that will be
1030 /// passed for assertions that are being reviewed).
1032 ReviewViolation(const char *comment,
1033 const char *fileName,
1034 int lineNumber,
1035 const char *reviewLevel,
1036 int count);
1037
1038 // ACCESSORS
1039
1040 /// Return the `comment` attribute of this object.
1041 const char *comment() const;
1042
1043 /// Return the `count` attribute of this object.
1044 int count() const;
1045
1046 /// Return the `fileName` attribute of this object.
1047 const char *fileName() const;
1048
1049 /// Return the `lineNumber` attribute of this object.
1050 int lineNumber() const;
1051
1052 /// Return the `reviewLevel` attribute of this object.
1053 const char *reviewLevel() const;
1054};
1055
1056 // ============
1057 // class Review
1058 // ============
1059
1060/// This "utility" class maintains a pointer containing the address of the
1061/// current review-failure handler function (of type
1062/// `Review::ViolationHandler`) and provides methods to administer this
1063/// function pointer. The `invokeHandler` method calls the
1064/// currently-installed failure handler. The default installed handler is
1065/// the `Review::failByLog` function.
1066///
1067/// This class also provides a suite of standard failure-handler functions
1068/// that are suitable to be installed as the current
1069/// `Review::ViolationHandler` function. Note that clients are free to
1070/// install any of these ("off-the-shelf") handlers, or to provide their own
1071/// ("custom") review-failure handler function when using this facility.
1072/// Also note that review-failure handlers CAN return, unlike assertion
1073/// failure handlers, though not returning (thus escalating review behavior
1074/// implicitly to the level of asserts) is acceptable.
1075///
1076/// Finally, this class defines the constant strings that are used as the
1077/// `reviewLevel` in `ReviewViolation`s associated with failed `BSLS_REVIEW`
1078/// invocations.
1079///
1080/// See @ref bsls_review
1081class Review {
1082
1083 public:
1084 // TYPES
1085
1086 /// `Count` is an alias for an atomic integer. All @ref bsls_review macros
1087 /// declare a static local `Count` variable that is used to track how
1088 /// many times that review has failed. This count gets updated through
1089 /// the `bsls::Review::updateCount` function.
1090 typedef bsls::AtomicOperations::AtomicTypes::Int Count;
1091
1092 /// `ViolationHandler` is an alias for a pointer to a function returning
1093 /// `void`, and taking, as a parameter, a `const` reference to a
1094 /// `ReviewViolation` instance. For example:
1095 /// @code
1096 /// void myHandler(const ReviewViolation& violation);
1097 /// @endcode
1098 typedef void (*ViolationHandler)(const ReviewViolation&);
1099
1100 private:
1101 // FRIENDS
1103
1104 // PRIVATE CLASS METHODS
1105
1106 /// Make the specified handler `function` the current review-failure
1107 /// handler. This method has effect regardless of whether the
1108 /// `lockReviewAdministration` method has been called.
1109 static void setViolationHandlerRaw(Review::ViolationHandler function);
1110
1111 public:
1112 // PUBLIC CONSTANTS
1113
1114 // 'reviewLevel' Strings
1115
1116 static const char k_LEVEL_SAFE[];
1117 static const char k_LEVEL_OPT[];
1118 static const char k_LEVEL_REVIEW[];
1119 static const char k_LEVEL_INVOKE[];
1120
1121 // CLASS METHODS
1122
1123 // Administrative Methods
1124
1125 /// Make the specified handler `function` the current review-failure
1126 /// handler. This method has no effect if the
1127 /// `lockReviewAdministration` method has been called.
1129
1130 /// Return the address of the currently installed review-failure handler
1131 /// function. Note that the initial value of the review-failure handler
1132 /// is the `Review::failByLog` method.
1134
1135 /// Disable all subsequent calls to `setViolationHandler`. Note that
1136 /// this method has no effect on the behavior of a
1137 /// `ReviewFailureHandlerGuard` object.
1139
1140 // Dispatcher Methods (called from within macros)
1141
1142 /// Increment the specified `count` and return the new value. Instead
1143 /// of overflowing, when the value is sufficiently large, decrement the
1144 /// value so that large values repeat periodically.
1145 static int updateCount(Count *count);
1146
1147 /// Invoke the currently installed review-failure handler function with
1148 /// the specified `violation` as its argument. Note that this function
1149 /// is intended for use by the (BSLS) "REVIEW" macros, but may also be
1150 /// called by clients directly as needed.
1151 static void invokeHandler(const ReviewViolation& violation);
1152
1153#ifdef BSLS_ASSERT_USE_CONTRACTS
1154 static void invokeLanguageContractHandler(
1155 const std::contract_violation& violation);
1156 // Call 'invokeHandler' with a 'ReviewViolation' with properties from
1157 // the specified 'violation', tracking a 'count' of repeated violations
1158 // statically.
1159#endif
1160
1161 // Standard Review-Failure Handlers
1162
1163 /// Log a message to `stdout` that an assertion has failed with
1164 /// information on the failure from the specified `violation`. A
1165 /// suitably formatted "cheap stack" is included in the log message that
1166 /// identifies the call site where the failure occurred.
1167 static void failByLog(const ReviewViolation& violation);
1168
1169 /// Emulate the invocation of the standard `assert` macro with a `false`
1170 /// argument, using the specified `violation` to generate an output
1171 /// message and then, after logging, unconditionally abort.
1172 static void failByAbort(const ReviewViolation& violation);
1173
1174 /// Use the specified `violation` to generate an output message and
1175 /// then, after logging, spin in an infinite loop. Note that this
1176 /// handler function is useful for hanging a process so that a debugger
1177 /// may be attached to it.
1178 static void failBySleep(const ReviewViolation& violation);
1179
1180 /// Throw an `AssertTestException` (whose attributes are `comment`,
1181 /// `filename`, and `lineNumber` from the specified `violation`),
1182 /// provided that `BDE_BUILD_TARGET_EXC` is defined; otherwise, log an
1183 /// appropriate message and abort the program (similar to
1184 /// `failByAbort`).
1185 static void failByThrow(const ReviewViolation& violation);
1186};
1187
1188 // ===============================
1189 // class ReviewFailureHandlerGuard
1190 // ===============================
1191
1192/// An object of this class saves the current review handler and installs
1193/// the one specified on construction. On destruction, the original review
1194/// handler is restored. Note that two objects of this class cannot be
1195/// safely used concurrently from two separate threads (but may of course
1196/// appear sequentially, including in nested blocks and function invocations
1197/// within a single thread). Note that the behavior of objects of this
1198/// class is unaffected by the (`static`) `Review::lockReviewAdministration`
1199/// method (i.e., the temporary replacement will occur, regardless of
1200/// whether that method has been invoked).
1201///
1202/// See @ref bsls_review
1204
1205 // DATA
1206 Review::ViolationHandler d_original; // original (restored at destruction)
1207
1208 private:
1209 // NOT IMPLEMENTED
1212
1213 public:
1214 // CREATORS
1215
1216 /// Create a guard object that installs the specified `temporary` review
1217 /// failure handler and automatically restores the original handler on
1218 /// destruction.
1220
1221 /// Restore the failure handler that was in place when this object was
1222 /// created and destroy this guard.
1224};
1225
1226// ============================================================================
1227// INLINE FUNCTION DEFINITIONS
1228// ============================================================================
1229
1230 // ---------------------
1231 // class ReviewViolation
1232 // ---------------------
1233
1234// CREATORS
1236inline
1238 const char *fileName,
1239 int lineNumber,
1240 const char *reviewLevel,
1241 int count)
1242: d_comment_p((comment == 0) ? "" : comment)
1243, d_fileName_p((fileName == 0) ? "" : fileName)
1244, d_lineNumber(lineNumber)
1245, d_reviewLevel_p((reviewLevel == 0) ? "" : reviewLevel)
1246, d_count(count)
1247{
1248}
1249
1250// ACCESSORS
1251inline
1252const char *ReviewViolation::comment() const
1253{
1254 return d_comment_p;
1255}
1256
1257inline
1259{
1260 return d_count;
1261}
1262
1263inline
1264const char *ReviewViolation::fileName() const
1265{
1266 return d_fileName_p;
1267}
1268
1269inline
1271{
1272 return d_lineNumber;
1273}
1274
1275inline
1277{
1278 return d_reviewLevel_p;
1279}
1280
1281} // close package namespace
1282
1283
1284#endif // deeper include guard
1285
1286 // ========================================================
1287 // UNDEFINE THE LOCALLY-SCOPED IMPLEMENTATION DETAIL MACROS
1288 // ========================================================
1289
1290#undef BSLS_REVIEW_NO_REVIEW_MACROS_DEFINED
1291
1292 // =========================================
1293 // IMPLEMENTATION USING THE C++ PREPROCESSOR
1294 // =========================================
1295//
1296// At most one of the following review levels may be set during the compilation
1297// of any component that includes 'bsls_review.h':
1298//..
1299// BSLS_REVIEW_LEVEL_REVIEW_SAFE
1300// BSLS_REVIEW_LEVEL_REVIEW
1301// BSLS_REVIEW_LEVEL_REVIEW_OPT
1302// BSLS_REVIEW_LEVEL_NONE
1303//..
1304// ----------------------------------------------------------------------------
1305
1306#if defined(BSLS_REVIEW_LEVEL_REVIEW_SAFE) && \
1307 defined(BSLS_REVIEW_LEVEL_REVIEW)
1308#error incompatible BSLS_REVIEW levels: \
1309..._LEVEL_REVIEW_SAFE and ..._LEVEL_REVIEW
1310#endif
1311
1312#if defined(BSLS_REVIEW_LEVEL_REVIEW_SAFE) && \
1313 defined(BSLS_REVIEW_LEVEL_REVIEW_OPT)
1314#error incompatible BSLS_REVIEW levels: \
1315..._LEVEL_REVIEW_SAFE and ..._LEVEL_REVIEW_OPT
1316#endif
1317
1318#if defined(BSLS_REVIEW_LEVEL_REVIEW_SAFE) && \
1319 defined(BSLS_REVIEW_LEVEL_NONE)
1320#error incompatible BSLS_REVIEW levels: \
1321..._LEVEL_REVIEW_SAFE and ..._LEVEL_NONE
1322#endif
1323
1324#if defined(BSLS_REVIEW_LEVEL_REVIEW) && \
1325 defined(BSLS_REVIEW_LEVEL_REVIEW_OPT)
1326#error incompatible BSLS_REVIEW levels: \
1327..._LEVEL_REVIEW and ..._LEVEL_REVIEW_OPT
1328#endif
1329
1330#if defined(BSLS_REVIEW_LEVEL_REVIEW) && \
1331 defined(BSLS_REVIEW_LEVEL_NONE)
1332#error incompatible BSLS_REVIEW levels: \
1333..._LEVEL_REVIEW and ..._LEVEL_NONE
1334#endif
1335
1336#if defined(BSLS_REVIEW_LEVEL_REVIEW_OPT) && \
1337 defined(BSLS_REVIEW_LEVEL_NONE)
1338#error incompatible BSLS_REVIEW levels: \
1339..._LEVEL_REVIEW_OPT and ..._LEVEL_NONE
1340#endif
1341
1342// At most one of the following assert levels may be set during the compilation
1343// of any component that includes 'bsls_review.h' (this is redundant with
1344// checks in 'bsls_assert.h', but we want to be sure these are checked even for
1345// users including only this header):
1346//..
1347// BSLS_ASSERT_LEVEL_ASSERT_SAFE
1348// BSLS_ASSERT_LEVEL_ASSERT
1349// BSLS_ASSERT_LEVEL_ASSERT_OPT
1350// BSLS_ASSERT_LEVEL_NONE
1351// BSLS_ASSERT_LEVEL_ASSUME_SAFE
1352// BSLS_ASSERT_LEVEL_ASSUME_ASSERT
1353// BSLS_ASSERT_LEVEL_ASSUME_OPT
1354//..
1355// ----------------------------------------------------------------------------
1356
1357#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) && \
1358 defined(BSLS_ASSERT_LEVEL_ASSERT)
1359#error incompatible BSLS_ASSERT levels: \
1360..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSERT
1361#endif
1362
1363#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) && \
1364 defined(BSLS_ASSERT_LEVEL_ASSERT_OPT)
1365#error incompatible BSLS_ASSERT levels: \
1366..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSERT_OPT
1367#endif
1368
1369#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) && \
1370 defined(BSLS_ASSERT_LEVEL_NONE)
1371#error incompatible BSLS_ASSERT levels: \
1372..._LEVEL_ASSERT_SAFE and ..._LEVEL_NONE
1373#endif
1374
1375#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) && \
1376 defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)
1377#error incompatible BSLS_ASSERT levels: \
1378..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSUME_OPT
1379#endif
1380
1381#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) && \
1382 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
1383#error incompatible BSLS_ASSERT levels: \
1384..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSUME_ASSERT
1385#endif
1386
1387#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) && \
1388 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
1389#error incompatible BSLS_ASSERT levels: \
1390..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSUME_SAFE
1391#endif
1392
1393#if defined(BSLS_ASSERT_LEVEL_ASSERT) && \
1394 defined(BSLS_ASSERT_LEVEL_ASSERT_OPT)
1395#error incompatible BSLS_ASSERT levels: \
1396..._LEVEL_ASSERT and ..._LEVEL_ASSERT_OPT
1397#endif
1398
1399#if defined(BSLS_ASSERT_LEVEL_ASSERT) && \
1400 defined(BSLS_ASSERT_LEVEL_NONE)
1401#error incompatible BSLS_ASSERT levels: \
1402..._LEVEL_ASSERT and ..._LEVEL_NONE
1403#endif
1404
1405#if defined(BSLS_ASSERT_LEVEL_ASSERT) && \
1406 defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)
1407#error incompatible BSLS_ASSERT levels: \
1408..._LEVEL_ASSERT and ..._LEVEL_ASSUME_OPT
1409#endif
1410
1411#if defined(BSLS_ASSERT_LEVEL_ASSERT) && \
1412 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
1413#error incompatible BSLS_ASSERT levels: \
1414..._LEVEL_ASSERT and ..._LEVEL_ASSUME_ASSERT
1415#endif
1416
1417#if defined(BSLS_ASSERT_LEVEL_ASSERT) && \
1418 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
1419#error incompatible BSLS_ASSERT levels: \
1420..._LEVEL_ASSERT and ..._LEVEL_ASSUME_SAFE
1421#endif
1422
1423#if defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) && \
1424 defined(BSLS_ASSERT_LEVEL_NONE)
1425#error incompatible BSLS_ASSERT levels: \
1426..._LEVEL_ASSERT_OPT and ..._LEVEL_NONE
1427#endif
1428
1429#if defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) && \
1430 defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)
1431#error incompatible BSLS_ASSERT levels: \
1432..._LEVEL_ASSERT_OPT and ..._LEVEL_ASSUME_OPT
1433#endif
1434
1435#if defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) && \
1436 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
1437#error incompatible BSLS_ASSERT levels: \
1438..._LEVEL_ASSERT_OPT and ..._LEVEL_ASSUME_ASSERT
1439#endif
1440
1441#if defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) && \
1442 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
1443#error incompatible BSLS_ASSERT levels: \
1444..._LEVEL_ASSERT_OPT and ..._LEVEL_ASSUME_SAFE
1445#endif
1446
1447#if defined(BSLS_ASSERT_LEVEL_NONE) && \
1448 defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)
1449#error incompatible BSLS_ASSERT levels: \
1450..._LEVEL_NONE and ..._LEVEL_ASSUME_OPT
1451#endif
1452
1453#if defined(BSLS_ASSERT_LEVEL_NONE) && \
1454 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
1455#error incompatible BSLS_ASSERT levels: \
1456..._LEVEL_NONE and ..._LEVEL_ASSUME_ASSERT
1457#endif
1458
1459#if defined(BSLS_ASSERT_LEVEL_NONE) && \
1460 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
1461#error incompatible BSLS_ASSERT levels: \
1462..._LEVEL_NONE and ..._LEVEL_ASSUME_SAFE
1463#endif
1464
1465#if defined(BSLS_ASSERT_LEVEL_ASSUME_OPT) && \
1466 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
1467#error incompatible BSLS_ASSERT levels: \
1468..._LEVEL_ASSUME_OPT and ..._LEVEL_ASSUME_ASSERT
1469#endif
1470
1471#if defined(BSLS_ASSERT_LEVEL_ASSUME_OPT) && \
1472 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
1473#error incompatible BSLS_ASSERT levels: \
1474..._LEVEL_ASSUME_OPT and ..._LEVEL_ASSUME_SAFE
1475#endif
1476
1477#if defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT) && \
1478 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
1479#error incompatible BSLS_ASSERT levels: \
1480..._LEVEL_ASSUME_ASSERT and ..._LEVEL_ASSUME_SAFE
1481#endif
1482
1483#endif
1484
1485// ----------------------------------------------------------------------------
1486// Copyright 2018 Bloomberg Finance L.P.
1487//
1488// Licensed under the Apache License, Version 2.0 (the "License");
1489// you may not use this file except in compliance with the License.
1490// You may obtain a copy of the License at
1491//
1492// http://www.apache.org/licenses/LICENSE-2.0
1493//
1494// Unless required by applicable law or agreed to in writing, software
1495// distributed under the License is distributed on an "AS IS" BASIS,
1496// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1497// See the License for the specific language governing permissions and
1498// limitations under the License.
1499// ----------------------------- END-OF-FILE ----------------------------------
1500
1501/** @} */
1502/** @} */
1503/** @} */
Definition bsls_review.h:1203
ReviewFailureHandlerGuard(Review::ViolationHandler temporary)
Definition bsls_review.h:1001
BSLS_KEYWORD_CONSTEXPR ReviewViolation(const char *comment, const char *fileName, int lineNumber, const char *reviewLevel, int count)
Definition bsls_review.h:1237
int lineNumber() const
Return the lineNumber attribute of this object.
Definition bsls_review.h:1270
int count() const
Return the count attribute of this object.
Definition bsls_review.h:1258
const char * reviewLevel() const
Return the reviewLevel attribute of this object.
Definition bsls_review.h:1276
const char * fileName() const
Return the fileName attribute of this object.
Definition bsls_review.h:1264
const char * comment() const
Return the comment attribute of this object.
Definition bsls_review.h:1252
Definition bsls_review.h:1081
static Review::ViolationHandler violationHandler()
static const char k_LEVEL_REVIEW[]
Definition bsls_review.h:1118
static void setViolationHandler(Review::ViolationHandler function)
static void failByThrow(const ReviewViolation &violation)
static int updateCount(Count *count)
static const char k_LEVEL_OPT[]
Definition bsls_review.h:1117
static void failByAbort(const ReviewViolation &violation)
bsls::AtomicOperations::AtomicTypes::Int Count
Definition bsls_review.h:1090
static void failByLog(const ReviewViolation &violation)
static const char k_LEVEL_SAFE[]
Definition bsls_review.h:1116
static void invokeHandler(const ReviewViolation &violation)
void(* ViolationHandler)(const ReviewViolation &)
Definition bsls_review.h:1098
static void failBySleep(const ReviewViolation &violation)
static void lockReviewAdministration()
static const char k_LEVEL_INVOKE[]
Definition bsls_review.h:1119
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_CONSTEXPR
Definition bsls_keyword.h:588
Definition bdlt_iso8601util.h:691