BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_assert.h
Go to the documentation of this file.
1/// @file bsls_assert.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_assert.h -*-C++-*-
8#ifndef INCLUDED_BSLS_ASSERT
9#define INCLUDED_BSLS_ASSERT
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_assert bsls_assert
15/// @brief Provide build-specific, runtime-configurable assertion macros.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_assert
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_assert-purpose"> Purpose</a>
25/// * <a href="#bsls_assert-classes"> Classes </a>
26/// * <a href="#bsls_assert-macros"> Macros </a>
27/// * <a href="#bsls_assert-description"> Description </a>
28/// * <a href="#bsls_assert-defensive-programming"> Defensive Programming (DP) </a>
29/// * <a href="#bsls_assert-assertion-semantics"> Assertion Semantics </a>
30/// * <a href="#bsls_assert-assertion-modes"> Assertion Modes </a>
31/// * <a href="#bsls_assert-review-mode"> Review Mode </a>
32/// * <a href="#bsls_assert-detailed-behavior"> Detailed Behavior </a>
33/// * <a href="#bsls_assert-selecting-which-assert-macro-to-use"> Selecting Which ASSERT Macro to Use </a>
34/// * <a href="#bsls_assert-assertion-and-review-levels"> Assertion and Review Levels </a>
35/// * <a href="#bsls_assert-runtime-configurable-assertion-failure-behavior"> Runtime-Configurable Assertion-Failure Behavior </a>
36/// * <a href="#bsls_assert-exception-throwing-failure-handlers-and-bsls-assertfailurehandlerguard"> Exception-Throwing Failure Handlers and bsls::AssertFailureHandlerGuard </a>
37/// * <a href="#bsls_assert-assertion-handler-policy"> Assertion Handler Policy </a>
38/// * <a href="#bsls_assert-configuring-an-exception-to-the-assertion-handler-policy"> Configuring an Exception to the Assertion Handler Policy </a>
39/// * <a href="#bsls_assert-legacy-handler-functions"> Legacy Handler Functions </a>
40/// * <a href="#bsls_assert-assertions-in-header-files"> Assertions in Header Files (Mixing Build Options Across Translation Units) </a>
41/// * <a href="#bsls_assert-conditional-compilation"> Conditional Compilation </a>
42/// * <a href="#bsls_assert-validating-disabled-macro-expressions"> Validating Disabled Macro Expressions </a>
43/// * <a href="#bsls_assert-language-level-contracts"> Language-Level Contracts </a>
44/// * <a href="#bsls_assert-usage"> Usage </a>
45/// * <a href="#bsls_assert-example-1-using-bsls_assert-bsls_assert_safe-and-bsls_assert_opt"> Example 1: Using BSLS_ASSERT, BSLS_ASSERT_SAFE, and BSLS_ASSERT_OPT </a>
46/// * <a href="#bsls_assert-example-2-when-and-how-to-call-the-invokehandler-method-directly"> Example 2: When and How to Call the invokeHandler Method Directly </a>
47/// * <a href="#bsls_assert-example-3-runtime-configuration-of-the-bsls-assert-facility"> Example 3: Runtime Configuration of the bsls::Assert Facility </a>
48/// * <a href="#bsls_assert-example-4-creating-a-custom-assertion-handler"> Example 4: Creating a Custom Assertion Handler </a>
49/// * <a href="#bsls_assert-example-5-using-the-bsls-assertfailurehandlerguard"> Example 5: Using the bsls::AssertFailureHandlerGuard </a>
50/// * <a href="#bsls_assert-example-6-using-assert-macros-along-with-bde_build_target_safe_2"> Example 6: Using (BSLS) "ASSERT" Macros Along With BDE_BUILD_TARGET_SAFE_2 </a>
51/// * <a href="#bsls_assert-example-7-conditional-compilation-associated-with-enabled-assertion-levels"> Example 7: Conditional Compilation Associated with Enabled Assertion Levels </a>
52/// * <a href="#bsls_assert-example-8-conditional-compilation-of-support-functions"> Example 8: Conditional Compilation of Support Functions </a>
53/// * <a href="#bsls_assert-example-9-conditional-compilation-of-support-code"> Example 9: Conditional Compilation of Support Code </a>
54///
55/// # Purpose {#bsls_assert-purpose}
56/// Provide build-specific, runtime-configurable assertion macros.
57///
58/// # Classes {#bsls_assert-classes}
59///
60/// - bsls::Assert: namespace for "assert" management functions
61/// - bsls::AssertFailureHandlerGuard: scoped guard for changing handlers safely
62/// - bsls::AssertViolation: attributes describing a failed assertion
63///
64/// # Macros {#bsls_assert-macros}
65///
66/// - BSLS_ASSERT: runtime check typically enabled in non-opt build modes
67/// - BSLS_ASSERT_SAFE: runtime check typically only enabled in safe build modes
68/// - BSLS_ASSERT_OPT: runtime check typically enabled in all build modes
69/// - BSLS_ASSERT_INVOKE: for directly invoking the current failure handler
70/// - BSLS_ASSERT_INVOKE_NORETURN: direct invocation always marked to not return
71///
72/// @see bsls_review, bsls_asserttest
73///
74/// # Description {#bsls_assert-description}
75/// This component provides three "assert-like" macros,
76/// `BSLS_ASSERT`, `BSLS_ASSERT_SAFE`, and `BSLS_ASSERT_OPT`, that can be used
77/// to enable optional *redundant* runtime checks in corresponding build modes.
78/// If an assertion argument evaluates to 0, a runtime-configurable "handler"
79/// function is invoked with a `bsls::AssertViolation`, a value-semantic class
80/// that encapsulates the current filename, line number, level of failed check,
81/// and (0-valued expression) argument text.
82///
83/// The class `bsls::Assert` provides functions for manipulating the globally
84/// configured "handler". A scoped guard for setting and restoring the assert
85/// handler is provided by `bsls::AssertFailureHandlerGuard`.
86///
87/// An additional macro, `BSLS_ASSERT_INVOKE`, is provided for direct invocation
88/// of the current assertion failure handler. This macro is always enabled
89/// (i.e., regardless of build mode).
90///
91/// ## Defensive Programming (DP) {#bsls_assert-defensive-programming}
92///
93///
94/// Although there is no one agreed-upon definition, in this context we will use
95/// the term *Defensive* *Programming* (DP) to mean any attempt by the component
96/// author to provide (optional) runtime validation of the preconditions (or
97/// invariants) defined in the function-level documentation (contract) for that
98/// component. Note that DP is intended to help expose defects early in the
99/// development process, and *never* to mask or recover from them in production.
100///
101/// Calling a function without satisfying its preconditions results in
102/// *undefined* *behavior*. Detecting and reporting undefined behavior due to
103/// client misuse can sometimes be very helpful at identifying subtle errors.
104/// Additionally, we may choose to embed redundant (i.e., logically superfluous)
105/// runtime checks -- both as a form of active documentation, and also to help
106/// expose our own, latent coding errors that have escaped detection during
107/// testing. In either case, these *defensive* (and other) runtime checks can
108/// add significant overhead. Hence, this extra runtime overhead should not
109/// necessarily be incorporated for every build target and assertion mode (see
110/// "Build Modes" below). Moreover, the extent of these checks may change
111/// (i.e., for a particular build mode) from one release to the next.
112/// Therefore, any defensive (or other redundant) checks provided for a
113/// particular build mode are *NEVER* part of the function-level contract -- and
114/// remain solely what is known as a *Quality-of-Implementation* (QoI) issue.
115///
116/// ## Assertion Semantics {#bsls_assert-assertion-semantics}
117///
118///
119/// There are three important aspects of assertions: (1) **Every** **assertion**
120/// **is** **redundant**; it is essential that if all assertions are compiled out of
121/// a program that is defect-free, apart from improved runtime performance, the
122/// program behaves identically. Hence, (2) **each** !boolean-valued! **assert**
123/// **argument** **must** **have** **no** !side-effects!. Finally, (3) **assertions**
124/// **do** **not** **affect** **binary** **compatibility**; hence, translation units with
125/// different assertion levels (but not necessarily build targets) can safely be
126/// combined into a single program (see "Build Modes" and "Assertions in Header
127/// Files" below). Note that the build target `BDE_BUILD_TARGET_SAFE_2` does
128/// permit binary incompatibility for conditionally compiled source code, but
129/// there is no corresponding `BSLS_ASSERT_SAFE_2` assertion macro (see {Usage}
130/// below).
131///
132/// ## Assertion Modes {#bsls_assert-assertion-modes}
133///
134///
135/// Depending on the build, assertion macros can expand in 3 different ways:
136///
137/// 1. A @ref bsls_assert macro is "enabled in assert mode", or simply "enabled" if
138/// it expands to check its predicate and call the assert failure handler
139/// when it is false.
140/// 2. A @ref bsls_assert macro is "enabled in review mode", or simply "in review
141/// mode" if it expands to check its predicate and call the *review* failure
142/// handler when it is false. This is identical to a @ref bsls_review macro of
143/// the same level when it is enabled.
144/// 3. A @ref bsls_assert macro is "disabled" if it expands to do nothing,
145/// producing no executed code in the compiled program.
146///
147/// ## Review Mode {#bsls_assert-review-mode}
148///
149///
150/// The ability to enable assertions in review mode allows clients to easily and
151/// safely test, in a production environment, whether assertions having a lower
152/// threshold than what they currently have deployed are being triggered
153/// (without terminating the application). It is intended as an interim step
154/// towards lowering the assertion level threshold for an existing application.
155/// See @ref bsls_review for a more detailed description of the behavior of
156/// assertions in review mode and suggested workflows for using this behavior.
157///
158/// ## Detailed Behavior {#bsls_assert-detailed-behavior}
159///
160///
161/// If an assertion fires (i.e., due to a 0-valued expression argument in an
162/// assert macro that is enabled or in review mode), there is a violation of the
163/// contract that the assertion is checking. If the assertion is enabled, the
164/// goal of the assertion is to report the precise location and nature of the
165/// defect *quickly* and *loudly* and prevent continued execution of the calling
166/// function past that point. If the assertion is in review mode then the
167/// behavior will match the corresponding @ref bsls_review macro and execution
168/// might continue, which has a priority of just logging the failure location.
169///
170/// When enabled, the assert macros will all do essentially the same thing: Each
171/// macro tests the predicate expression `X`, and if `!(X)` is `true`, invokes
172/// the currently installed assertion failure handler. An instance of
173/// `bsls::AssertViolation` will be created and populated with a textual
174/// rendering of the predicate (`#X`), the current `__FILE__`, the current
175/// `__LINE__`, and a string representing which particular type of assertion has
176/// failed. This `violation` is then passed to the currently installed
177/// assertion failure handler (a function pointer with the type
178/// `bsls::Assert::ViolationHandler` having the signature:
179/// @code
180/// void(const bsls::AssertViolation&);
181/// @endcode
182///
183/// On some (currently experimental) platforms with support for some form of the
184/// upcoming language-level contract facilities there is also the ability to
185/// configure the assertion macros to introduce an assumption of the truth of
186/// their predicate. With this option the predicate will not neccesarily even
187/// be evaluated, and if it were to return false the compiler will treat the
188/// situation as undefined behavior ("impossible"). This mode for assertions
189/// can lead to improved code generation, but be aware that the potential
190/// downside of being wrong about the truth of your assertions is unbounded, and
191/// so deploying applications built with any assertions assumed should be done
192/// with great care - there are no guarantees about anything a program will do
193/// when an assumed assertion is violated.
194///
195/// ## Selecting Which ASSERT Macro to Use {#bsls_assert-selecting-which-assert-macro-to-use}
196///
197///
198/// The choice of which specific macro to use is governed primarily by the
199/// impact that enabling the assertion (in either assert mode or review mode)
200/// will have on the runtime performance of the function, and in some cases on
201/// the size of the function.
202///
203/// 1. BSLS_ASSERT_SAFE - This macro should be reserved for tests incurring an
204/// expensive change to the performance of a function, either a very high
205/// constant time increase in execution time of the function, or an increase
206/// in the algorithmic complexity of a function. Note especially that a
207/// change in algorithmic complexity breaks the documented contract of many
208/// functions (e.g., an `O(n)` check in a function with a documented
209/// `O(log(n))` runtime speed) and so checks with that level of cost should
210/// be reserved for diagnostic use in "safe" builds.
211/// 2. BSLS_ASSERT - For "inexpensive" checks with only a constant factor
212/// overhead. The majority of checks should fall into this category.
213/// 3. BSLS_ASSERT_OPT - For "negligible" checks that have little to no
214/// measurable overhead on a function. This will often be the case for
215/// argument checking in larger functions, or very simple checks in smaller
216/// functions. Keep in mind that these checks will be enabled in all
217/// typically deployed build modes, so they should be reserved for larger
218/// functions and functions that will not be called in highly performance
219/// critical code.
220///
221/// ## Assertion and Review Levels {#bsls_assert-assertion-and-review-levels}
222///
223///
224/// There are a few macros available to control which of the @ref bsls_assert
225/// macros are disabled, enabled in review mode, or enabled in assert mode (see
226/// {Assertion Modes} above). These macros are for the compilation and build
227/// environment to provide and are not themselves defined by BDE code -- e.g.,
228/// by supplying one or more of these macros with `-D` options on the compiler
229/// command line. In general, these macros are used to determine an
230/// `ASSERT_LEVEL` that can be (from most aggressive/optimized to safest)
231/// `ASSUME_SAFE`, `ASSUME_ASSERT`, `ASSUME_OPT`, `NONE`, `ASSERT_OPT`,
232/// `ASSERT`, or `ASSERT_SAFE`. Separately, a `REVIEW_LEVEL` is determined that
233/// can be `NONE`, `REVIEW_OPT`, `REVIEW`, or `REVIEW_SAFE`. Depending on these
234/// levels, the various @ref bsls_assert macros will be enabled, in review mode,
235/// assumed, or disabled. Macros up to the assert level will be enabled. If
236/// the review level is higher than the assert level then macros up to the
237/// review level (and above the assert level) will be enabled in review mode.
238/// Finally, macros higher than both the review level and the assert level will
239/// be disabled. If the review level is `NONE` and the assert level is set to
240/// one of the assume levels, then macros that would be disabled up to the
241/// assumed level are instead assumed. If there is a review level set then no
242/// macros will ever be assumed. The following table illustrates this:
243/// @code
244/// ===========================================
245/// Macro Instantiation Based on Review Level
246/// ===========================================
247/// ENABLED - Assertion is enabled (in "assert mode")
248/// REVIEW - Assertion is enabled (in "review mode")
249/// ASSUMED - Assertion is assumed (if supported)
250/// <blank> - Assertion is ignored
251/// -----------BSLS... LEVELS---------- ----------BSLS_.. MACROS---------
252/// BSLS_ASSERT_LEVEL BSLS_REVIEW_LEVEL ASSERT_OPT ASSERT ASSERT_SAFE
253/// ----------------- ----------------- ---------- ---------- -----------
254/// ASSUME_SAFE NONE ASSUMED ASSUMED ASSUMED
255/// ASSUME_ASSERT NONE ASSUMED ASSUMED
256/// ASSUME_OPT NONE ASSUMED
257/// NONE NONE
258/// NONE (or ASSUME*) REVIEW_OPT REVIEW
259/// NONE (or ASSUME*) REVIEW REVIEW REVIEW
260/// NONE (or ASSUME*) REVIEW_SAFE REVIEW REVIEW REVIEW
261/// ASSERT_OPT NONE ENABLED
262/// ASSERT_OPT REVIEW_OPT ENABLED
263/// ASSERT_OPT REVIEW ENABLED REVIEW
264/// ASSERT_OPT REVIEW_SAFE ENABLED REVIEW REVIEW
265/// ASSERT NONE ENABLED ENABLED
266/// ASSERT REVIEW_OPT ENABLED ENABLED
267/// ASSERT REVIEW ENABLED ENABLED
268/// ASSERT REVIEW_SAFE ENABLED ENABLED REVIEW
269/// ASSERT_SAFE NONE ENABLED ENABLED ENABLED
270/// ASSERT_SAFE REVIEW_OPT ENABLED ENABLED ENABLED
271/// ASSERT_SAFE REVIEW ENABLED ENABLED ENABLED
272/// ASSERT_SAFE REVIEW_SAFE ENABLED ENABLED ENABLED
273/// @endcode
274/// See @ref bsls_review for the logic that determines the review level. The
275/// logic that determines the assertion level checks a few different macros.
276/// The first check is for one of the 7 mutually exclusive `BSLS_ASSERT_LEVEL`
277/// macros that can explicitly set the assert level:
278/// @code
279/// MACRO BSLS_ASSERT_LEVEL
280/// ----- ----------------
281/// BSLS_ASSERT_LEVEL_ASSUME_SAFE ASSUME_SAFE
282/// BSLS_ASSERT_LEVEL_ASSUME_ASSERT ASSUME_ASSERT
283/// BSLS_ASSERT_LEVEL_ASSUME_OPT ASSUME_OPT
284/// BSLS_ASSERT_LEVEL_NONE NONE
285/// BSLS_ASSERT_LEVEL_ASSERT_OPT ASSERT_OPT
286/// BSLS_ASSERT_LEVEL_ASSERT ASSERT
287/// BSLS_ASSERT_LEVEL_ASSERT_SAFE ASSERT_SAFE
288/// @endcode
289/// If none of these are defined, the assert level is determined by the build
290/// mode. With "safer" build modes we incorporate higher level defensive
291/// checks. A particular build mode is implied by the relevant (BDE) build
292/// targets that are defined at compilation (preprocessing) time. The following
293/// table shows the three (BDE) build targets that can affect the assertion and
294/// review levels:
295/// @code
296/// (BDE) Build Targets
297/// -----------------------
298/// (A) BDE_BUILD_TARGET_SAFE_2
299/// (B) BDE_BUILD_TARGET_SAFE
300/// (C) BDE_BUILD_TARGET_OPT
301/// @endcode
302/// *Any* of the 8 possible combinations of the three build targets is valid:
303/// e.g., `BDE_BUILD_TARGET_OPT` and `BDE_BUILD_TARGET_SAFE_2` may both be
304/// defined. The following table shows the assert level that is set depending
305/// on which combination of build target macros have been set:
306/// @code
307/// =========================================================
308/// "ASSERT" Level Set With no Level-Overriding Flags defined
309/// =========================================================
310/// --- BDE_BUILD_TARGET ---- BSLS_ASSERT_LEVEL
311/// _SAFE_2 _SAFE _OPT
312/// ------- ------- ------- -----------------
313/// ASSERT
314/// DEFINED ASSERT_OPT
315/// DEFINED ASSERT_SAFE
316/// DEFINED DEFINED ASSERT_SAFE
317/// DEFINED ASSERT_SAFE
318/// DEFINED DEFINED ASSERT_SAFE
319/// DEFINED DEFINED ASSERT_SAFE
320/// DEFINED DEFINED DEFINED ASSERT_SAFE
321/// @endcode
322/// As the table above illustrates, with no build target explicitly defined the
323/// assert level defaults to `ASSERT`. If only `BDE_BUILD_TARGET_OPT` is
324/// defined, the assert level will be set to `ASSERT_OPT`. If either
325/// `BDE_BUILD_TARGET_SAFE` or `BDE_BUILD_TARGET_SAFE_2` is defined then the
326/// assert level is set to `ASSERT_SAFE` and ALL assert macros will be enabled.
327///
328/// ## Runtime-Configurable Assertion-Failure Behavior {#bsls_assert-runtime-configurable-assertion-failure-behavior}
329///
330///
331/// In addition to the three (BSLS) "ASSERT" macros, `BSLS_ASSERT`,
332/// `BSLS_ASSERT_SAFE`, and `BSLS_ASSERT_OPT`, and the immediate invocation
333/// macro `BSLS_ASSERT_INVOKE`, this component provides (1) an `invokeHandler`
334/// method used (primarily) to implement these "ASSERT" macros and enable their
335/// runtime configuration, (2) administration methods to configure, at runtime,
336/// the behavior resulting from an assertion failure (i.e., by installing an
337/// appropriate assertion-failure handler function), and (3) a suite of standard
338/// ("off-the-shelf") assertion-failure handler functions, to be installed via
339/// the administrative methods (if desired), and invoked by the `invokeHandler`
340/// method on an assertion failure.
341///
342/// When an enabled assertion fails, the currently installed *failure* *handler*
343/// ("callback") function is invoked. The default handler is the (`static`)
344/// `bsls::Assert::failByAbort` method; a user may replace this default handler
345/// by using the (`static`) `bsls::Assert::setViolationHandler` administrative
346/// method and passing it (the address of) a function whose signature conforms
347/// to the `bsls::Assert::ViolationHandler` `typedef`. This handler may be one
348/// of the other handler methods provided in `bsls::Assert`, or a new "custom"
349/// function, written by the user (see {Usage} below).
350///
351/// ## Exception-Throwing Failure Handlers and bsls::AssertFailureHandlerGuard {#bsls_assert-exception-throwing-failure-handlers-and-bsls-assertfailurehandlerguard}
352///
353///
354/// Among the failure handlers provided is `bsls::Assert::failByThrow`, which
355/// throws a `bsls::AssertTestException` object. Throwing an exception,
356/// however, is not safe in all environments and deliberately aborting is more
357/// useful in a debugging context than throwing an unhandled exception. Hence,
358/// in order for an `bsls::AssertTestException` object to be thrown on an
359/// assertion failure, the user must first install the
360/// `bsls::Assert::failByThrow` handler (or another exception-throwing handler)
361/// explicitly.
362///
363/// Note that an object of type `bsls::AssertFailureHandlerGuard` can be used to
364/// temporarily set an exception-throwing handler within a `try` block,
365/// automatically restoring the previous handler when the `try` block exits (see
366/// {Usage} below).
367///
368/// ## Assertion Handler Policy {#bsls_assert-assertion-handler-policy}
369///
370///
371/// Bloomberg policy is that (by default) tasks may not install an assertion
372/// handler that returns control to the point immediately following the
373/// detection of a failed assertion. So an assertion handler may, for example,
374/// terminate the task or throw an exception, but may not log the problem and
375/// return. @ref bsls_assert , by default, enforces that policy by terminating the
376/// task if an installed assertion handler function chooses to returns normally.
377///
378/// ### Configuring an Exception to the Assertion Handler Policy {#bsls_assert-configuring-an-exception-to-the-assertion-handler-policy}
379///
380///
381/// @ref bsls_assert provides a two-part mechanism to permit returning after the
382/// detection of failed assertions.
383///
384/// It is a violation of Bloomberg policy to modify this default configuration
385/// without permission from senior management. (Internal Bloomberg users should
386/// contact the BDE team if you feel your application needs an exception to this
387/// policy).
388///
389/// The intention is to provide a means to override the assertion failure policy
390/// that can be enabled quickly, but requires the explicit (and obvious) choice
391/// from both the owner of the application's `main` function, and the person
392/// responsible for building the application. In order to enable a policy
393/// exception, `permitOutOfPolicyReturningFailureHandler` must be called, and
394/// the task must be linked with a special build of `bsls_assert.o` (in which
395/// the `k_permitOutOfPolicyReturningAssertionBuildKey` constant has the value
396/// "bsls-PermitOutOfPolicyReturn").
397///
398/// ## Legacy Handler Functions {#bsls_assert-legacy-handler-functions}
399///
400///
401/// Prior to the introduction of `bsls::AssertViolation`, the signature for
402/// `bsls::Assert::ViolationHandler` was this:
403/// @code
404/// void(const char*, const char*,int)
405/// @endcode
406/// This signature for a handler is still supported (though deprecated) under
407/// its original name `bsls::Assert::Handler`. Overloads that take a
408/// `bsls::Assert::Handler` exist for `bsls::AssertFailureHandler` and the
409/// constructor for `bsls::AssertFailureHandlerGuard`, so code that uses the old
410/// handler signature should work without changes.
411///
412/// If a legacy handler is set as the current handler, the function
413/// `bsls::Assert::failureHandler()` will return a pointer to that function,
414/// while `bsls::Assert::violationHandler()` will return an internal function
415/// that extracts the appropriate arguments from the generated
416/// `bsls::AssertViolation` object and passes them to the installed `Handler`.
417///
418/// ## Assertions in Header Files (Mixing Build Options Across Translation Units) {#bsls_assert-assertions-in-header-files}
419///
420///
421/// Mixing build modes across translation units, although not strictly
422/// conformant with the C++ language standard, is permissible in practice;
423/// however, the defensive checks that are enabled may be unpredictable. The
424/// *one-definition* *rule* states that if there are multiple definitions of an
425/// object or function within a program, these definitions *must* be identical
426/// or else the program is *ill-formed*. Unfortunately, definitions in header
427/// files may not be identical across object (`.o`) files if the build targets
428/// or assertion-level flags defined during translation (preprocessing) are not
429/// the same.
430///
431/// For example, consider an `inline` function that sets the width of a `Square`
432/// and optionally checks for (defends against) a negative `width` argument:
433/// @code
434/// // our_square.h
435/// // ...
436///
437/// inline
438/// void Square::setWidth(int width)
439/// {
440/// BSLS_ASSERT_SAFE(width >= 0);
441///
442/// d_width = width;
443/// }
444/// @endcode
445/// Now consider a client that uses this `setWidth` method:
446/// @code
447/// // my_client.cpp
448/// // ...
449/// void f()
450/// {
451/// Square s;
452/// s.setWidth(-5);
453/// }
454/// @endcode
455/// We can build the @ref our_square component in "safe mode" -- e.g., by
456/// incorporating `-DBSLS_ASSERT_LEVEL_ASSERT_SAFE` on the (Unix) command line.
457/// Notice, however, that building client software against a version of
458/// `our_square.o` compiled in "safe mode" does *not* ensure that all of the
459/// `BSLS_ASSERT_SAFE` macros will be active (will instantiate); instead, the
460/// client's build mode will (most likely) govern those instantiations of the
461/// `BSLS_ASSERT_SAFE` macro located within the library. The only way to ensure
462/// that all of the `BSLS_ASSERT_SAFE` macros instantiate is to build the
463/// *client* as well as the library software in "safe mode".
464///
465/// Inline functions are not the only source of multiple inconsistent
466/// definitions. Consider a non-`inline` method `reserveCapacity` on a `List`
467/// template, parameterized by element `TYPE`:
468/// @code
469/// // our_list.h
470/// // ...
471///
472/// template <class TYPE>
473/// void List<TYPE>::reserveCapacity(int numElements)
474/// {
475/// BSLS_ASSERT(numElements >= 0);
476/// // ...
477/// }
478/// @endcode
479/// Each different translation unit that invokes `reserveCapacity` potentially
480/// generates another instantiation of this function template. Those
481/// translation units that are compiled in "debug mode" (or "safe mode") --
482/// e.g., with `BSLS_ASSERT_LEVEL_ASSERT` (or `BSLS_ASSERT_LEVEL_ASSERT_SAFE`)
483/// defined -- will incorporate code corresponding to each use of the
484/// `BSLS_ASSERT` macro therein; the rest will not. Which one of these template
485/// instantiations the linker uses in the final program is undefined and highly
486/// unpredictable.
487///
488/// The bottom line is that, unless clients of a library are compiled with (at
489/// least) the same level of assertion enabling as the library itself, not all
490/// of the library's defensive checking (for the assertion-level for which the
491/// library was compiled) will necessarily be incorporated into the client code.
492/// Similarly, compiling a client in a higher-level of defensive checking (e.g.,
493/// "safe mode") than the library was compiled (e.g., "debug mode") may result
494/// in additional defensive checks beyond what the library author intended for
495/// the mode (e.g., "debug mode") in which the library was compiled.
496///
497/// Note that all build modes (except for when `BDE_BUILD_TARGET_SAFE_2` is
498/// defined, see below) are required to be binary compatible (e.g., fields
499/// cannot be added to the middle of a `struct`). Since a component's contract
500/// makes no explicit promise about what checking will occur, that contract is
501/// not violated when different parts of a program are compiled with different
502/// levels of assertion-enabling build options. The only consequence is that a
503/// smaller (or larger) number of defensive checks may be active than might
504/// otherwise be expected.
505///
506/// ## Conditional Compilation {#bsls_assert-conditional-compilation}
507///
508///
509/// To recap, there are three (mutually compatible) general *build* *targets*:
510/// * `BDE_BUILD_TARGET_OPT`
511/// * `BDE_BUILD_TARGET_SAFE`
512/// * `BDE_BUILD_TARGET_SAFE_2`
513/// seven (mutually exclusive) component-specific *assertion* *levels*:
514/// * `BSLS_ASSERT_LEVEL_ASSERT_SAFE`
515/// * `BSLS_ASSERT_LEVEL_ASSERT`
516/// * `BSLS_ASSERT_LEVEL_ASSERT_OPT`
517/// * `BSLS_ASSERT_LEVEL_NONE`
518/// * `BSLS_ASSERT_LEVEL_ASSUME_OPT`
519/// * `BSLS_ASSERT_LEVEL_ASSUME_ASSERT`
520/// * `BSLS_ASSERT_LEVEL_ASSUME_SAFE`
521/// and four (mutually exclusive) component-specific *review* *levels*:
522/// * `BSLS_REVIEW_LEVEL_REVIEW_SAFE`
523/// * `BSLS_REVIEW_LEVEL_REVIEW`
524/// * `BSLS_REVIEW_LEVEL_REVIEW_OPT`
525/// * `BSLS_REVIEW_LEVEL_NONE`
526/// The above macros can be defined (externally) by the build environment to
527/// affect which of the three *assert* *macros*:
528/// * `BSLS_ASSERT_SAFE(boolean-valued expression)`
529/// * `BSLS_ASSERT(boolean-valued expression)`
530/// * `BSLS_ASSERT_OPT(boolean-valued expression)`
531/// will be enabled in assert mode, which will be in review mode, which will be
532/// assumed, and which will be disabled.
533///
534/// The public interface of this component also explicitly provides a number of
535/// additional intermediate macros to identify how the various `BSLS_ASSERT`
536/// macros have been instantiated. These each exist for each level and have the
537/// following suffixes and meanings:
538/// * `IS_ACTIVE`: Defined if the corresponding level is enabled in assert or
539/// review mode. For example, `BSLS_ASSERT_SAFE_IS_ACTIVE` is defined if
540/// (and only if) the conditions expressed using `BSLS_ASSERT_SAFE` will be
541/// checked at runtime (either as assertions or reviews).
542/// * `IS_REVIEW`: Defined if the corresponding level is enabled in review
543/// mode.
544/// * `IS_ASSUMED`: Defined if the corresponding level is assumed.
545/// * `IS_USED`: Defined if assert expressions for the corresponding level need
546/// to be valid (i.e., if they are "ODR-used"). For example,
547/// `BSLS_ASSERT_SAFE_IS_USED` is defined if (and only if) the conditions
548/// expressed using `BSLS_ASSERT_SAFE` will be compiled. Note that this is a
549/// super-set of the cases where `BSLS_ASSERT_SAFE_IS_ACTIVE` will be
550/// defined, which is when the conditions will be checked at runtime, while
551/// `BSLS_ASSERT_SAFE_IS_USED` is also defined if the conditions are assumed
552/// or if `BSLS_ASSERT_VALIDATE_DISABLED_MACROS` is defined.
553///
554/// Putting that together, these 3 macros are defined if the corresponding macro
555/// is in assert or review mode - and thus the expression will be checked and a
556/// violation handler will be invoked on failure:
557/// * `BSLS_ASSERT_SAFE_IS_ACTIVE`
558/// * `BSLS_ASSERT_IS_ACTIVE`
559/// * `BSLS_ASSERT_OPT_IS_ACTIVE`
560/// These three are defined if the corresponding macro is in review mode - and
561/// thus the expression will be checked and the review violation handler will be
562/// invoked on failure. These will be defined when the review level has been
563/// set to a level higher than the assert level:
564/// * `BSLS_ASSERT_SAFE_IS_REVIEW`
565/// * `BSLS_ASSERT_IS_REVIEW`
566/// * `BSLS_ASSERT_OPT_IS_REVIEW`
567/// These three are defined if the corresponding macro is being assumed, and it
568/// will be hard undefined behavior to violate these expressions:
569/// * `BSLS_ASSERT_SAFE_IS_ASSUMED`
570/// * `BSLS_ASSERT_IS_ASSUMED`
571/// * `BSLS_ASSERT_OPT_IS_ASSUMED`
572///
573/// Finally, three more macros with the `IS_USED` suffix are defined when the
574/// expression for the corresponding macro is going to be compiled. This will
575/// be true for macros in assert, review or assumed modes, and it will be true
576/// for all macros if `BSLS_ASSERT_VALIDATE_DISABLED_MACROS` has been defined.
577/// * `BSLS_ASSERT_SAFE_IS_USED`
578/// * `BSLS_ASSERT_IS_USED`
579/// * `BSLS_ASSERT_OPT_IS_USED`
580///
581/// Note that any of the `IS_ACTIVE`, `IS_REVIEW", and `IS_ASSUMED' macros being
582/// defined will imply that the corresponding `IS_USED` macro is also defined.
583///
584/// Which of these macros to use to conditionally compile supporting code is
585/// based on when that supporting code needs to be compiled:
586/// * Use `#if defined(..._IS_USED)` when:
587/// * Writing functions that are only accessible to and needed for assertions
588/// of the corresponding level. This could be private member functions,
589/// static functions, or functions in an anonymous namespace. See
590/// {Example 8} for details on this use.
591/// * Use `#if !defined(..._IS_ACTIVE) && !defined(..._IS_ASSUMED)` when:
592/// * You are writing (test) code that will intentionally violate a contract
593/// when there is not going to be any intrinsic ill effect to that
594/// violation. Generally this should only be required when there is a need
595/// to validate out-of-contract behavior of a component from within its own
596/// test driver.
597/// * Use `#if defined(...IS_ACTIVE)` when:
598/// * You are doing negative testing and want to be sure that when you call
599/// your function out of contract that the violation handler will be
600/// invoked. See @ref bsls_asserttest for tools to do this without having
601/// to manually check these macros.
602/// * Writing redundant defensive code that should only execute when the
603/// corresponding assertions are going to be enabled. The assertion itself
604/// should also be included in the same preprocessor block. See
605/// {Example 9} for details on this use.
606/// * Note that historically this was the only macro available, and it is
607/// often used for blocks of code where the checks above would be more
608/// appropriate. This can often lead to code that fails to compile with
609/// `BSLS_ASSERT_VALIDATE_DISABLED_MACROS` enabled or which will not work
610/// correctly when assumptions are turned on.
611///
612/// See {Example 6} and {Example 7}, respectively, for how
613/// `BDE_BUILD_TARGET_SAFE_2` and intermediate assertion predicate macros, such
614/// as `BSLS_ASSERT_SAFE_IS_ACTIVE` (and even `BSLS_ASSERT_OPT_IS_ACTIVE`), can
615/// be used profitably in practice.
616///
617/// ## Validating Disabled Macro Expressions {#bsls_assert-validating-disabled-macro-expressions}
618///
619///
620/// An additional external macro, `BSLS_ASSERT_VALIDATE_DISABLED_MACROS`, can be
621/// defined to control the compile time behavior of @ref bsls_assert . Enabling
622/// this macro configures all *disabled* assert macros to still instantiate
623/// their predicates (in a non-evaluated context) to be sure that the predicate
624/// is still syntactically valid. This can be used to ensure assertions that
625/// are rarely enabled have valid expressions.
626///
627/// ## Language-Level Contracts {#bsls_assert-language-level-contracts}
628///
629///
630/// Contracts were proposed, accepted into the draft C++20 standard, and then
631/// removed. Implementations of that facility exist and it is expected future
632/// implementations will begin to arrive as work on new proposals comes to
633/// fruition. Defining the macro `BSLS_ASSERT_USE_CONTRACTS` will cause all
634/// `BSLS_ASSERT` (and, if possible, `BSLS_REVIEW`) macros to go through the
635/// language-level contract implementation if it is available (currently only on
636/// an experimental version of the gcc-compiler), otherwise a diagnostic will be
637/// issued.
638///
639/// Note that mixing builds that do and do not use `BSLS_ASSERT_USE_CONTRACTS`
640/// is not supported. Attempting to link against a library bult with a
641/// different mode for this option will cause a link-time error.
642///
643/// ## Usage {#bsls_assert-usage}
644///
645///
646/// The following examples illustrate (1) when to use each of the three kinds of
647/// (BSLS) "ASSERT" macros, (2) when and how to call the `invokeHandler` method
648/// directly, (3) how to configure, at runtime, the behavior resulting from an
649/// assertion failure using "off-the-shelf" handler methods, (4) how to create
650/// your own custom assertion-failure handler function, (5) proper use of
651/// `bsls::AssertFailureHandlerGuard` to install, temporarily, an
652/// exception-producing assert handler, (6) how "ASSERT" macros would be used in
653/// conjunction with portions of the source code (affecting binary
654/// compatibility) that are incorporated only when `BDE_BUILD_TARGET_SAFE_2` is
655/// defined, and (7) how assertion predicates (e.g.,
656/// `BSLS_ASSERT_SAFE_IS_ACTIVE`) are used to conditionally compile additional
657/// (redundant) defensive source code (not affecting binary compatibility)
658/// precisely when the corresponding (BSLS) "ASSERT" macro (e.g.,
659/// `BSLS_ASSERT_SAFE`) is active.
660///
661/// ### Example 1: Using BSLS_ASSERT, BSLS_ASSERT_SAFE, and BSLS_ASSERT_OPT {#bsls_assert-example-1-using-bsls_assert-bsls_assert_safe-and-bsls_assert_opt}
662///
663///
664/// This component provides three different variants of (BSLS) "ASSERT" macros.
665/// This first usage example illustrates how one might select each of the
666/// particular variants, based on the runtime cost of the defensive check
667/// relative to that of the useful work being done.
668///
669/// Use of the `BSLS_ASSERT_SAFE` macro is often appropriate when the defensive
670/// check occurs within the body of an `inline` function. The
671/// `BSLS_ASSERT_SAFE` macro minimizes the impact on runtime performance as it
672/// is instantiated only when requested (i.e., by building in "safe mode"). For
673/// example, consider a light-weight point class `Kpoint` that maintains `x` and
674/// `y` coordinates in the range `[-1000 .. 1000]`:
675/// @code
676/// my_kpoint.h
677/// ...
678///
679/// class Kpoint {
680/// short int d_x;
681/// short int d_y;
682/// public:
683/// Kpoint(short int x, short int y);
684/// // ...
685/// // The behavior is undefined unless '-1000 <= x <= 1000' and
686/// // '-1000 <= y <= 1000'.
687/// // ...
688/// };
689///
690/// ...
691/// @endcode
692/// Since the cost of validation here is significant compared with the useful
693/// work being done, we might choose to implement defensive checks using
694/// `BSLS_ASSERT_SAFE` as follows:
695/// @code
696/// ...
697///
698/// inline
699/// Kpoint::Kpoint(short int x, short int y)
700/// : d_x(x)
701/// , d_y(y)
702/// {
703/// BSLS_ASSERT_SAFE(-1000 <= x); BSLS_ASSERT_SAFE(x <= 1000);
704/// BSLS_ASSERT_SAFE(-1000 <= y); BSLS_ASSERT_SAFE(y <= 1000);
705/// }
706/// @endcode
707/// For more substantial (non-`inline`) functions, we would be more likely to
708/// use the `BSLS_ASSERT` macro because the runtime overhead due to defensive
709/// checks is likely to be much less significant. For example, consider a
710/// hash-table class that allows the client to resize the underlying table:
711/// @code
712/// my_hashtable.h
713/// ...
714///
715/// class HashTable {
716/// // ...
717/// public:
718/// // ...
719///
720/// void resize(double loadFactor);
721/// // Adjust the size of the underlying hash table to be approximately
722/// // the current number of elements divided by the specified
723/// // 'loadFactor'. The behavior is undefined unless
724/// // '0 < loadFactor'.
725/// };
726/// @endcode
727/// Since the relative runtime cost of validating the input argument is quite
728/// small (e.g., less than 10%) compared to the typical work being done, we
729/// might choose to implement the defensive check using `BSLS_ASSERT` as
730/// follows:
731/// @code
732/// my_hashtable.cpp
733/// ...
734///
735/// void HashTable::resize(double loadFactor)
736/// {
737/// BSLS_ASSERT(0 < loadFactor);
738///
739/// // ...
740/// }
741/// @endcode
742/// In some cases, the runtime cost of checking is always negligible when
743/// compared with the runtime cost of performing the useful work; moreover, the
744/// consequences of continuing in an undefined state for certain applications
745/// could be catastrophic. Instead of using `BSLS_ASSERT` in such cases, we
746/// might consider using `BSLS_ASSERT_OPT`. For example, suppose we have a
747/// financial application class `TradingSystem` that performs trades:
748/// @code
749/// my_tradingsystem.h
750/// ...
751///
752/// class TradingSystem {
753/// // ...
754/// public:
755/// // ...
756/// @endcode
757/// Further suppose that there is a particular method `executeTrade` that takes,
758/// as a scaling factor, an integer that must be a multiple of 100 or the
759/// behavior is undefined (and might actually execute a trade):
760/// @code
761/// void executeTrade(int scalingFactor);
762/// // Execute the current trade using the specified 'scalingFactor'.
763/// // The behavior is undefined unless '0 <= scalingFactor' and '100'
764/// // evenly divides 'scalingFactor'.
765/// // ...
766/// };
767/// @endcode
768/// Because the cost of the two checks is likely not even measurable compared to
769/// the overhead of accessing databases and executing the trade, and because the
770/// consequences of specifying a bad scaling factor are virtually unbounded, we
771/// might choose to implement these defensive checks using `BSLS_ASSERT_OPT` as
772/// follows:
773/// @code
774/// my_tradingsystem.cpp
775/// ...
776///
777/// void TradingSystem::executeTrade(int scalingFactor)
778/// {
779/// BSLS_ASSERT_OPT(0 <= scalingFactor);
780/// BSLS_ASSERT_OPT(0 == scalingFactor % 100);
781///
782/// // ...
783/// }
784/// @endcode
785/// Notice that in each case, the choice of which of the three (BSLS) "ASSERT"
786/// macros to use is governed primarily by the relative runtime cost compared
787/// with that of the useful work being done (and only secondarily by the
788/// potential consequences of continuing execution in an undefined state).
789///
790/// ### Example 2: When and How to Call the invokeHandler Method Directly {#bsls_assert-example-2-when-and-how-to-call-the-invokehandler-method-directly}
791///
792///
793/// There *may* be times (but this is yet to be demonstrated) when we might
794/// reasonably choose to unconditionally invoke the currently installed
795/// assertion-failure handler directly -- i.e., instead of via one of the three
796/// (BSLS) "ASSERT" macros provided in this component. Suppose that we are
797/// currently in the body of some function `someFunc` and, for whatever reason,
798/// feel compelled to invoke the currently installed assertion-failure handler
799/// based on some criteria other than the current build mode.
800/// `BSLS_ASSERT_INVOKE` is provided for this purpose. The call might look as
801/// follows:
802/// @code
803/// void someFunc(bool a, bool b, bool c)
804/// {
805/// bool someCondition = a && b && !c;
806///
807/// if (someCondition) {
808/// BSLS_ASSERT_INVOKE("Bad News");
809/// }
810/// }
811/// @endcode
812/// If presented with invalid arguments, `someFunc` (above) will produce output
813/// similar to the following:
814/// @code
815/// Assertion failed: Bad News, file bsls_assert.t.cpp, line 609
816/// Abort (core dumped)
817/// @endcode
818/// If a piece of code needs to be guaranteed to not return, the additional
819/// macro `BSLS_ASSERT_INVOKE_NORETURN` is also available. It behaves the same
820/// way as `BSLS_ASSERT_INVOKE`, but if the installed handler *does* return
821/// `failByAbort` will be immediately called. On supported platforms it is
822/// marked appropriately to not return to support compiler requirements and
823/// static analysis tools.
824///
825/// ### Example 3: Runtime Configuration of the bsls::Assert Facility {#bsls_assert-example-3-runtime-configuration-of-the-bsls-assert-facility}
826///
827///
828/// By default, any assertion failure will result in the invocation of the
829/// `bsls::Assert::failByAbort` handler function. We can replace this behavior
830/// with that of one of the other static failure handler methods supplied in
831/// `bsls::Assert` as follows. Let's assume we are at the top of our
832/// application called `myMain` (which would typically be `main`):
833/// @code
834/// void myMain()
835/// {
836/// @endcode
837/// First observe that the default assertion-failure handler function is, in
838/// fact, `bsls::Assert::failByAbort`:
839/// @code
840/// assert(&bsls::Assert::failByAbort == bsls::Assert::violationHandler());
841/// @endcode
842/// Next, we install a new assertion-failure handler function,
843/// `bsls::Assert::failBySleep`, from the suite of "off-the-shelf" handlers
844/// provided as `static` methods of `bsls::Assert`:
845/// @code
846/// bsls::Assert::setViolationHandler(&bsls::Assert::failBySleep);
847/// @endcode
848/// Observe that `bsls::Assert::failBySleep` is the new, currently-installed
849/// assertion-failure handler:
850/// @code
851/// assert(&bsls::Assert::failBySleep == bsls::Assert::violationHandler());
852/// @endcode
853/// Note that if we were to explicitly invoke the current assertion-failure
854/// handler as follows:
855/// @code
856/// BSLS_ASSERT_INVOKE("message"); // This will hang!
857/// @endcode
858/// the program will hang since `bsls::Assert::failBySleep` repeatedly sleeps
859/// for a period of time within an infinite loop. Thus, this assertion-failure
860/// handler is useful for hanging a process so that a debugger may be attached
861/// to it.
862///
863/// We may now decide to disable the `setViolationHandler` method using the
864/// `bsls::Assert::lockAssertAdministration()` method to ensure that no one else
865/// will override our decision globally. Note, however, that the
866/// `bsls::AssertFailureHandlerGuard` is not affected, and can still be used to
867/// supplant the currently installed handler (see below):
868/// @code
869/// bsls::Assert::lockAssertAdministration();
870/// @endcode
871/// Attempting to change the currently installed handler now will fail:
872/// @code
873/// bsls::Assert::setViolationHandler(&bsls::Assert::failByAbort);
874///
875/// assert(&bsls::Assert::failByAbort != bsls::Assert::violationHandler());
876///
877/// assert(&bsls::Assert::failBySleep == bsls::Assert::violationHandler());
878/// }
879/// @endcode
880///
881/// ### Example 4: Creating a Custom Assertion Handler {#bsls_assert-example-4-creating-a-custom-assertion-handler}
882///
883///
884/// Sometimes, especially during testing, we may need to write our own custom
885/// assertion-failure handler function. The only requirements are that the
886/// function have the same prototype (i.e., the same respective parameter and
887/// return types) as the `bsls::Assert::Handle` `typedef`, and that the function
888/// should not return (i.e., it must `abort`, `exit`, `terminate`, `throw`, or
889/// hang). To illustrate, we will create a `static` method at file scope that
890/// conforms to the required structure (notice the explicit use of `std::printf`
891/// from `<cstdio>` instead of `std::cout` from `<iostream>` to avoid
892/// interaction with the C++ memory allocation layer):
893/// @code
894/// static bool globalEnableOurPrintingFlag = true;
895///
896/// static
897/// void ourFailureHandler(const bsls::AssertViolation& violation)
898/// // Print the expression 'comment', 'file' name, and 'line' number from
899/// // the specified 'violation' to 'stdout' as a comma-separated list,
900/// // replacing null string-argument values with empty strings (unless
901/// // printing has been disabled by the 'globalEnableOurPrintingFlag'
902/// // variable), then unconditionally abort.
903/// {
904/// const char *comment = violation.comment();
905/// if (!comment) {
906/// comment = "";
907/// }
908/// const char *file = violation.fileName();
909/// if (!file) {
910/// file = "";
911/// }
912/// int line = violation.lineNumber();
913/// if (globalEnableOurPrintingFlag) {
914/// std::printf("%s, %s, %d\n", comment, file, line);
915/// }
916/// std::abort();
917/// }
918/// @endcode
919/// At the top level of our application we have the following:
920/// @code
921/// void ourMain()
922/// {
923/// @endcode
924/// First, let's observe that we can assign this new function to a function
925/// pointer of type `bsls::Assert::Handler`:
926/// @code
927/// bsls::Assert::ViolationHandler f = &ourFailureHandler;
928/// @endcode
929/// Now we can install it just as we would any other handler:
930/// @code
931/// bsls::Assert::setViolationHandler(&ourFailureHandler);
932/// @endcode
933/// We can now invoke the default handler directly:
934/// @code
935/// BSLS_ASSERT_INVOKE("str1");
936/// }
937/// @endcode
938/// With the resulting output something like as follows:
939/// @code
940/// str1, my_file.cpp, 17
941/// Abort (core dumped)
942/// @endcode
943///
944/// ### Example 5: Using the bsls::AssertFailureHandlerGuard {#bsls_assert-example-5-using-the-bsls-assertfailurehandlerguard}
945///
946///
947/// Sometimes we may want to replace, temporarily (i.e., within some local
948/// lexical scope), the currently installed assertion-failure handler function.
949/// In particular, we sometimes use the `bsls::AssertFailureHandlerGuard` class
950/// to replace the current handler with one that throws an exception (because we
951/// know that such an exception is safe in the local context). Let's start with
952/// the simple factorial function below, which validates, in "debug mode" (or
953/// "safe mode"), that its input is non-negative:
954/// @code
955/// double fact(int n)
956/// // Return 'n!'. The behavior is undefined unless '0 <= n'.
957/// {
958/// BSLS_ASSERT(0 <= n);
959///
960/// double result = 1.0;
961/// while (n > 1) {
962/// result *= n--;
963/// }
964/// return result;
965/// }
966/// @endcode
967/// Now consider the following integer-valued `extern "C"` C++ function,
968/// `wrapperFunc`, which can be called from C and FORTRAN, as well as from C++:
969/// @code
970/// extern "C" int wrapperFunc(bool verboseFlag)
971/// {
972/// enum { GOOD = 0, BAD } result = GOOD; (void) verboseFlag;
973/// @endcode
974/// The purpose of this function is to allow assertion failures in subroutine
975/// calls below this function to be handled by throwing an exception, which is
976/// then caught by the wrapper and reported to the caller as a "bad" status.
977/// Hence, when within the runtime scope of this function, we want to install,
978/// temporarily, the assertion-failure handler `bsls::Assert::failByThrow`,
979/// which, when invoked, causes an `bsls::AssertTestException` object to be
980/// thrown. (Note that we are not advocating this approach for "recovery", but
981/// rather for an orderly shut-down, or perhaps during testing.) The
982/// `bsls::AssertFailureHandlerGuard` class is provided for just this purpose:
983/// @code
984/// assert(&bsls::Assert::failByAbort == bsls::Assert::violationHandler());
985///
986/// bsls::AssertFailureHandlerGuard guard(&bsls::Assert::failByThrow);
987///
988/// assert(&bsls::Assert::failByThrow == bsls::Assert::violationHandler());
989/// @endcode
990/// Next we open up a `try` block, and somewhere within the `try` we
991/// "accidentally" invoke `fact` with an out-of-contract value (i.e., `-1`):
992/// @code
993/// #ifdef BDE_BUILD_TARGET_EXC
994/// try
995/// #endif
996/// {
997///
998/// // ...
999///
1000/// double d = fact(-1); // Out-of-contract call to 'fact'.
1001///
1002/// // ...
1003/// }
1004/// #ifdef BDE_BUILD_TARGET_EXC
1005/// catch (const bsls::AssertTestException& e) {
1006/// result = BAD;
1007/// if (verboseFlag) {
1008/// std::printf( "Internal Error: %s, %s, %d\n",
1009/// e.expression(),
1010/// e.filename(),
1011/// e.lineNumber() );
1012/// }
1013/// }
1014/// #endif
1015/// return result;
1016/// }
1017/// @endcode
1018/// Assuming exceptions are enabled (i.e., `BDE_BUILD_TARGET_EXC` is defined),
1019/// if an `bsls::AssertTestException` occurs below this wrapper function, the
1020/// exception will be caught, a message will be printed to `stdout`, e.g.,
1021/// @code
1022/// Internal Error: bsls_assert.t.cpp:500: 0 <= n
1023/// @endcode
1024/// and the `wrapperFunc` function will return a bad status (i.e., 1) to its
1025/// caller. Note that if exceptions are not enabled,
1026/// `bsls::Assert::failByThrow` will behave as `bsls::Assert::failByAbort`, and
1027/// dump core immediately:
1028/// @code
1029/// Assertion failed: 0 <= n, file bsls_assert.t.cpp, line 500
1030/// Abort (core dumped)
1031/// @endcode
1032/// Finally note that the `bsls::AssertFailureHandlerGuard` is not thread-aware.
1033/// In particular, a guard that is created in one thread will also affect the
1034/// failure handlers that are used in other threads. Care should be taken when
1035/// using this guard when more than a single thread is executing.
1036///
1037/// ### Example 6: Using (BSLS) "ASSERT" Macros Along With BDE_BUILD_TARGET_SAFE_2 {#bsls_assert-example-6-using-assert-macros-along-with-bde_build_target_safe_2}
1038///
1039///
1040/// Recall that assertions do not affect binary compatibility; however, software
1041/// built with `BDE_BUILD_TARGET_SAFE_2` defined need not be binary compatible
1042/// with software built otherwise. In this example, we look at how we might use
1043/// the (BSLS) "ASSERT" family of macros in conjunction with code that is
1044/// incorporated (at compile time) only when `BDE_BUILD_TARGET_SAFE_2` is
1045/// defined.
1046///
1047/// As a simple example, let's consider an elided implementation of a
1048/// singly-linked integer list and its iterator. Whenever
1049/// `BDE_BUILD_TARGET_SAFE_2` is defined, we want to defend against the
1050/// possibility that a client mistakenly passes a `ListIter` object into a
1051/// `List` object method (e.g., `List::insert`) where that `ListIter` object did
1052/// not originate from the same `List` object.
1053///
1054/// We'll start by defining a local helper `List_Link` `struct` as follows:
1055/// @code
1056/// struct List_Link {
1057/// List_Link *d_next_p;
1058/// int d_data;
1059/// List_Link(List_Link *next, int data) : d_next_p(next), d_data(data) { }
1060/// };
1061/// @endcode
1062/// Next, we'll define `ListIter`, which always identifies the current position
1063/// in a sequence of links, but whenever `BDE_BUILD_TARGET_SAFE_2` is defined,
1064/// also maintains a pointer to its parent `List` object:
1065/// @code
1066/// class List; // Forward declaration.
1067///
1068/// class ListIter {
1069/// #ifdef BDE_BUILD_TARGET_SAFE_2
1070/// List *d_parent_p; // Exists only in "safe 2 mode".
1071/// #endif
1072/// List_Link **d_current_p;
1073/// friend class List;
1074/// friend bool operator==(const ListIter&, const ListIter&);
1075/// private:
1076/// ListIter(List_Link **current,
1077/// List *
1078/// #ifdef BDE_BUILD_TARGET_SAFE_2
1079/// parent // Not used unless in "safe 2 mode".
1080/// #endif
1081/// )
1082/// : d_current_p(current)
1083/// #ifdef BDE_BUILD_TARGET_SAFE_2
1084/// , d_parent_p(parent) // Initialize only in "safe 2 mode".
1085/// #endif
1086/// { }
1087/// public:
1088/// ListIter& operator++() { /* ... */ return *this; }
1089/// // ...
1090/// };
1091/// bool operator==(const ListIter& lhs, const ListIter& rhs);
1092/// bool operator!=(const ListIter& lhs, const ListIter& rhs);
1093/// @endcode
1094/// Finally we define the `List` class itself with most of the operations
1095/// elided; the methods of particular interest here are `begin` and `insert`:
1096/// @code
1097///
1098/// class List {
1099/// List_Link *d_head_p;
1100/// public:
1101/// // CREATORS
1102/// List() : d_head_p(0) { }
1103/// List(const List&) { /* ... */ }
1104/// ~List() { /* ... */ }
1105///
1106/// // MANIPULATORS
1107/// List& operator=(const List&) { /* ... */ return *this; }
1108///
1109/// //| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
1110/// //v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v
1111/// //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
1112/// ListIter begin()
1113/// // Return an iterator referring to the beginning of this list.
1114/// {
1115/// return ListIter(&d_head_p, this);
1116/// }
1117/// //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
1118///
1119/// //| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
1120/// //v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v
1121/// //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
1122/// void insert(const ListIter& position, int data)
1123/// // Insert the specified 'data' value into this list at the
1124/// // specified 'position'.
1125/// {
1126/// #ifdef BDE_BUILD_TARGET_SAFE_2
1127/// BSLS_ASSERT_SAFE(this == position.d_parent_p); // "safe 2 mode"
1128/// #endif
1129/// *position.d_current_p = new List_Link(*position.d_current_p, data);
1130/// }
1131/// //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
1132///
1133/// // ACCESSORS
1134/// void print()
1135/// // Output the contents of this list to 'stdout'.
1136/// {
1137/// printf( "[" );
1138/// for (List_Link *p = d_head_p; p; p = p->d_next_p) {
1139/// printf( " %d", p->d_data );
1140/// }
1141/// printf(" ]\n");
1142/// }
1143/// };
1144/// @endcode
1145/// Outside of "safe 2 mode", it is possible to pass an iterator object obtained
1146/// from the `begin` method of one `List` object into the `insert` method of
1147/// another, having, perhaps, unexpected results:
1148/// @code
1149/// void sillyFunc(bool printFlag)
1150/// {
1151/// List a;
1152/// ListIter aIt = a.begin();
1153/// a.insert(aIt, 1);
1154/// a.insert(aIt, 2);
1155/// a.insert(aIt, 3);
1156///
1157/// if (printFlag) {
1158/// std::printf( "a = "); a.print();
1159/// }
1160///
1161/// List b;
1162/// ListIter bIt = b.begin();
1163/// a.insert(bIt, 4); // Oops! Should have been: 'b.insert(bIt, 4);'
1164/// a.insert(bIt, 5); // Oops! " " " ' " " 5 '
1165/// a.insert(bIt, 6); // Oops! " " " ' " " 6 '
1166///
1167/// if (printFlag) {
1168/// std::printf( "a = "); a.print();
1169/// std::printf( "b = "); b.print();
1170/// }
1171/// }
1172/// @endcode
1173/// In the example above, we have "accidentally" passed the iterator `bIt`
1174/// obtained from `List` object `b` into the `insert` method for `List` object
1175/// `a`. The resulting undefined behavior (in other than "safe 2 mode") might
1176/// produce output that looks as follows:
1177/// @code
1178/// a = [ 3 2 1 ]
1179/// a = [ 3 2 1 ]
1180/// b = [ 6 5 4 ]
1181/// @endcode
1182/// If the same `sillyFunc` were compiled in "safe 2 mode" (i.e., with
1183/// `BDE_BUILD_TARGET_SAFE_2` defined) the undefined behavior would be detected
1184/// and the output would, by default, look more like the following:
1185/// @code
1186/// a = [ 3 2 1 ]
1187/// FATAL my_list.cpp:56 Assertion failed: this == position.d_parent_p
1188/// Abort (core dumped)
1189/// @endcode
1190/// thereby quickly exposing the misuse by the client.
1191///
1192/// ### Example 7: Conditional Compilation Associated with Enabled Assertion Levels {#bsls_assert-example-7-conditional-compilation-associated-with-enabled-assertion-levels}
1193///
1194///
1195/// In cases where we want to tie code, other than just an assertion, to a
1196/// specific level of enabled assertions, we will want to use the corresponding
1197/// intermediate predicate that enables that level of assertions:
1198///
1199/// * For `BSLS_ASSERT_SAFE`, use `BSLS_ASSERT_SAFE_IS_ACTIVE`.
1200/// * For `BSLS_ASSERT`, use `BSLS_ASSERT_IS_ACTIVE`.
1201/// * For `BSLS_ASSERT_OPT`, use `BSLS_ASSERT_OPT_IS_ACTIVE`.
1202///
1203/// Suppose that we have a class such as `MyDate` (below) that, except for
1204/// checking its invariants, would have a trivial destructor. By not declaring
1205/// a destructor at all, we may realize performance advantages, but then we lose
1206/// the ability to validate our invariants in "debug" or "safe" mode. What we
1207/// want to do is to declare (and later define) the destructor in precisely
1208/// those build modes for which we would want to assert invariants.
1209///
1210/// An elided class `MyDate`, which is based on a serial-date implementation, is
1211/// provided for reference:
1212/// @code
1213/// class MyDate {
1214/// // This class implements a value-semantic "date" type representing
1215/// // valid date values in the range '[ 0001Jan01 .. 9999Dec31 ]'.
1216///
1217/// // DATA
1218/// int d_serialDate; // sequential representation within a valid range
1219///
1220/// public:
1221/// // CLASS METHODS
1222///
1223/// // ...
1224///
1225/// // CREATORS
1226/// MyDate();
1227/// // Create a 'MyDate' object having the value '0001Jan01'.
1228///
1229/// // ...
1230///
1231/// MyDate(const MyDate& original);
1232/// // Create a 'MyDate' object having the same value as the specified
1233/// // 'original' object.
1234///
1235/// #if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
1236/// ~MyDate();
1237/// // Destroy this object. Note that in some build modes the
1238/// // destructor generated by the compiler is trivial.
1239/// #endif
1240///
1241/// // ...
1242/// };
1243///
1244/// ...
1245///
1246/// ========================================================================
1247/// INLINE FUNCTION DEFINITIONS
1248/// ========================================================================
1249///
1250/// ...
1251///
1252/// CREATORS
1253/// inline
1254/// MyDate::MyDate()
1255/// : d_serialDate(1) // 0001Jan01
1256/// {
1257/// }
1258///
1259/// inline
1260/// MyDate::MyDate(const MyDate& original)
1261/// : d_serialDate(original.d_serialDate)
1262/// {
1263/// }
1264///
1265/// ...
1266///
1267/// #if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
1268/// inline
1269/// MyDate::~MyDate()
1270/// {
1271/// BSLS_ASSERT_SAFE(1 <= d_serialDate); // 0001Jan01
1272/// BSLS_ASSERT_SAFE( d_serialDate <= 3652061); // 9999Dec31
1273/// }
1274/// #endif
1275///
1276/// ...
1277/// @endcode
1278/// In practice, however, we would probably implement an `isValidSerialDate`
1279/// method in a lower-level utility class, e.g., `MyDateImpUtil`, leading to
1280/// code that is more fine-grained, modular, and hierarchically reusable:
1281/// @code
1282/// struct MyDateImpUtil {
1283/// static bool isValidSerialDate(int d_date);
1284/// // Return 'true' if the specified 'd_date' represents a valid date
1285/// // value, and 'false' otherwise.
1286/// };
1287///
1288/// inline
1289/// bool MyDateImpUtil::isValidSerialDate(int d_date)
1290/// {
1291/// return 1 <= d_date && d_date <= 3652061;
1292/// }
1293/// @endcode
1294/// Like other aspects of `BSLS_ASSERT_SAFE`, the example above violates the
1295/// one-definition rule for mixed-mode builds. Note that all code conditionally
1296/// compiled based on `BSLS_ASSERT_SAFE_IS_ACTIVE`, `BSLS_ASSERT_IS_ACTIVE`, and
1297/// `BSLS_ASSERT_OPT_IS_ACTIVE` should be binary compatible for mixed-mode
1298/// builds. If the conditionally-compiled code would not be binary compatible,
1299/// use `BDE_BUILD_TARGET_SAFE_2` instead.
1300///
1301/// WARNING - In practice, declaring a destructor in some build modes but not
1302/// others has led to subtle and difficult-to-diagnose failures. DON'T DO IT!
1303///
1304/// Finally, in very rare cases, we may want to put in (redundant) defensive
1305/// code (in the spirit of `BSLS_ASSERT_OPT`) that is not part of the
1306/// component-level contract, yet (1) is known to have negligible runtime cost
1307/// and (2) is deemed to be so important as to be necessary even for optimized
1308/// builds.
1309///
1310/// For example, consider again the `MyDate` class above that now also declares
1311/// a non-`inline` `print` method to format the current date value in some
1312/// human-readable, but otherwise unspecified format:
1313/// @code
1314/// xyza_mydate.h
1315/// ...
1316/// class MyDate {
1317/// // ...
1318///
1319/// // DATA
1320/// int d_serialDate; // sequential representation within a valid range
1321///
1322/// public:
1323/// // ...
1324/// // ACCESSORS
1325/// // ...
1326///
1327/// std::ostream& print(std::ostream& stream, ...) const;
1328/// // Write the value of this object to the specified output 'stream'
1329/// // in some human-readable format, and return a reference to
1330/// // 'stream'. Optionally specify ...
1331///
1332/// // ...
1333///
1334/// };
1335/// @endcode
1336/// Successfully writing bad data is among the most insidious of bugs, because a
1337/// latent error can persist and not be discovered until long after the program
1338/// terminates. Writing the value of a corrupted `MyDate` object in a
1339/// *machine-readable* (binary) format is an error so serious as to warrant
1340/// invoking
1341/// @code
1342/// void testFunction(int d_serialDate) {
1343/// BSLS_ASSERT_OPT(MyDateImpUtil::isValidSerialDate(d_serialDate));
1344/// }
1345/// @endcode
1346/// each time we attempt the output operation; however, printing the value in a
1347/// human-readable format intended primarily for debugging purposes is another
1348/// matter. In anything other than a safe build (which in this case would
1349/// enforce essentially all method preconditions), it would be unfortunate if a
1350/// developer, knowing that there was a problem involving the use of `MyDate`,
1351/// inserted print statements to identify that problem, only to have the `print`
1352/// method itself ruthlessly invoke the assert handler, likely terminating the
1353/// process). Moreover, it may also be unsafe even to attempt to format the
1354/// value of a `MyDate` object whose `d_serialDate` value violates its
1355/// invariants (e.g., due to a static table lookup). In such cases we may, as
1356/// sympathetic library developers, choose to implement different undefined
1357/// (undocumented) redundant defensive behaviors, depending on the desired level
1358/// of assertions:
1359/// @code
1360/// xyza_mydate.cpp
1361/// ...
1362/// #include <xyza_mydateimputil.h>
1363/// ...
1364///
1365/// std::ostream& MyDate::print(std::ostream& stream, ...) const
1366/// {
1367/// // BSLS_ASSERT(/* any *argument* preconditions for this function */);
1368///
1369/// // Handle case where the invariants have been violated.
1370///
1371/// #ifdef BSLS_ASSERT_OPT_IS_ACTIVE
1372/// // Note that if 'BSLS_ASSERT_LEVEL_NONE' has been set, this code --
1373/// // along with all 'BSLS_ASSERT_OPT' macros -- will not instantiate,
1374/// // enabling us to verify that the combined runtime overhead of all such
1375/// // (redundant) defensive code is at worst negligible, if not
1376/// // unmeasurable.
1377///
1378/// if (!MyDateImpUtil::isValidSerialDate(d_serialDate)) {
1379///
1380/// // Our invariant is corrupted.
1381///
1382/// #ifdef BSLS_ASSERT_IS_ACTIVE
1383/// // Providing debugging information in this mode would be useful.
1384///
1385/// std::cerr << "\nxyza::MyDate: Invalid internal serial date value "
1386/// << d_serialDate << '.' << std::endl;
1387///
1388/// #endif // BSLS_ASSERT_IS_ACTIVE
1389///
1390/// // In safe mode, each of the 'MyClass' methods fully guards its
1391/// // preconditions: There is simply no easy way to get here!
1392///
1393/// BSLS_ASSERT_SAFE("Probable rogue memory overwrite!" && 0);
1394///
1395/// // If we get here, we're corrupted, but not in safe mode!
1396///
1397/// return stream << "(* Invalid 'MyDate' State "
1398/// << d_serialDate
1399/// << " *)" << std::flush; // RETURN
1400///
1401/// }
1402/// #endif // BSLS_ASSERT_OPT_IS_ACTIVE
1403///
1404/// // If we get here in a production build, this object is "sane": Do
1405/// // whatever this 'print' method would normally do, assuming that no
1406/// // method preconditions or object invariants are violated.
1407///
1408/// // ... <*** Your (Normal-Case) Formatting Code Here! ***>
1409///
1410/// return stream;
1411/// }
1412/// @endcode
1413/// ### Example 8: Conditional Compilation of Support Functions {#bsls_assert-example-8-conditional-compilation-of-support-functions}
1414///
1415///
1416/// Occasionally a function may exist only to support a specific set of
1417/// assertions. Often this can happen when a large expression that captures a
1418/// complicated precondition wants to be refactored into a distinct location to
1419/// ease understanding of it. When this happens the function might still remain
1420/// as a private implementation detail of the class.
1421///
1422/// When the only assertion macros that use the function are disabled this can
1423/// lead to a compiler warning about a function being unused, and the
1424/// corresponding code bloat from having the function available might be an
1425/// overhead that is not desired.
1426///
1427/// In order to totally remove the function when it is not needed, the `IS_USED`
1428/// suffixed macros can be used to guard the declaration and definition of the
1429/// function. Suppose we have a `class` with a function having a complex
1430/// precondition, and that precondition check is both private and only needed
1431/// when the assertions that use it are enabled. In that case, we can guard the
1432/// definitions and declarations against even being compiled like this:
1433/// @code
1434/// class ComplexObject {
1435/// // ...
1436/// #if defined(BSLS_ASSERT_SAFE_IS_USED)
1437/// bool isPurplish() const;
1438/// // Return 'true' if the current state of this object fits within
1439/// // the complex requirements of being sufficiently purple, false
1440/// // otherwise.
1441/// #endif
1442/// // ...
1443/// public:
1444/// // MANIPULATORS
1445/// void doSomethingPurpley();
1446/// // Do something purpley. The behavior is undefined unless this
1447/// // object is currently purplish (contact customer support to know
1448/// // the current threshholds for purplishness).
1449/// };
1450///
1451/// #if defined(BSLS_ASSERT_SAFE_IS_USED)
1452/// bool ComplexObject::isPurplish() const
1453/// {
1454/// // The real implementation would encode the complex logic of needing to
1455/// // determine if this object feels purplish at the moment.
1456/// return true;
1457/// }
1458/// #endif
1459///
1460/// void ComplexObject::doSomethingPurpley()
1461/// {
1462/// BSLS_ASSERT_SAFE(isPurplish());
1463/// }
1464/// @endcode
1465/// Now, the `ComplexObject::isPurplish` function will only exist in a subset of
1466/// builds:
1467/// * When `BSLS_ASSERT_SAFE` assertions are enabled in assert or review mode,
1468/// the function will be compiled and invoked.
1469/// * When `BSLS_ASSERT_VALIDATE_DISABLED_MACROS` is defined the function will
1470/// be compiled. This will make sure that a future change does not
1471/// invalidate the implementation of `isPurplish()` even though it is not
1472/// used.
1473/// * When `BSLS_ASSERT_SAFE` assertions are assumed the function will be
1474/// compiled and might be invoked, or at least have its implementation
1475/// inspected by the compiler to improve code generation.
1476///
1477/// ### Example 9: Conditional Compilation of Support Code {#bsls_assert-example-9-conditional-compilation-of-support-code}
1478///
1479///
1480/// Sometimes there is code that needs to run in a function before an assertion
1481/// to gather information needed only by that assertion. Often this can be
1482/// capturing input values or other system state before it is modified and
1483/// verifying at the end of a function that the values are changed (or not)
1484/// appropriately.
1485///
1486/// When the corresponding assertion macro is not active in assert or review
1487/// mode the supporting code should not be executed at all. Importantly,
1488/// because the capturing of additional information is an extra cost, the
1489/// assertion itself does not lend itself to being assumed.
1490///
1491/// Suppose we have a function that wishes to swap the values of its input:
1492/// @code
1493/// struct MySwapper {
1494/// template <class T>
1495/// static void swap(T& lhs, T& rhs)
1496/// // Exchange the values of the specified 'lhs' and 'rhs'.
1497/// {
1498/// T tmp = lhs;
1499/// lhs = rhs;
1500/// rhs = tmp;
1501/// }
1502/// };
1503/// @endcode
1504/// This works great as a simple `swap` implementation, but we would like to
1505/// assert in safe mode that it is doing the correct thing. In order to do that
1506/// we need to capture the initial values of our inputs before doing anything
1507/// else, and we want to do this only when the respective assertions are
1508/// enabled. Here we would guard our code and our assertions in a check that
1509/// `BSLS_ASSERT_SAFE_IS_ACTIVE` is defined, like this:
1510/// @code
1511/// struct MySwapper {
1512/// template <class T>
1513/// static void swap(T& lhs, T& rhs)
1514/// // Exchange the values of the specified 'lhs' and 'rhs'.
1515/// {
1516/// #if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
1517/// T origLhs(lhs);
1518/// T origRhs(rhs);
1519/// #endif
1520/// T tmp = lhs;
1521/// lhs = rhs;
1522/// rhs = tmp;
1523/// #if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
1524/// BSLS_ASSERT_SAFE(rhs == origLhs);
1525/// BSLS_ASSERT_SAFE(lhs == origRhs);
1526/// #endif
1527/// }
1528/// };
1529/// @endcode
1530/// @}
1531/** @} */
1532/** @} */
1533
1534/** @addtogroup bsl
1535 * @{
1536 */
1537/** @addtogroup bsls
1538 * @{
1539 */
1540/** @addtogroup bsls_assert
1541 * @{
1542 */
1543
1544#include <bsls_annotation.h>
1545#include <bsls_assertimputil.h>
1546#include <bsls_buildtarget.h>
1547#include <bsls_compilerfeatures.h>
1548#include <bsls_keyword.h>
1549#include <bsls_performancehint.h>
1550#include <bsls_platform.h>
1551#include <bsls_review.h>
1552
1553#ifdef BSLS_ASSERT_USE_CONTRACTS
1554#include <contract>
1555#endif
1556
1557 // =============================
1558 // Checks for Pre-Defined macros
1559 // =============================
1560
1561#if defined(BSLS_ASSERT_OPT)
1562#error BSLS_ASSERT_OPT is already defined!
1563#endif
1564
1565#if defined(BSLS_ASSERT_OPT_IS_ACTIVE)
1566#error BSLS_ASSERT_OPT_IS_ACTIVE is already defined!
1567#endif
1568
1569#if defined(BSLS_ASSERT_OPT_IS_ASSUMED)
1570#error BSLS_ASSERT_OPT_IS_ASSUMED is already defined!
1571#endif
1572
1573#if defined(BSLS_ASSERT_OPT_IS_REVIEW)
1574#error BSLS_ASSERT_OPT_IS_REVIEW is already defined!
1575#endif
1576
1577#if defined(BSLS_ASSERT_OPT_IS_USED)
1578#error BSLS_ASSERT_OPT_IS_USED is already defined!
1579#endif
1580
1581#if defined(BSLS_ASSERT)
1582#error BSLS_ASSERT is already defined!
1583#endif
1584
1585#if defined(BSLS_ASSERT_IS_ACTIVE)
1586#error BSLS_ASSERT_IS_ACTIVE is already defined!
1587#endif
1588
1589#if defined(BSLS_ASSERT_IS_ASSUMED)
1590#error BSLS_ASSERT_IS_ASSUMED is already defined!
1591#endif
1592
1593#if defined(BSLS_ASSERT_IS_REVIEW)
1594#error BSLS_ASSERT_IS_REVIEW is already defined!
1595#endif
1596
1597#if defined(BSLS_ASSERT_IS_USED)
1598#error BSLS_ASSERT_IS_USED is already defined!
1599#endif
1600
1601#if defined(BSLS_ASSERT_SAFE)
1602#error BSLS_ASSERT_SAFE is already defined!
1603#endif
1604
1605#if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
1606#error BSLS_ASSERT_SAFE_IS_ACTIVE is already defined!
1607#endif
1608
1609#if defined(BSLS_ASSERT_SAFE_IS_ASSUMED)
1610#error BSLS_ASSERT_SAFE_IS_ASSUMED is already defined!
1611#endif
1612
1613#if defined(BSLS_ASSERT_SAFE_IS_REVIEW)
1614#error BSLS_ASSERT_SAFE_IS_REVIEW is already defined!
1615#endif
1616
1617#if defined(BSLS_ASSERT_SAFE_IS_USED)
1618#error BSLS_ASSERT_SAFE_IS_USED is already defined!
1619#endif
1620
1621#if defined(BSLS_ASSERT_INVOKE)
1622#error BSLS_ASSERT_INVOKE is already defined!
1623#endif
1624
1625#if defined(BSLS_ASSERT_INVOKE_NORETURN)
1626#error BSLS_ASSERT_INVOKE_NORETURN is already defined!
1627#endif
1628
1629 // =================================
1630 // (BSLS) "ASSERT" Macro Definitions
1631 // =================================
1632
1633// Implementation Note: We wrap the 'if' statement below in a (seemingly
1634// redundant) do-while-false loop to require, syntactically, a trailing
1635// semicolon, and to ensure that the macro behaves properly in an if-then-else
1636// context -- even if one forgets to wrap, with curly braces, the body of an
1637// 'if' having just a single 'BSLS_ASSERT*' statement.
1638
1639 // =============================================
1640 // Factored Implementation for Internal Use Only
1641 // =============================================
1642
1643#if !(defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) || \
1644 defined(BSLS_ASSERT_LEVEL_ASSERT) || \
1645 defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) || \
1646 defined(BSLS_ASSERT_LEVEL_NONE) || \
1647 defined(BSLS_ASSERT_LEVEL_ASSUME_OPT) || \
1648 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT) || \
1649 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE))
1650 #define BSLS_ASSERT_NO_ASSERTION_MACROS_DEFINED 1
1651#else
1652 #define BSLS_ASSERT_NO_ASSERTION_MACROS_DEFINED 0
1653#endif
1654
1655#ifdef BSLS_ASSERT_USE_CONTRACTS
1656#define BSLS_ASSERT_ASSERT_IMP(X,LVL) [[ assert check_never_continue : X ]]
1657
1658#define BSLS_ASSERT_ASSUME_IMP(X,LVL) [[ assert assume : X ]]
1659#define BSLS_ASSERT_ASSUME_ENABLED
1660
1661#ifdef BSLS_ASSERT_VALIDATE_DISABLED_MACROS
1662#define BSLS_ASSERT_DISABLED_IMP(X,LVL) [[ assert ignore : X ]]
1663#else
1664#define BSLS_ASSERT_DISABLED_IMP(X,LVL)
1665#endif
1666
1667#else
1668#define BSLS_ASSERT_ASSERT_IMP(X,LVL) do { \
1669 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!(X))) { \
1670 BSLS_PERFORMANCEHINT_UNLIKELY_HINT; \
1671 BloombergLP::bsls::AssertViolation violation( \
1672 #X, \
1673 BSLS_ASSERTIMPUTIL_FILE, \
1674 BSLS_ASSERTIMPUTIL_LINE, \
1675 LVL); \
1676 BloombergLP::bsls::Assert::invokeHandler(violation); \
1677 } \
1678 } while (false)
1679
1680#if defined(BSLS_PLATFORM_CMP_CLANG)
1681
1682#define BSLS_ASSERT_ASSUME_IMP(X,LVL) __builtin_assume((X)?true:false)
1683#define BSLS_ASSERT_ASSUME_ENABLED
1684
1685#elif defined(BSLS_PLATFORM_CMP_GNU)
1686// While a common practice with GCC is to implement assumptions using an
1687// expression of the form 'if (!(X)) __builtin_unreachable();', this idiom
1688// relies on the expression 'X' being inline and truly sideeffect free before
1689// GCC will consistently elide the check itself, making this a pessimisation
1690// when used arbitrarily. Because of this we do not attempt to leverage
1691// assumption on GCC and leave the following commented out:
1692//..
1693// #define BSLS_ASSERT_ASSUME_IMP(X,LVL) if (!(X)) { __builtin_unreachable(); }
1694// #define BSLS_ASSERT_ASSUME_ENABLED
1695//..
1696
1697#elif defined (BSLS_PLATFORM_CMP_MSVC)
1698#define BSLS_ASSERT_ASSUME_IMP(X,LVL) __assume((X)?true:false)
1699#define BSLS_ASSERT_ASSUME_ENABLED
1700
1701#endif
1702
1703#if !defined(BSLS_ASSERT_ASSUME_IMP)
1704// The above flavors of 'assumption' are the only available ones that we
1705// support, and the only platforms where we currently attempt to use
1706// assumption.
1707#define BSLS_ASSERT_ASSUME_IMP(X,LVL) BSLS_ASSERT_DISABLED_IMP(X,LVL)
1708#endif
1709
1710#ifdef BSLS_ASSERT_VALIDATE_DISABLED_MACROS
1711#define BSLS_ASSERT_DISABLED_IMP(X,LVL) (void)sizeof((!(X))?true:false)
1712#else
1713#define BSLS_ASSERT_DISABLED_IMP(X,LVL)
1714#endif
1715#endif
1716
1717 // ================
1718 // BSLS_ASSERT_SAFE
1719 // ================
1720
1721// Determine if 'BSLS_ASSERT_SAFE' should be active.
1722
1723// Define the control macros, also usable from client code.
1724#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) \
1725 || BSLS_ASSERT_NO_ASSERTION_MACROS_DEFINED && ( \
1726 defined(BDE_BUILD_TARGET_SAFE_2) || \
1727 defined(BDE_BUILD_TARGET_SAFE) )
1728 #define BSLS_ASSERT_SAFE_IS_ACTIVE
1729#elif defined(BSLS_REVIEW_SAFE_IS_ACTIVE)
1730 #define BSLS_ASSERT_SAFE_IS_REVIEW
1731#elif defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE) && \
1732 !defined(BSLS_REVIEW_OPT_IS_ACTIVE) && \
1733 !defined(BSLS_REVIEW_IS_ACTIVE) && \
1734 !defined(BSLS_REVIEW_SAFE_IS_ACTIVE)
1735 #define BSLS_ASSERT_SAFE_IS_ASSUMED
1736#endif
1737
1738// Indicate when 'BSLS_ASSERT_SAFE' arguments will be ODR-used.
1739#if defined(BSLS_ASSERT_SAFE_IS_REVIEW) || \
1740 defined(BSLS_ASSERT_SAFE_IS_ACTIVE) || \
1741 (defined(BSLS_ASSERT_SAFE_IS_ASSUMED) \
1742 && defined(BSLS_ASSERT_ASSUME_ENABLED)) || \
1743 defined(BSLS_ASSERT_VALIDATE_DISABLED_MACROS)
1744 #define BSLS_ASSERT_SAFE_IS_USED
1745#endif
1746
1747// Define 'BSLS_ASSERT_SAFE' accordingly.
1748
1749#if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
1750 #define BSLS_ASSERT_SAFE(X) BSLS_ASSERT_ASSERT_IMP( \
1751 X, \
1752 BloombergLP::bsls::Assert::k_LEVEL_SAFE)
1753#elif defined(BSLS_ASSERT_SAFE_IS_REVIEW)
1754 #define BSLS_ASSERT_SAFE(X) BSLS_REVIEW_REVIEW_IMP( \
1755 X, \
1756 BloombergLP::bsls::Assert::k_LEVEL_SAFE)
1757#elif defined(BSLS_ASSERT_SAFE_IS_ASSUMED)
1758 #define BSLS_ASSERT_SAFE(X) BSLS_ASSERT_ASSUME_IMP( \
1759 X, \
1760 BloombergLP::bsls::Assert::k_LEVEL_SAFE)
1761#else
1762 #define BSLS_ASSERT_SAFE(X) BSLS_ASSERT_DISABLED_IMP( \
1763 X, \
1764 BloombergLP::bsls::Assert::k_LEVEL_SAFE)
1765#endif
1766
1767
1768 // ===========
1769 // BSLS_ASSERT
1770 // ===========
1771
1772// Determine if 'BSLS_ASSERT' should be active.
1773
1774// Define the control macros, also usable from client code.
1775#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) || \
1776 defined(BSLS_ASSERT_LEVEL_ASSERT) \
1777 || BSLS_ASSERT_NO_ASSERTION_MACROS_DEFINED && ( \
1778 defined(BDE_BUILD_TARGET_SAFE_2) || \
1779 defined(BDE_BUILD_TARGET_SAFE) || \
1780 !defined(BDE_BUILD_TARGET_OPT) )
1781 #define BSLS_ASSERT_IS_ACTIVE
1782#elif defined(BSLS_REVIEW_IS_ACTIVE)
1783 #define BSLS_ASSERT_IS_REVIEW
1784#elif (defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE) || \
1785 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)) && \
1786 !defined(BSLS_REVIEW_OPT_IS_ACTIVE) && \
1787 !defined(BSLS_REVIEW_IS_ACTIVE) && \
1788 !defined(BSLS_REVIEW_SAFE_IS_ACTIVE)
1789 #define BSLS_ASSERT_IS_ASSUMED
1790#endif
1791
1792// Indicate when 'BSLS_ASSERT' arguments will be ODR-used.
1793#if defined(BSLS_ASSERT_IS_REVIEW) || \
1794 defined(BSLS_ASSERT_IS_ACTIVE) || \
1795 (defined(BSLS_ASSERT_IS_ASSUMED) \
1796 && defined(BSLS_ASSERT_ASSUME_ENABLED)) || \
1797 defined(BSLS_ASSERT_VALIDATE_DISABLED_MACROS)
1798 #define BSLS_ASSERT_IS_USED
1799#endif
1800
1801// Define 'BSLS_ASSERT' accordingly.
1802
1803#if defined(BSLS_ASSERT_IS_ACTIVE)
1804 #define BSLS_ASSERT(X) BSLS_ASSERT_ASSERT_IMP( \
1805 X, \
1806 BloombergLP::bsls::Assert::k_LEVEL_ASSERT)
1807#elif defined(BSLS_ASSERT_IS_REVIEW)
1808 #define BSLS_ASSERT(X) BSLS_REVIEW_REVIEW_IMP( \
1809 X, \
1810 BloombergLP::bsls::Assert::k_LEVEL_ASSERT)
1811#elif defined(BSLS_ASSERT_IS_ASSUMED)
1812 #define BSLS_ASSERT(X) BSLS_ASSERT_ASSUME_IMP( \
1813 X, \
1814 BloombergLP::bsls::Assert::k_LEVEL_ASSERT)
1815#else
1816 #define BSLS_ASSERT(X) BSLS_ASSERT_DISABLED_IMP( \
1817 X, \
1818 BloombergLP::bsls::Assert::k_LEVEL_ASSERT)
1819#endif
1820
1821 // ===============
1822 // BSLS_ASSERT_OPT
1823 // ===============
1824
1825// Determine if 'BSLS_ASSERT_OPT' should be active.
1826
1827// Define the control macros, also usable from client code.
1828#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) || \
1829 defined(BSLS_ASSERT_LEVEL_ASSERT) || \
1830 defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) \
1831 || BSLS_ASSERT_NO_ASSERTION_MACROS_DEFINED
1832 #define BSLS_ASSERT_OPT_IS_ACTIVE
1833#elif defined(BSLS_REVIEW_OPT_IS_ACTIVE)
1834 #define BSLS_ASSERT_OPT_IS_REVIEW
1835#elif (defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE) || \
1836 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT) || \
1837 defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)) && \
1838 !defined(BSLS_REVIEW_OPT_IS_ACTIVE) && \
1839 !defined(BSLS_REVIEW_IS_ACTIVE) && \
1840 !defined(BSLS_REVIEW_SAFE_IS_ACTIVE)
1841 #define BSLS_ASSERT_OPT_IS_ASSUMED
1842#endif
1843
1844// Indicate when 'BSLS_ASSERT_OPT' arguments will be ODR-used.
1845#if defined(BSLS_ASSERT_OPT_IS_REVIEW) || \
1846 defined(BSLS_ASSERT_OPT_IS_ACTIVE) || \
1847 (defined(BSLS_ASSERT_OPT_IS_ASSUMED) \
1848 && defined(BSLS_ASSERT_ASSUME_ENABLED)) || \
1849 defined(BSLS_ASSERT_VALIDATE_DISABLED_MACROS)
1850 #define BSLS_ASSERT_OPT_IS_USED
1851#endif
1852
1853// Define 'BSLS_ASSERT_OPT' accordingly.
1854
1855#if defined(BSLS_ASSERT_OPT_IS_ACTIVE)
1856 #define BSLS_ASSERT_OPT(X) BSLS_ASSERT_ASSERT_IMP( \
1857 X, \
1858 BloombergLP::bsls::Assert::k_LEVEL_OPT)
1859#elif defined(BSLS_ASSERT_OPT_IS_REVIEW)
1860 #define BSLS_ASSERT_OPT(X) BSLS_REVIEW_REVIEW_IMP( \
1861 X, \
1862 BloombergLP::bsls::Assert::k_LEVEL_OPT)
1863#elif defined(BSLS_ASSERT_OPT_IS_ASSUMED)
1864 #define BSLS_ASSERT_OPT(X) BSLS_ASSERT_ASSUME_IMP( \
1865 X, \
1866 BloombergLP::bsls::Assert::k_LEVEL_OPT)
1867#else
1868 #define BSLS_ASSERT_OPT(X) BSLS_ASSERT_DISABLED_IMP( \
1869 X, \
1870 BloombergLP::bsls::Assert::k_LEVEL_OPT)
1871#endif
1872
1873 // ==================
1874 // BSLS_ASSERT_INVOKE
1875 // ==================
1876
1877// 'BSLS_ASSERT_INVOKE' is always active and never in review mode or disabled.
1878#define BSLS_ASSERT_INVOKE(X) do { \
1879 BloombergLP::bsls::AssertViolation violation( \
1880 X, \
1881 BSLS_ASSERTIMPUTIL_FILE, \
1882 BSLS_ASSERTIMPUTIL_LINE, \
1883 BloombergLP::bsls::Assert::k_LEVEL_INVOKE); \
1884 BloombergLP::bsls::Assert::invokeHandler(violation); \
1885 } while (false)
1886
1887// 'BSLS_ASSERT_INVOKE_NORETURN' is always active and guaranteed to never
1888// return (by calling 'bsls::Assert::failByAbort') even if the installed
1889// handler does return. Note that this macro expands into an infinite loop
1890// (that will always terminate the program in its first iteration) in order to
1891// suppress warnings even on platforms that do not understand the
1892// '[[noreturn]]' attribute. Therefore, this macro can be used to implement
1893// code paths that are meant to be unreachable within functions having non-void
1894// return types.
1895#define BSLS_ASSERT_INVOKE_NORETURN(X) do { \
1896 BloombergLP::bsls::AssertViolation violation( \
1897 X, \
1898 BSLS_ASSERTIMPUTIL_FILE, \
1899 BSLS_ASSERTIMPUTIL_LINE, \
1900 BloombergLP::bsls::Assert::k_LEVEL_INVOKE); \
1901 BloombergLP::bsls::Assert::invokeHandlerNoReturn(violation); \
1902 } while (true)
1903
1904 // ===================================
1905 // BSLS_ASSERT_NORETURN_INVOKE_HANDLER
1906 // ===================================
1907
1908#ifdef BSLS_ASSERT_ENABLE_NORETURN_FOR_INVOKE_HANDLER
1909#define BSLS_ASSERT_NORETURN_INVOKE_HANDLER BSLS_ANNOTATION_NORETURN
1910#else
1911#define BSLS_ASSERT_NORETURN_INVOKE_HANDLER
1912#endif
1913
1914// A nested include guard is needed to support the test driver implementation.
1915#ifndef BSLS_ASSERT_RECURSIVELY_INCLUDED_TESTDRIVER_GUARD
1916#define BSLS_ASSERT_RECURSIVELY_INCLUDED_TESTDRIVER_GUARD
1917
1918
1919namespace bsls {
1920
1921 // =====================
1922 // class AssertViolation
1923 // =====================
1924
1925/// This class is an unconstrained *in-core* value-semantic class that
1926/// characterizes the details of a assert failure that has occurred.
1927///
1928/// See @ref bsls_assert
1930
1931 // DATA
1932 const char *d_comment_p; // the comment associated with the violation,
1933 // generally representing the expression that
1934 // failed
1935
1936 const char *d_fileName_p; // the name of the file where the violation
1937 // occurred
1938
1939 int d_lineNumber; // the line number where the violation
1940 // occurred
1941
1942 const char *d_assertLevel_p; // the level and type of the violation that
1943 // occurred, generally one of the 'k_LEVEL'
1944 // constants defined in 'bsls::Review' or
1945 // 'bsls::Assert'
1946
1947 public:
1948 // CREATORS
1949
1950 /// Create a `AssertViolation` with the specified `comment`, `fileName`,
1951 /// `lineNumber`, and `assertLevel`. Note that the supplied
1952 /// `assertLevel` will usually be one of the `k_LEVEL` constants defined
1953 /// in `bsls::Assert`
1955 AssertViolation(const char *comment,
1956 const char *fileName,
1957 int lineNumber,
1958 const char *assertLevel);
1959
1960 // ACCESSORS
1961
1962 /// Return the `assertLevel` attribute of this object.
1963 const char *assertLevel() const;
1964
1965 /// Return the `comment` attribute of this object.
1966 const char *comment() const;
1967
1968 /// Return the `fileName` attribute of this object.
1969 const char *fileName() const;
1970
1971 /// Return the `lineNumber` attribute of this object.
1972 int lineNumber() const;
1973};
1974
1975 // ============
1976 // class Assert
1977 // ============
1978
1979/// This "utility" class maintains a pointer containing the address of the
1980/// current assertion-failure handler function (of type
1981/// `Assert::ViolationHandler`) and provides methods to administer this
1982/// function pointer. The `invokeHandler` method calls the
1983/// currently-installed failure handler. This class also provides a suite
1984/// of standard failure-handler functions that are suitable to be installed
1985/// as the current `Assert::ViolationHandler` function. Note that clients
1986/// are free to install any of these ("off-the-shelf") handlers, or to
1987/// provide their own ("custom") assertion-failure handler functions when
1988/// using this facility. Also note that assertion-failure handler functions
1989/// must not return (i.e., they must `abort`, `exit`, `terminate`, `throw`,
1990/// or hang).
1991///
1992/// Finally, this class defines the constant strings that are passed as the
1993/// `reviewLevel` to the @ref bsls_review handler for checks that failed in
1994/// "review mode" (see {Assertion Modes}).
1995///
1996/// See @ref bsls_assert
1997class Assert {
1998
1999 public:
2000 // TYPES
2001
2002 /// `ViolationHandler` is an alias for a pointer to a function returning
2003 /// `void`, and taking, as a parameter a single `const` reference to a
2004 /// `bsls::AssertViolation` -- e.g.,
2005 /// @code
2006 /// void myHandler(const bsls::AssertViolation&);
2007 /// @endcode
2008 typedef void (*ViolationHandler)(const AssertViolation&);
2009
2010 /// `Handler` is an alias for a pointer to a function returning `void`,
2011 /// and taking, as parameters, two null-terminated strings and an `int`,
2012 /// which is the structure of all assertion-failure handler functions
2013 /// supported by this class -- e.g.,
2014 /// @code
2015 /// void myHandler(const char *text, const char *file, int line);
2016 /// @endcode
2017 typedef void (*Handler)(const char *, const char *, int);
2018
2019 private:
2020 // FRIENDS
2022
2023 // PRIVATE CLASS METHODS
2024
2025 /// Make the specified handler `function` the current assertion-failure
2026 /// handler.
2027 static void setViolationHandlerRaw(Assert::ViolationHandler function);
2028
2029 /// Make the specified `function` the current legacy handler and set the
2030 /// current assertion-failure handler to `failOnViolation`.
2031 static void setFailureHandlerRaw(Assert::Handler function);
2032
2033 /// Get the `comment`, `fileName`, and `lineNumber` from the specified
2034 /// `violation` and pass them to the registered `Handler`. This
2035 /// function exists to provide support for the older signature for
2036 /// assertion-failure handlers specified by `Handler`.
2037 static void failOnViolation(const AssertViolation& violation);
2038
2039 public:
2040 // PUBLIC CONSTANTS
2041
2042 // 'assertLevel' Strings
2043
2044 static const char k_LEVEL_SAFE[];
2045 static const char k_LEVEL_OPT[];
2046 static const char k_LEVEL_ASSERT[];
2047 static const char k_LEVEL_INVOKE[];
2048
2049 // PUBLIC CLASS DATA
2051 // This constant has the value "No".
2052 // See {Assertion Handler Policy}.
2053
2054 // CLASS METHODS
2055
2056 // Administrative Methods
2057
2058 /// Make the specified violation handler `function` the current
2059 /// assertion-failure handler. This method has no effect if the
2060 /// `lockAssertAdministration` method has been called.
2062
2063 /// Make the specified handler `function` the current assertion-failure
2064 /// handler. This method has no effect if the
2065 /// `lockAssertAdministration` method has been called.
2066 static void setFailureHandler(Assert::Handler function);
2067
2068 /// Disable all subsequent calls to `setFailureHandler`. Note that this
2069 /// method has no effect on the behavior of a
2070 /// `AssertFailureHandlerGuard` object.
2072
2073 /// Return the address of the currently installed assertion-failure
2074 /// handler function if it is a `Handler` (and not a
2075 /// `ViolationHandler`); otherwise, return `NULL`.
2077
2078 /// Return the address of the currently installed assertion-failure
2079 /// handler function.
2081
2082 // Dispatcher Method (called from within macros)
2083
2085 /// Invoke the currently installed assertion-failure handler function
2086 /// with the specified `violation`. The behavior is undefined if the
2087 /// macro `BSLS_ASSERT_ENABLE_NORETURN_FOR_INVOKE_HANDLER` is defined,
2088 /// and the currently installed assertion-failure handler function
2089 /// returns to the caller (i.e., the assertion handler does *not*
2090 /// `abort`, `exit`, `terminate`, `throw`, or hang). Note that this
2091 /// function is intended for use by the (BSLS) "ASSERT" macros, but may
2092 /// also be called by clients directly as needed (preferably with
2093 /// `BSLS_ASSERT_INVOKE`). Also note that the configuration macro
2094 /// `BSLS_ASSERT_ENABLE_NORETURN_FOR_INVOKE_HANDLER` is intended to
2095 /// support static analysis tools, which require an annotation to see
2096 /// that a failed "ASSERT" prevents further execution of a function with
2097 /// "bad" values.
2098 static void invokeHandler(const AssertViolation& violation);
2099
2101 /// @deprecated Use @ref invokeHandler(const AssertViolation&) instead.
2102 ///
2103 /// Invoke the currently installed assertion-failure handler function
2104 /// with the specified expression `text`, `file` name, and `line` number
2105 /// as its arguments. The behavior is undefined if the macro
2106 /// `BSLS_ASSERT_ENABLE_NORETURN_FOR_INVOKE_HANDLER` is defined, and the
2107 /// currently installed assertion-failure handler function returns to
2108 /// the caller (i.e., the assertion handler does *not* `abort`, `exit`,
2109 /// `terminate`, `throw`, or hang). Note that this function is
2110 /// deprecated, as the (BSLS) "ASSERT" macros all now use the
2111 /// `bsls::AssertViolation` overload of `invokeHandler` instead.
2112 static void invokeHandler(const char *text, const char *file, int line);
2113
2114 /// Invoke the currently installed assertion-failure handler function
2115 /// with the specified `violation`. If the handler returns normally,
2116 /// invoke `bsls::Assert::failByAbort`.
2118 static void invokeHandlerNoReturn(const AssertViolation &violation);
2119
2120#ifdef BSLS_ASSERT_USE_CONTRACTS
2121 static void invokeLanguageContractHandler(
2122 const std::contract_violation& violation);
2123 // Call 'invokeHandler' with an 'AssertViolation' with properties from
2124 // the specified 'violation'.
2125#endif
2126
2127 // Standard Assertion-Failure Handlers
2128
2129 /// (Default Handler) Emulate the invocation of the standard `assert`
2130 /// macro with a `false` argument, using the expression `comment`,
2131 /// `file` name, and `line` number from the specified `violation` to
2132 /// generate a helpful output message and then, after logging,
2133 /// unconditionally aborting. Note that this handler function is the
2134 /// default installed assertion handler.
2136 static void failByAbort(const AssertViolation& violation);
2137
2138 /// Use the expression `comment`, `file` name, and `line` number from
2139 /// the specified `violation` to generate a helpful output message and
2140 /// then, after logging, spin in an infinite loop. Note that this
2141 /// handler function is useful for hanging a process so that a debugger
2142 /// may be attached to it.
2144 static void failBySleep(const AssertViolation& violation);
2145
2146 /// Throw an `AssertTestException` whose attributes are the `comemnt`,
2147 /// `file`, `line`, and `level` from the specified `violation` provided
2148 /// that `BDE_BUILD_TARGET_EXC` is defined; otherwise, log an
2149 /// appropriate message and abort the program (similar to
2150 /// `failByAbort`).
2152 static void failByThrow(const AssertViolation& violation);
2153
2154 /// @deprecated Use @ref failByAbort instead.
2155 ///
2156 /// Emulate the invocation of the standard `assert` macro with a `false`
2157 /// argument, using the specified expression `comment`, `file` name, and
2158 /// `line` number to generate a helpful output message and then, after
2159 /// logging, unconditionally aborting.
2161 static void failAbort(const char *comment, const char *file, int line);
2162
2163 /// @deprecated Use @ref failBySleep instead.
2164 ///
2165 /// Use the specified expression `comment`, `file` name, and `line`
2166 /// number to generate a helpful output message and then, after logging,
2167 /// spin in an infinite loop. Note that this handler function is useful
2168 /// for hanging a process so that a debugger may be attached to it.
2170 static void failSleep(const char *comment, const char *file, int line);
2171
2172 /// @deprecated Use @ref failByThrow instead.
2173 ///
2174 /// Throw an `AssertTestException` whose attributes are the specified
2175 /// `comemnt`, `file`, `line`, and `level` provided that
2176 /// `BDE_BUILD_TARGET_EXC` is defined; otherwise, log an appropriate
2177 /// message and abort the program (similar to `failAbort`).
2179 static void failThrow(const char *comment, const char *file, int line);
2180
2181
2182 // Assertion Handler Policy Enforcement
2183
2184 /// Return `true` if `k_permitOutOfPolicyReturningAssertionBuildKey`
2185 /// does not have the value "bsls-PermitOutOfPolicyReturn" or
2186 /// `permitOutOfPolicyReturningFailureHandler` has not previously been
2187 /// invoked, and `false` otherwise. Note that returning `true`
2188 /// indicates that `bsls::Assert` should abort the task if the currently
2189 /// installed assertion-failure handler returns normally (after the
2190 /// detection of a failed assertion).
2192
2193 /// DO NOT USE! It is a violation of Bloomberg policy to invoke this
2194 /// function without having prior authorization from senior management.
2195 ///
2196 /// Allow an assertion handler to return control to the calling function
2197 /// (after a failed assertion). The behavior is undefined if
2198 /// `BSLS_ASSERT_ENABLE_NORETURN_FOR_INVOKE_HANDLER` is defined (and
2199 /// thus `invokeHandler` would not be able to return anyway). Note
2200 /// that, by default, an assertion handler that attempts to return
2201 /// normally will cause the program to be aborted.
2202 ///
2203 /// Internal Bloomberg users should contact the BDE team if they feel
2204 /// their application might need to violate Bloomberg policy by allowing
2205 /// the currently installed assertion handler to return normally (after
2206 /// a failed assertion).
2208};
2209
2210 // ===============================
2211 // class AssertFailureHandlerGuard
2212 // ===============================
2213
2214/// An object of this class saves the current assert handler and installs
2215/// the one specified on construction. On destruction, the original assert
2216/// handler is restored. Note that two objects of this class cannot be
2217/// safely used concurrently from two separate threads (but may of course
2218/// appear sequentially, including in nested blocks and function invocations
2219/// within a single thread). Note that the behavior of objects of this
2220/// class is unaffected by the (`static`) `Assert::lockAssertAdministration`
2221/// method (i.e., the temporary replacement will occur, regardless of
2222/// whether that method has been invoked.)
2223///
2224/// See @ref bsls_assert
2226
2227 // DATA
2228 Assert::ViolationHandler d_original; // original handler
2229 Assert::Handler d_legacyOriginal; // original legacy handler
2230
2231 private:
2232 // NOT IMPLEMENTED
2235
2236 public:
2237 // CREATORS
2238
2240 /// Create a guard object that installs the specified `temporary`
2241 /// failure handler and automatically restores the original handler on
2242 /// destruction.
2244
2245 /// Restore the failure handler that was in place when this object was
2246 /// created and destroy this guard.
2248};
2249
2250} // close package namespace
2251
2252#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
2253
2254// ============================================================================
2255// BACKWARD COMPATIBILITY
2256// ============================================================================
2257
2258// BDE_VERIFY pragma: push
2259// BDE_VERIFY pragma: -SLM01
2260// BDE_VERIFY pragma: -CP01
2261// BDE_VERIFY pragma: -TR04
2262// BDE_VERIFY pragma: -TR17
2263
2264#ifndef BDE_OMIT_INTERNAL_DEPRECATED
2265 // =========================
2266 // BDE_ASSERT_H (deprecated)
2267 // =========================
2268
2269// Active in "Safe Mode"
2270
2271#define BDE_ASSERT_H(X) BSLS_ASSERT_SAFE(X)
2272#define BSL_ASSERT_H(X) BSLS_ASSERT_SAFE(X) // introduced during migration
2273
2274 // ===========================
2275 // BDE_ASSERT_CPP (deprecated)
2276 // ===========================
2277
2278// Active in "Safe Mode" and "Debug Mode"
2279
2280#define BDE_ASSERT_CPP(X) BSLS_ASSERT(X)
2281#define BSL_ASSERT_CPP(X) BSLS_ASSERT(X) // introduced during migration
2282
2283/// This alias is defined for backward compatibility.
2285
2286/// This alias is defined for backward compatibility.
2288
2289 // ==========================
2290 // BSLS_ASSERT_H (deprecated)
2291 // ==========================
2292
2293// Old 'BSLS_ASSERT' implementation macro that was incorrectly used externally.
2294
2295#define BSLS_ASSERT_ASSERT(X) BSLS_ASSERT_ASSERT_IMP( \
2296 X, \
2297 BloombergLP::bsls::Assert::k_LEVEL_ASSERT)
2298
2299#endif // BDE_OMIT_INTERNAL_DEPRECATED
2300
2301/// This alias is defined for backward compatibility.
2303
2304/// This alias is defined for backward compatibility.
2306
2307#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
2308
2309// BDE_VERIFY pragma: pop
2310
2311// ============================================================================
2312// INLINE FUNCTION DEFINITIONS
2313// ============================================================================
2314
2315namespace bsls {
2316 // ---------------------
2317 // class AssertViolation
2318 // ---------------------
2319
2320// CREATORS
2322inline
2324 const char *fileName,
2325 int lineNumber,
2326 const char *assertLevel)
2327: d_comment_p((comment == 0) ? "" : comment)
2328, d_fileName_p((fileName == 0) ? "" : fileName)
2329, d_lineNumber(lineNumber)
2330, d_assertLevel_p((assertLevel == 0) ? "" : assertLevel)
2331{
2332}
2333
2334// ACCESSORS
2335inline
2337{
2338 return d_assertLevel_p;
2339}
2340
2341inline
2342const char *AssertViolation::comment() const
2343{
2344 return d_comment_p;
2345}
2346
2347inline
2348const char *AssertViolation::fileName() const
2349{
2350 return d_fileName_p;
2351}
2352
2353inline
2355{
2356 return d_lineNumber;
2357}
2358
2359} // close package namespace
2360
2361
2362#endif // deeper include guard
2363
2364 // ========================================================
2365 // UNDEFINE THE LOCALLY-SCOPED IMPLEMENTATION DETAIL MACROS
2366 // ========================================================
2367
2368#undef BSLS_ASSERT_NORETURN_INVOKE_HANDLER
2369#undef BSLS_ASSERT_NO_ASSERTION_MACROS_DEFINED
2370#undef BSLS_ASSERT_ASSUME_ENABLED
2371
2372 // =========================================
2373 // IMPLEMENTATION USING THE C++ PREPROCESSOR
2374 // =========================================
2375//
2376// At most one of the following build options may be set during the compilation
2377// of any component that includes 'bsls_assert.h':
2378//..
2379// BSLS_ASSERT_LEVEL_ASSERT_SAFE
2380// BSLS_ASSERT_LEVEL_ASSERT
2381// BSLS_ASSERT_LEVEL_ASSERT_OPT
2382// BSLS_ASSERT_LEVEL_NONE
2383// BSLS_ASSERT_LEVEL_ASSUME_SAFE
2384// BSLS_ASSERT_LEVEL_ASSUME_ASSERT
2385// BSLS_ASSERT_LEVEL_ASSUME_OPT
2386//..
2387// ----------------------------------------------------------------------------
2388
2389#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) && \
2390 defined(BSLS_ASSERT_LEVEL_ASSERT)
2391#error incompatible BSLS_ASSERT levels: \
2392..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSERT
2393#endif
2394
2395#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) && \
2396 defined(BSLS_ASSERT_LEVEL_ASSERT_OPT)
2397#error incompatible BSLS_ASSERT levels: \
2398..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSERT_OPT
2399#endif
2400
2401#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) && \
2402 defined(BSLS_ASSERT_LEVEL_NONE)
2403#error incompatible BSLS_ASSERT levels: \
2404..._LEVEL_ASSERT_SAFE and ..._LEVEL_NONE
2405#endif
2406
2407#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) && \
2408 defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)
2409#error incompatible BSLS_ASSERT levels: \
2410..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSUME_OPT
2411#endif
2412
2413#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) && \
2414 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
2415#error incompatible BSLS_ASSERT levels: \
2416..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSUME_ASSERT
2417#endif
2418
2419#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) && \
2420 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
2421#error incompatible BSLS_ASSERT levels: \
2422..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSUME_SAFE
2423#endif
2424
2425#if defined(BSLS_ASSERT_LEVEL_ASSERT) && \
2426 defined(BSLS_ASSERT_LEVEL_ASSERT_OPT)
2427#error incompatible BSLS_ASSERT levels: \
2428..._LEVEL_ASSERT and ..._LEVEL_ASSERT_OPT
2429#endif
2430
2431#if defined(BSLS_ASSERT_LEVEL_ASSERT) && \
2432 defined(BSLS_ASSERT_LEVEL_NONE)
2433#error incompatible BSLS_ASSERT levels: \
2434..._LEVEL_ASSERT and ..._LEVEL_NONE
2435#endif
2436
2437#if defined(BSLS_ASSERT_LEVEL_ASSERT) && \
2438 defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)
2439#error incompatible BSLS_ASSERT levels: \
2440..._LEVEL_ASSERT and ..._LEVEL_ASSUME_OPT
2441#endif
2442
2443#if defined(BSLS_ASSERT_LEVEL_ASSERT) && \
2444 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
2445#error incompatible BSLS_ASSERT levels: \
2446..._LEVEL_ASSERT and ..._LEVEL_ASSUME_ASSERT
2447#endif
2448
2449#if defined(BSLS_ASSERT_LEVEL_ASSERT) && \
2450 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
2451#error incompatible BSLS_ASSERT levels: \
2452..._LEVEL_ASSERT and ..._LEVEL_ASSUME_SAFE
2453#endif
2454
2455#if defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) && \
2456 defined(BSLS_ASSERT_LEVEL_NONE)
2457#error incompatible BSLS_ASSERT levels: \
2458..._LEVEL_ASSERT_OPT and ..._LEVEL_NONE
2459#endif
2460
2461#if defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) && \
2462 defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)
2463#error incompatible BSLS_ASSERT levels: \
2464..._LEVEL_ASSERT_OPT and ..._LEVEL_ASSUME_OPT
2465#endif
2466
2467#if defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) && \
2468 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
2469#error incompatible BSLS_ASSERT levels: \
2470..._LEVEL_ASSERT_OPT and ..._LEVEL_ASSUME_ASSERT
2471#endif
2472
2473#if defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) && \
2474 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
2475#error incompatible BSLS_ASSERT levels: \
2476..._LEVEL_ASSERT_OPT and ..._LEVEL_ASSUME_SAFE
2477#endif
2478
2479#if defined(BSLS_ASSERT_LEVEL_NONE) && \
2480 defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)
2481#error incompatible BSLS_ASSERT levels: \
2482..._LEVEL_NONE and ..._LEVEL_ASSUME_OPT
2483#endif
2484
2485#if defined(BSLS_ASSERT_LEVEL_NONE) && \
2486 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
2487#error incompatible BSLS_ASSERT levels: \
2488..._LEVEL_NONE and ..._LEVEL_ASSUME_ASSERT
2489#endif
2490
2491#if defined(BSLS_ASSERT_LEVEL_NONE) && \
2492 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
2493#error incompatible BSLS_ASSERT levels: \
2494..._LEVEL_NONE and ..._LEVEL_ASSUME_SAFE
2495#endif
2496
2497#if defined(BSLS_ASSERT_LEVEL_ASSUME_OPT) && \
2498 defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
2499#error incompatible BSLS_ASSERT levels: \
2500..._LEVEL_ASSUME_OPT and ..._LEVEL_ASSUME_ASSERT
2501#endif
2502
2503#if defined(BSLS_ASSERT_LEVEL_ASSUME_OPT) && \
2504 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
2505#error incompatible BSLS_ASSERT levels: \
2506..._LEVEL_ASSUME_OPT and ..._LEVEL_ASSUME_SAFE
2507#endif
2508
2509#if defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT) && \
2510 defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
2511#error incompatible BSLS_ASSERT levels: \
2512..._LEVEL_ASSUME_ASSERT and ..._LEVEL_ASSUME_SAFE
2513#endif
2514
2515#endif
2516
2517// ----------------------------------------------------------------------------
2518// Copyright 2018 Bloomberg Finance L.P.
2519//
2520// Licensed under the Apache License, Version 2.0 (the "License");
2521// you may not use this file except in compliance with the License.
2522// You may obtain a copy of the License at
2523//
2524// http://www.apache.org/licenses/LICENSE-2.0
2525//
2526// Unless required by applicable law or agreed to in writing, software
2527// distributed under the License is distributed on an "AS IS" BASIS,
2528// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2529// See the License for the specific language governing permissions and
2530// limitations under the License.
2531// ----------------------------- END-OF-FILE ----------------------------------
2532
2533/** @} */
2534/** @} */
2535/** @} */
Definition bsls_assert.h:2225
AssertFailureHandlerGuard(Assert::Handler temporary)
AssertFailureHandlerGuard(Assert::ViolationHandler temporary)
Definition bsls_assert.h:1929
BSLS_KEYWORD_CONSTEXPR AssertViolation(const char *comment, const char *fileName, int lineNumber, const char *assertLevel)
Definition bsls_assert.h:2323
int lineNumber() const
Return the lineNumber attribute of this object.
Definition bsls_assert.h:2354
const char * comment() const
Return the comment attribute of this object.
Definition bsls_assert.h:2342
const char * assertLevel() const
Return the assertLevel attribute of this object.
Definition bsls_assert.h:2336
const char * fileName() const
Return the fileName attribute of this object.
Definition bsls_assert.h:2348
Definition bsls_assert.h:1997
static Assert::ViolationHandler violationHandler()
static BSLS_ANNOTATION_NORETURN void invokeHandlerNoReturn(const AssertViolation &violation)
static BSLS_ANNOTATION_NORETURN void failSleep(const char *comment, const char *file, int line)
static const char k_LEVEL_ASSERT[]
Definition bsls_assert.h:2046
static void setViolationHandler(Assert::ViolationHandler function)
static void lockAssertAdministration()
static const char k_LEVEL_SAFE[]
Definition bsls_assert.h:2044
static Assert::Handler failureHandler()
static BSLS_ASSERT_NORETURN_INVOKE_HANDLER void invokeHandler(const char *text, const char *file, int line)
static BSLS_ANNOTATION_NORETURN void failByThrow(const AssertViolation &violation)
static BSLS_ANNOTATION_NORETURN void failBySleep(const AssertViolation &violation)
static bool abortUponReturningAssertionFailureHandler()
static void setFailureHandler(Assert::Handler function)
static BSLS_ANNOTATION_NORETURN void failAbort(const char *comment, const char *file, int line)
static BSLS_ANNOTATION_NORETURN void failByAbort(const AssertViolation &violation)
static void permitOutOfPolicyReturningFailureHandler()
void(* Handler)(const char *, const char *, int)
Definition bsls_assert.h:2017
static BSLS_ASSERT_NORETURN_INVOKE_HANDLER void invokeHandler(const AssertViolation &violation)
static const char k_LEVEL_INVOKE[]
Definition bsls_assert.h:2047
static const char k_LEVEL_OPT[]
Definition bsls_assert.h:2045
void(* ViolationHandler)(const AssertViolation &)
Definition bsls_assert.h:2008
static const char * k_permitOutOfPolicyReturningAssertionBuildKey
Definition bsls_assert.h:2050
static BSLS_ANNOTATION_NORETURN void failThrow(const char *comment, const char *file, int line)
#define BSLS_ANNOTATION_NORETURN
Definition bsls_annotation.h:383
bsls::Assert bsls_Assert
This alias is defined for backward compatibility.
Definition bsls_assert.h:2302
bsls::AssertFailureHandlerGuard bsls_AssertFailureHandlerGuard
This alias is defined for backward compatibility.
Definition bsls_assert.h:2305
bsls::AssertFailureHandlerGuard bdes_AssertFailureHandlerGuard
This alias is defined for backward compatibility.
Definition bsls_assert.h:2287
#define BSLS_ASSERT_NORETURN_INVOKE_HANDLER
Definition bsls_assert.h:1911
bsls::Assert bdes_Assert
This alias is defined for backward compatibility.
Definition bsls_assert.h:2284
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_CONSTEXPR
Definition bsls_keyword.h:588
Definition bdlt_iso8601util.h:691