// bsls_assert.h                                                      -*-C++-*-
#ifndef INCLUDED_BSLS_ASSERT
#define INCLUDED_BSLS_ASSERT

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide build-specific, runtime-configurable assertion macros.
//
//@CLASSES:
//  bsls::Assert: namespace for "assert" management functions
//  bsls::AssertFailureHandlerGuard: scoped guard for changing handlers safely
//  bsls::AssertViolation: attributes describing a failed assertion
//
//@MACROS:
//  BSLS_ASSERT: runtime check typically enabled in non-opt build modes
//  BSLS_ASSERT_SAFE: runtime check typically only enabled in safe build modes
//  BSLS_ASSERT_OPT: runtime check typically enabled in all build modes
//  BSLS_ASSERT_INVOKE: for directly invoking the current failure handler
//  BSLS_ASSERT_INVOKE_NORETURN: direct invocation always marked to not return
//
//@SEE_ALSO: bsls_review, bsls_asserttest
//
//@DESCRIPTION: This component provides three "assert-like" macros,
// 'BSLS_ASSERT', 'BSLS_ASSERT_SAFE', and 'BSLS_ASSERT_OPT', that can be used
// to enable optional *redundant* runtime checks in corresponding build modes.
// If an assertion argument evaluates to 0, a runtime-configurable "handler"
// function is invoked with a 'bsls::AssertViolation', a value-semantic class
// that encapsulates the current filename, line number, level of failed check,
// and (0-valued expression) argument text.
//
// The class 'bsls::Assert' provides functions for manipulating the globally
// configured "handler".  A scoped guard for setting and restoring the assert
// handler is provided by 'bsls::AssertFailureHandlerGuard'.
//
// An additional macro, 'BSLS_ASSERT_INVOKE', is provided for direct invocation
// of the current assertion failure handler.  This macro is always enabled
// (i.e., regardless of build mode).
//
///Defensive Programming (DP)
///--------------------------
// Although there is no one agreed-upon definition, in this context we will use
// the term *Defensive* *Programming* (DP) to mean any attempt by the component
// author to provide (optional) runtime validation of the preconditions (or
// invariants) defined in the function-level documentation (contract) for that
// component.  Note that DP is intended to help expose defects early in the
// development process, and *never* to mask or recover from them in production.
//
// Calling a function without satisfying its preconditions results in
// *undefined* *behavior*.  Detecting and reporting undefined behavior due to
// client misuse can sometimes be very helpful at identifying subtle errors.
// Additionally, we may choose to embed redundant (i.e., logically superfluous)
// runtime checks -- both as a form of active documentation, and also to help
// expose our own, latent coding errors that have escaped detection during
// testing.  In either case, these *defensive* (and other) runtime checks can
// add significant overhead.  Hence, this extra runtime overhead should not
// necessarily be incorporated for every build target and assertion mode (see
// "Build Modes" below).  Moreover, the extent of these checks may change
// (i.e., for a particular build mode) from one release to the next.
// Therefore, any defensive (or other redundant) checks provided for a
// particular build mode are *NEVER* part of the function-level contract -- and
// remain solely what is known as a *Quality-of-Implementation* (QoI) issue.
//
///Assertion Semantics
///-------------------
// There are three important aspects of assertions: (1) !Every! !assertion!
// !is! !redundant!; it is essential that if all assertions are compiled out of
// a program that is defect-free, apart from improved runtime performance, the
// program behaves identically.  Hence, (2) !each! !boolean-valued! !assert!
// !argument! !must! !have! !no! !side-effects!.  Finally, (3) !assertions!
// !do! !not! !affect! !binary! !compatibility!; hence, translation units with
// different assertion levels (but not necessarily build targets) can safely be
// combined into a single program (see "Build Modes" and "Assertions in Header
// Files" below).  Note that the build target 'BDE_BUILD_TARGET_SAFE_2' does
// permit binary incompatibility for conditionally compiled source code, but
// there is no corresponding 'BSLS_ASSERT_SAFE_2' assertion macro (see {Usage}
// below).
//
///Assertion Modes
///---------------
// Depending on the build, assertion macros can expand in 3 different ways:
//
//: 1 A 'bsls_assert' macro is "enabled in assert mode", or simply "enabled" if
//:   it expands to check its predicate and call the assert failure handler
//:   when it is false.
//:
//: 2 A 'bsls_assert' macro is "enabled in review mode", or simply "in review
//:   mode" if it expands to check its predicate and call the *review* failure
//:   handler when it is false.  This is identical to a 'bsls_review' macro of
//:   the same level when it is enabled.
//:
//: 3 A 'bsls_assert' macro is "disabled" if it expands to do nothing,
//:   producing no executed code in the compiled program.
//
///Review Mode
///-----------
// The ability to enable assertions in review mode allows clients to easily and
// safely test, in a production environment, whether assertions having a lower
// threshold than what they currently have deployed are being triggered
// (without terminating the application).  It is intended as an interim step
// towards lowering the assertion level threshold for an existing application.
// See {'bsls_review'} for a more detailed description of the behavior of
// assertions in review mode and suggested workflows for using this behavior.
//
///Detailed Behavior
///-----------------
// If an assertion fires (i.e., due to a 0-valued expression argument in an
// assert macro that is enabled or in review mode), there is a violation of the
// contract that the assertion is checking.  If the assertion is enabled, the
// goal of the assertion is to report the precise location and nature of the
// defect *quickly* and *loudly* and prevent continued execution of the calling
// function past that point.  If the assertion is in review mode then the
// behavior will match the corresponding 'bsls_review' macro and execution
// might continue, which has a priority of just logging the failure location.
//
// When enabled, the assert macros will all do essentially the same thing: Each
// macro tests the predicate expression 'X', and if '!(X)' is 'true', invokes
// the currently installed assertion failure handler.  An instance of
// 'bsls::AssertViolation' will be created and populated with a textual
// rendering of the predicate ('#X'), the current '__FILE__', the current
// '__LINE__', and a string representing which particular type of assertion has
// failed.  This 'violation' is then passed to the currently installed
// assertion failure handler (a function pointer with the type
// 'bsls::Assert::ViolationHandler' having the signature:
//..
//  void(const bsls::AssertViolation&);
//..
//
// On some (currently experimental) platforms with support for some form of the
// upcoming language-level contract facilities there is also the ability to
// configure the assertion macros to introduce an assumption of the truth of
// their predicate.  With this option the predicate will not neccesarily even
// be evaluated, and if it were to return false the compiler will treat the
// situation as undefined behavior ("impossible").  This mode for assertions
// can lead to improved code generation, but be aware that the potential
// downside of being wrong about the truth of your assertions is unbounded, and
// so deploying applications built with any assertions assumed should be done
// with great care - there are no guarantees about anything a program will do
// when an assumed assertion is violated.
//
///Selecting Which ASSERT Macro to Use
///-----------------------------------
// The choice of which specific macro to use is governed primarily by the
// impact that enabling the assertion (in either assert mode or review mode)
// will have on the runtime performance of the function, and in some cases on
// the size of the function.
//
//: 1 BSLS_ASSERT_SAFE - This macro should be reserved for tests incurring an
//:   expensive change to the performance of a function, either a very high
//:   constant time increase in execution time of the function, or an increase
//:   in the algorithmic complexity of a function.  Note especially that a
//:   change in algorithmic complexity breaks the documented contract of many
//:   functions (e.g., an 'O(n)' check in a function with a documented
//:   'O(log(n))' runtime speed) and so checks with that level of cost should
//:   be reserved for diagnostic use in "safe" builds.
//:
//: 2 BSLS_ASSERT - For "inexpensive" checks with only a constant factor
//:   overhead.  The majority of checks should fall into this category.
//:
//: 3 BSLS_ASSERT_OPT - For "negligible" checks that have little to no
//:   measurable overhead on a function.  This will often be the case for
//:   argument checking in larger functions, or very simple checks in smaller
//:   functions.  Keep in mind that these checks will be enabled in all
//:   typically deployed build modes, so they should be reserved for larger
//:   functions and functions that will not be called in highly performance
//:   critical code.
//
///Assertion and Review Levels
///---------------------------
// There are a few macros available to control which of the 'bsls_assert'
// macros are disabled, enabled in review mode, or enabled in assert mode (see
// {Assertion Modes} above).  These macros are for the compilation and build
// environment to provide and are not themselves defined by BDE code -- e.g.,
// by supplying one or more of these macros with '-D' options on the compiler
// command line.  In general, these macros are used to determine an
// 'ASSERT_LEVEL' that can be (from most aggressive/optimized to safest)
// 'ASSUME_SAFE', 'ASSUME_ASSERT', 'ASSUME_OPT', 'NONE', 'ASSERT_OPT',
// 'ASSERT', or 'ASSERT_SAFE'.  Separately, a 'REVIEW_LEVEL' is determined that
// can be 'NONE', 'REVIEW_OPT', 'REVIEW', or 'REVIEW_SAFE'.  Depending on these
// levels, the various 'bsls_assert' macros will be enabled, in review mode,
// assumed, or disabled.  Macros up to the assert level will be enabled.  If
// the review level is higher than the assert level then macros up to the
// review level (and above the assert level) will be enabled in review mode.
// Finally, macros higher than both the review level and the assert level will
// be disabled.  If the review level is 'NONE' and the assert level is set to
// one of the assume levels, then macros that would be disabled up to the
// assumed level are instead assumed.  If there is a review level set then no
// macros will ever be assumed.  The following table illustrates this:
//..
//  ===========================================
//   Macro Instantiation Based on Review Level
//  ===========================================
//  ENABLED   - Assertion is enabled (in "assert mode")
//  REVIEW    - Assertion is enabled (in "review mode")
//  ASSUMED   - Assertion is assumed (if supported)
//  <blank>   - Assertion is ignored
//  -----------BSLS... LEVELS----------  ----------BSLS_.. MACROS---------
//  BSLS_ASSERT_LEVEL BSLS_REVIEW_LEVEL  ASSERT_OPT ASSERT     ASSERT_SAFE
//  ----------------- -----------------  ---------- ---------- -----------
//  ASSUME_SAFE       NONE               ASSUMED    ASSUMED    ASSUMED
//  ASSUME_ASSERT     NONE               ASSUMED    ASSUMED
//  ASSUME_OPT        NONE               ASSUMED
//  NONE              NONE
//  NONE (or ASSUME*) REVIEW_OPT         REVIEW
//  NONE (or ASSUME*) REVIEW             REVIEW     REVIEW
//  NONE (or ASSUME*) REVIEW_SAFE        REVIEW     REVIEW     REVIEW
//  ASSERT_OPT        NONE               ENABLED
//  ASSERT_OPT        REVIEW_OPT         ENABLED
//  ASSERT_OPT        REVIEW             ENABLED    REVIEW
//  ASSERT_OPT        REVIEW_SAFE        ENABLED    REVIEW     REVIEW
//  ASSERT            NONE               ENABLED    ENABLED
//  ASSERT            REVIEW_OPT         ENABLED    ENABLED
//  ASSERT            REVIEW             ENABLED    ENABLED
//  ASSERT            REVIEW_SAFE        ENABLED    ENABLED    REVIEW
//  ASSERT_SAFE       NONE               ENABLED    ENABLED    ENABLED
//  ASSERT_SAFE       REVIEW_OPT         ENABLED    ENABLED    ENABLED
//  ASSERT_SAFE       REVIEW             ENABLED    ENABLED    ENABLED
//  ASSERT_SAFE       REVIEW_SAFE        ENABLED    ENABLED    ENABLED
//..
// See {'bsls_review'} for the logic that determines the review level.  The
// logic that determines the assertion level checks a few different macros.
// The first check is for one of the 7 mutually exclusive 'BSLS_ASSERT_LEVEL'
// macros that can explicitly set the assert level:
//..
//  MACRO                           BSLS_ASSERT_LEVEL
//  -----                           ----------------
//  BSLS_ASSERT_LEVEL_ASSUME_SAFE   ASSUME_SAFE
//  BSLS_ASSERT_LEVEL_ASSUME_ASSERT ASSUME_ASSERT
//  BSLS_ASSERT_LEVEL_ASSUME_OPT    ASSUME_OPT
//  BSLS_ASSERT_LEVEL_NONE          NONE
//  BSLS_ASSERT_LEVEL_ASSERT_OPT    ASSERT_OPT
//  BSLS_ASSERT_LEVEL_ASSERT        ASSERT
//  BSLS_ASSERT_LEVEL_ASSERT_SAFE   ASSERT_SAFE
//..
// If none of these are defined, the assert level is determined by the build
// mode.  With "safer" build modes we incorporate higher level defensive
// checks.  A particular build mode is implied by the relevant (BDE) build
// targets that are defined at compilation (preprocessing) time.  The following
// table shows the three (BDE) build targets that can affect the assertion and
// review levels:
//..
//        (BDE) Build Targets
//      -----------------------
//  (A) BDE_BUILD_TARGET_SAFE_2
//  (B) BDE_BUILD_TARGET_SAFE
//  (C) BDE_BUILD_TARGET_OPT
//..
// *Any* of the 8 possible combinations of the three build targets is valid:
// e.g., 'BDE_BUILD_TARGET_OPT' and 'BDE_BUILD_TARGET_SAFE_2' may both be
// defined.  The following table shows the assert level that is set depending
// on which combination of build target macros have been set:
//..
//   =========================================================
//   "ASSERT" Level Set With no Level-Overriding Flags defined
//   =========================================================
//  --- BDE_BUILD_TARGET ----   BSLS_ASSERT_LEVEL
//  _SAFE_2   _SAFE    _OPT
//  -------  -------  -------   -----------------
//                              ASSERT
//                    DEFINED   ASSERT_OPT
//           DEFINED            ASSERT_SAFE
//           DEFINED  DEFINED   ASSERT_SAFE
//  DEFINED                     ASSERT_SAFE
//  DEFINED           DEFINED   ASSERT_SAFE
//  DEFINED  DEFINED            ASSERT_SAFE
//  DEFINED  DEFINED  DEFINED   ASSERT_SAFE
//..
// As the table above illustrates, with no build target explicitly defined the
// assert level defaults to 'ASSERT'.  If only 'BDE_BUILD_TARGET_OPT' is
// defined, the assert level will be set to 'ASSERT_OPT'.  If either
// 'BDE_BUILD_TARGET_SAFE' or 'BDE_BUILD_TARGET_SAFE_2' is defined then the
// assert level is set to 'ASSERT_SAFE' and ALL assert macros will be enabled.
//
///Runtime-Configurable Assertion-Failure Behavior
///-----------------------------------------------
// In addition to the three (BSLS) "ASSERT" macros, 'BSLS_ASSERT',
// 'BSLS_ASSERT_SAFE', and 'BSLS_ASSERT_OPT', and the immediate invocation
// macro 'BSLS_ASSERT_INVOKE', this component provides (1) an 'invokeHandler'
// method used (primarily) to implement these "ASSERT" macros and enable their
// runtime configuration, (2) administration methods to configure, at runtime,
// the behavior resulting from an assertion failure (i.e., by installing an
// appropriate assertion-failure handler function), and (3) a suite of standard
// ("off-the-shelf") assertion-failure handler functions, to be installed via
// the administrative methods (if desired), and invoked by the 'invokeHandler'
// method on an assertion failure.
//
// When an enabled assertion fails, the currently installed *failure* *handler*
// ("callback") function is invoked.  The default handler is the ('static')
// 'bsls::Assert::failByAbort' method; a user may replace this default handler
// by using the ('static') 'bsls::Assert::setViolationHandler' administrative
// method and passing it (the address of) a function whose signature conforms
// to the 'bsls::Assert::ViolationHandler' 'typedef'.  This handler may be one
// of the other handler methods provided in 'bsls::Assert', or a new "custom"
// function, written by the user (see {Usage} below).
//
///Exception-Throwing Failure Handlers and 'bsls::AssertFailureHandlerGuard'
///-------------------------------------------------------------------------
// Among the failure handlers provided is 'bsls::Assert::failByThrow', which
// throws a 'bsls::AssertTestException' object.  Throwing an exception,
// however, is not safe in all environments and deliberately aborting is more
// useful in a debugging context than throwing an unhandled exception.  Hence,
// in order for an 'bsls::AssertTestException' object to be thrown on an
// assertion failure, the user must first install the
// 'bsls::Assert::failByThrow' handler (or another exception-throwing handler)
// explicitly.
//
// Note that an object of type 'bsls::AssertFailureHandlerGuard' can be used to
// temporarily set an exception-throwing handler within a 'try' block,
// automatically restoring the previous handler when the 'try' block exits (see
// {Usage} below).
//
///Assertion Handler Policy
///------------------------
// Bloomberg policy is that (by default) tasks may not install an assertion
// handler that returns control to the point immediately following the
// detection of a failed assertion.  So an assertion handler may, for example,
// terminate the task or throw an exception, but may not log the problem and
// return.  'bsls_assert', by default, enforces that policy by terminating the
// task if an installed assertion handler function chooses to returns normally.
//
///Configuring an Exception to the Assertion Handler Policy
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// 'bsls_assert' provides a two-part mechanism to permit returning after the
// detection of failed assertions.
//
// It is a violation of Bloomberg policy to modify this default configuration
// without permission from senior management.  (Internal Bloomberg users should
// contact the BDE team if you feel your application needs an exception to this
// policy).
//
// The intention is to provide a means to override the assertion failure policy
// that can be enabled quickly, but requires the explicit (and obvious) choice
// from both the owner of the application's 'main' function, and the person
// responsible for building the application.  In order to enable a policy
// exception, 'permitOutOfPolicyReturningFailureHandler' must be called, and
// the task must be linked with a special build of 'bsls_assert.o' (in which
// the 'k_permitOutOfPolicyReturningAssertionBuildKey' constant has the value
// "bsls-PermitOutOfPolicyReturn").
//
///Legacy Handler Functions
///------------------------
// Prior to the introduction of 'bsls::AssertViolation', the signature for
// 'bsls::Assert::ViolationHandler' was this:
//..
//  void(const char*, const char*,int)
//..
// This signature for a handler is still supported (though deprecated) under
// its original name 'bsls::Assert::Handler'.  Overloads that take a
// 'bsls::Assert::Handler' exist for 'bsls::AssertFailureHandler' and the
// constructor for 'bsls::AssertFailureHandlerGuard', so code that uses the old
// handler signature should work without changes.
//
// If a legacy handler is set as the current handler, the function
// 'bsls::Assert::failureHandler()' will return a pointer to that function,
// while 'bsls::Assert::violationHandler()' will return an internal function
// that extracts the appropriate arguments from the generated
// 'bsls::AssertViolation' object and passes them to the installed 'Handler'.
//
///Assertions in Header Files (Mixing Build Options Across Translation Units)
///--------------------------------------------------------------------------
// Mixing build modes across translation units, although not strictly
// conformant with the C++ language standard, is permissible in practice;
// however, the defensive checks that are enabled may be unpredictable.  The
// *one-definition* *rule* states that if there are multiple definitions of an
// object or function within a program, these definitions *must* be identical
// or else the program is *ill-formed*.  Unfortunately, definitions in header
// files may not be identical across object ('.o') files if the build targets
// or assertion-level flags defined during translation (preprocessing) are not
// the same.
//
// For example, consider an 'inline' function that sets the width of a 'Square'
// and optionally checks for (defends against) a negative 'width' argument:
//..
//  // our_square.h
//  // ...
//
//  inline
//  void Square::setWidth(int width)
//  {
//      BSLS_ASSERT_SAFE(width >= 0);
//
//      d_width = width;
//  }
//..
// Now consider a client that uses this 'setWidth' method:
//..
//  // my_client.cpp
//  // ...
//  void f()
//  {
//      Square s;
//      s.setWidth(-5);
//  }
//..
// We can build the 'our_square' component in "safe mode" -- e.g., by
// incorporating '-DBSLS_ASSERT_LEVEL_ASSERT_SAFE' on the (Unix) command line.
// Notice, however, that building client software against a version of
// 'our_square.o' compiled in "safe mode" does *not* ensure that all of the
// 'BSLS_ASSERT_SAFE' macros will be active (will instantiate); instead, the
// client's build mode will (most likely) govern those instantiations of the
// 'BSLS_ASSERT_SAFE' macro located within the library.  The only way to ensure
// that all of the 'BSLS_ASSERT_SAFE' macros instantiate is to build the
// *client* as well as the library software in "safe mode".
//
// Inline functions are not the only source of multiple inconsistent
// definitions.  Consider a non-'inline' method 'reserveCapacity' on a 'List'
// template, parameterized by element 'TYPE':
//..
//  // our_list.h
//  // ...
//
//  template <class TYPE>
//  void List<TYPE>::reserveCapacity(int numElements)
//  {
//      BSLS_ASSERT(numElements >= 0);
//      // ...
//  }
//..
// Each different translation unit that invokes 'reserveCapacity' potentially
// generates another instantiation of this function template.  Those
// translation units that are compiled in "debug mode" (or "safe mode") --
// e.g., with 'BSLS_ASSERT_LEVEL_ASSERT' (or 'BSLS_ASSERT_LEVEL_ASSERT_SAFE')
// defined -- will incorporate code corresponding to each use of the
// 'BSLS_ASSERT' macro therein; the rest will not.  Which one of these template
// instantiations the linker uses in the final program is undefined and highly
// unpredictable.
//
// The bottom line is that, unless clients of a library are compiled with (at
// least) the same level of assertion enabling as the library itself, not all
// of the library's defensive checking (for the assertion-level for which the
// library was compiled) will necessarily be incorporated into the client code.
// Similarly, compiling a client in a higher-level of defensive checking (e.g.,
// "safe mode") than the library was compiled (e.g., "debug mode") may result
// in additional defensive checks beyond what the library author intended for
// the mode (e.g., "debug mode") in which the library was compiled.
//
// Note that all build modes (except for when 'BDE_BUILD_TARGET_SAFE_2' is
// defined, see below) are required to be binary compatible (e.g., fields
// cannot be added to the middle of a 'struct').  Since a component's contract
// makes no explicit promise about what checking will occur, that contract is
// not violated when different parts of a program are compiled with different
// levels of assertion-enabling build options.  The only consequence is that a
// smaller (or larger) number of defensive checks may be active than might
// otherwise be expected.
//
///Conditional Compilation
///-----------------------
// To recap, there are three (mutually compatible) general *build* *targets*:
//: o 'BDE_BUILD_TARGET_OPT'
//: o 'BDE_BUILD_TARGET_SAFE'
//: o 'BDE_BUILD_TARGET_SAFE_2'
// seven (mutually exclusive) component-specific *assertion* *levels*:
//: o 'BSLS_ASSERT_LEVEL_ASSERT_SAFE'
//: o 'BSLS_ASSERT_LEVEL_ASSERT'
//: o 'BSLS_ASSERT_LEVEL_ASSERT_OPT'
//: o 'BSLS_ASSERT_LEVEL_NONE'
//: o 'BSLS_ASSERT_LEVEL_ASSUME_OPT'
//: o 'BSLS_ASSERT_LEVEL_ASSUME_ASSERT'
//: o 'BSLS_ASSERT_LEVEL_ASSUME_SAFE'
// and four (mutually exclusive) component-specific *review* *levels*:
//: o 'BSLS_REVIEW_LEVEL_REVIEW_SAFE'
//: o 'BSLS_REVIEW_LEVEL_REVIEW'
//: o 'BSLS_REVIEW_LEVEL_REVIEW_OPT'
//: o 'BSLS_REVIEW_LEVEL_NONE'
// The above macros can be defined (externally) by the build environment to
// affect which of the three *assert* *macros*:
//: o 'BSLS_ASSERT_SAFE(boolean-valued expression)'
//: o 'BSLS_ASSERT(boolean-valued expression)'
//: o 'BSLS_ASSERT_OPT(boolean-valued expression)'
// will be enabled in assert mode, which will be in review mode, which will be
// assumed, and which will be disabled.
//
// The public interface of this component also explicitly provides a number of
// additional intermediate macros to identify how the various 'BSLS_ASSERT'
// macros have been instantiated.  These each exist for each level and have the
// following suffixes and meanings:
//: o 'IS_ACTIVE': Defined if the corresponding level is enabled in assert or
//:   review mode.  For example, 'BSLS_ASSERT_SAFE_IS_ACTIVE' is defined if
//:   (and only if) the conditions expressed using 'BSLS_ASSERT_SAFE' will be
//:   checked at runtime (either as assertions or reviews).
//: o 'IS_REVIEW': Defined if the corresponding level is enabled in review
//:   mode.
//: o 'IS_ASSUMED': Defined if the corresponding level is assumed.
//: o 'IS_USED': Defined if assert expressions for the corresponding level need
//:   to be valid (i.e., if they are "ODR-used").  For example,
//:   'BSLS_ASSERT_SAFE_IS_USED' is defined if (and only if) the conditions
//:   expressed using 'BSLS_ASSERT_SAFE' will be compiled.  Note that this is a
//:   super-set of the cases where 'BSLS_ASSERT_SAFE_IS_ACTIVE' will be
//:   defined, which is when the conditions will be checked at runtime, while
//:   'BSLS_ASSERT_SAFE_IS_USED' is also defined if the conditions are assumed
//:   or if 'BSLS_ASSERT_VALIDATE_DISABLED_MACROS' is defined.
//
// Putting that together, these 3 macros are defined if the corresponding macro
// is in assert or review mode - and thus the expression will be checked and a
// violation handler will be invoked on failure:
//: o 'BSLS_ASSERT_SAFE_IS_ACTIVE'
//: o 'BSLS_ASSERT_IS_ACTIVE'
//: o 'BSLS_ASSERT_OPT_IS_ACTIVE'
// These three are defined if the corresponding macro is in review mode - and
// thus the expression will be checked and the review violation handler will be
// invoked on failure.  These will be defined when the review level has been
// set to a level higher than the assert level:
//: o 'BSLS_ASSERT_SAFE_IS_REVIEW'
//: o 'BSLS_ASSERT_IS_REVIEW'
//: o 'BSLS_ASSERT_OPT_IS_REVIEW'
// These three are defined if the corresponding macro is being assumed, and it
// will be hard undefined behavior to violate these expressions:
//: o 'BSLS_ASSERT_SAFE_IS_ASSUMED'
//: o 'BSLS_ASSERT_IS_ASSUMED'
//: o 'BSLS_ASSERT_OPT_IS_ASSUMED'
//
// Finally, three more macros with the 'IS_USED' suffix are defined when the
// expression for the corresponding macro is going to be compiled.  This will
// be true for macros in assert, review or assumed modes, and it will be true
// for all macros if 'BSLS_ASSERT_VALIDATE_DISABLED_MACROS' has been defined.
//: o 'BSLS_ASSERT_SAFE_IS_USED'
//: o 'BSLS_ASSERT_IS_USED'
//: o 'BSLS_ASSERT_OPT_IS_USED'
//
// Note that any of the 'IS_ACTIVE', 'IS_REVIEW", and 'IS_ASSUMED' macros being
// defined will imply that the corresponding 'IS_USED' macro is also defined.
//
// Which of these macros to use to conditionally compile supporting code is
// based on when that supporting code needs to be compiled:
//: o Use '#if defined(..._IS_USED)' when:
//:   * Writing functions that are only accessible to and needed for assertions
//:     of the corresponding level.  This could be private member functions,
//:     static functions, or functions in an anonymous namespace.  See
//:     {Example 8} for details on this use.
//: o Use '#if !defined(..._IS_ACTIVE) && !defined(..._IS_ASSUMED)' when:
//:   * You are writing (test) code that will intentionally violate a contract
//:     when there is not going to be any intrinsic ill effect to that
//:     violation.  Generally this should only be required when there is a need
//:     to validate out-of-contract behavior of a component from within its own
//:     test driver.
//: o Use '#if defined(...IS_ACTIVE)' when:
//:   * You are doing negative testing and want to be sure that when you call
//:     your function out of contract that the violation handler will be
//:     invoked.  See {'bsls_asserttest'} for tools to do this without having
//:     to manually check these macros.
//:   * Writing redundant defensive code that should only execute when the
//:     corresponding assertions are going to be enabled.  The assertion itself
//:     should also be included in the same preprocessor block.  See
//:     {Example 9} for details on this use.
//:   * Note that historically this was the only macro available, and it is
//:     often used for blocks of code where the checks above would be more
//:     appropriate.  This can often lead to code that fails to compile with
//:     'BSLS_ASSERT_VALIDATE_DISABLED_MACROS' enabled or which will not work
//:     correctly when assumptions are turned on.
//
// See {Example 6} and {Example 7}, respectively, for how
// 'BDE_BUILD_TARGET_SAFE_2' and intermediate assertion predicate macros, such
// as 'BSLS_ASSERT_SAFE_IS_ACTIVE' (and even 'BSLS_ASSERT_OPT_IS_ACTIVE'), can
// be used profitably in practice.
//
///Validating Disabled Macro Expressions
///-------------------------------------
// An additional external macro, 'BSLS_ASSERT_VALIDATE_DISABLED_MACROS', can be
// defined to control the compile time behavior of 'bsls_assert'.  Enabling
// this macro configures all *disabled* assert macros to still instantiate
// their predicates (in a non-evaluated context) to be sure that the predicate
// is still syntactically valid.  This can be used to ensure assertions that
// are rarely enabled have valid expressions.
//
///Language-Level Contracts
///------------------------
// Contracts were proposed, accepted into the draft C++20 standard, and then
// removed.  Implementations of that facility exist and it is expected future
// implementations will begin to arrive as work on new proposals comes to
// fruition.  Defining the macro 'BSLS_ASSERT_USE_CONTRACTS' will cause all
// 'BSLS_ASSERT' (and, if possible, 'BSLS_REVIEW') macros to go through the
// language-level contract implementation if it is available (currently only on
// an experimental version of the gcc-compiler), otherwise a diagnostic will be
// issued.
//
// Note that mixing builds that do and do not use 'BSLS_ASSERT_USE_CONTRACTS'
// is not supported.  Attempting to link against a library bult with a
// different mode for this option will cause a link-time error.
//
///Usage
///-----
// The following examples illustrate (1) when to use each of the three kinds of
// (BSLS) "ASSERT" macros, (2) when and how to call the 'invokeHandler' method
// directly, (3) how to configure, at runtime, the behavior resulting from an
// assertion failure using "off-the-shelf" handler methods, (4) how to create
// your own custom assertion-failure handler function, (5) proper use of
// 'bsls::AssertFailureHandlerGuard' to install, temporarily, an
// exception-producing assert handler, (6) how "ASSERT" macros would be used in
// conjunction with portions of the source code (affecting binary
// compatibility) that are incorporated only when 'BDE_BUILD_TARGET_SAFE_2' is
// defined, and (7) how assertion predicates (e.g.,
// 'BSLS_ASSERT_SAFE_IS_ACTIVE') are used to conditionally compile additional
// (redundant) defensive source code (not affecting binary compatibility)
// precisely when the corresponding (BSLS) "ASSERT" macro (e.g.,
// 'BSLS_ASSERT_SAFE') is active.
//
///Example 1: Using 'BSLS_ASSERT', 'BSLS_ASSERT_SAFE', and 'BSLS_ASSERT_OPT'
///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// This component provides three different variants of (BSLS) "ASSERT" macros.
// This first usage example illustrates how one might select each of the
// particular variants, based on the runtime cost of the defensive check
// relative to that of the useful work being done.
//
// Use of the 'BSLS_ASSERT_SAFE' macro is often appropriate when the defensive
// check occurs within the body of an 'inline' function.  The
// 'BSLS_ASSERT_SAFE' macro minimizes the impact on runtime performance as it
// is instantiated only when requested (i.e., by building in "safe mode").  For
// example, consider a light-weight point class 'Kpoint' that maintains 'x' and
// 'y' coordinates in the range '[-1000 .. 1000]':
//..
// my_kpoint.h
// ...
//
//  class Kpoint {
//      short int d_x;
//      short int d_y;
//    public:
//      Kpoint(short int x, short int y);
//          // ...
//          // The behavior is undefined unless '-1000 <= x <= 1000' and
//          // '-1000 <= y <= 1000'.
//      // ...
//  };
//
// ...
//..
// Since the cost of validation here is significant compared with the useful
// work being done, we might choose to implement defensive checks using
// 'BSLS_ASSERT_SAFE' as follows:
//..
// ...
//
//  inline
//  Kpoint::Kpoint(short int x, short int y)
//  : d_x(x)
//  , d_y(y)
//  {
//      BSLS_ASSERT_SAFE(-1000 <= x); BSLS_ASSERT_SAFE(x <= 1000);
//      BSLS_ASSERT_SAFE(-1000 <= y); BSLS_ASSERT_SAFE(y <= 1000);
//  }
//..
// For more substantial (non-'inline') functions, we would be more likely to
// use the 'BSLS_ASSERT' macro because the runtime overhead due to defensive
// checks is likely to be much less significant.  For example, consider a
// hash-table class that allows the client to resize the underlying table:
//..
// my_hashtable.h
// ...
//
//  class HashTable {
//      // ...
//    public:
//      // ...
//
//      void resize(double loadFactor);
//          // Adjust the size of the underlying hash table to be approximately
//          // the current number of elements divided by the specified
//          // 'loadFactor'.  The behavior is undefined unless
//          // '0 < loadFactor'.
//  };
//..
// Since the relative runtime cost of validating the input argument is quite
// small (e.g., less than 10%) compared to the typical work being done, we
// might choose to implement the defensive check using 'BSLS_ASSERT' as
// follows:
//..
// my_hashtable.cpp
// ...
//
//  void HashTable::resize(double loadFactor)
//  {
//      BSLS_ASSERT(0 < loadFactor);
//
//      // ...
//  }
//..
// In some cases, the runtime cost of checking is always negligible when
// compared with the runtime cost of performing the useful work; moreover, the
// consequences of continuing in an undefined state for certain applications
// could be catastrophic.  Instead of using 'BSLS_ASSERT' in such cases, we
// might consider using 'BSLS_ASSERT_OPT'.  For example, suppose we have a
// financial application class 'TradingSystem' that performs trades:
//..
// my_tradingsystem.h
// ...
//
//  class TradingSystem {
//      // ...
//    public:
//      // ...
//..
// Further suppose that there is a particular method 'executeTrade' that takes,
// as a scaling factor, an integer that must be a multiple of 100 or the
// behavior is undefined (and might actually execute a trade):
//..
//      void executeTrade(int scalingFactor);
//          // Execute the current trade using the specified 'scalingFactor'.
//          // The behavior is undefined unless '0 <= scalingFactor' and '100'
//          // evenly divides 'scalingFactor'.
//      // ...
//  };
//..
// Because the cost of the two checks is likely not even measurable compared to
// the overhead of accessing databases and executing the trade, and because the
// consequences of specifying a bad scaling factor are virtually unbounded, we
// might choose to implement these defensive checks using 'BSLS_ASSERT_OPT' as
// follows:
//..
// my_tradingsystem.cpp
// ...
//
//  void TradingSystem::executeTrade(int scalingFactor)
//  {
//      BSLS_ASSERT_OPT(0 <= scalingFactor);
//      BSLS_ASSERT_OPT(0 == scalingFactor % 100);
//
//      // ...
//  }
//..
// Notice that in each case, the choice of which of the three (BSLS) "ASSERT"
// macros to use is governed primarily by the relative runtime cost compared
// with that of the useful work being done (and only secondarily by the
// potential consequences of continuing execution in an undefined state).
//
///Example 2: When and How to Call the 'invokeHandler' Method Directly
///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// There *may* be times (but this is yet to be demonstrated) when we might
// reasonably choose to unconditionally invoke the currently installed
// assertion-failure handler directly -- i.e., instead of via one of the three
// (BSLS) "ASSERT" macros provided in this component.  Suppose that we are
// currently in the body of some function 'someFunc' and, for whatever reason,
// feel compelled to invoke the currently installed assertion-failure handler
// based on some criteria other than the current build mode.
// 'BSLS_ASSERT_INVOKE' is provided for this purpose.  The call might look as
// follows:
//..
//  void someFunc(bool a, bool b, bool c)
//  {
//      bool someCondition = a && b && !c;
//
//      if (someCondition) {
//          BSLS_ASSERT_INVOKE("Bad News");
//      }
//  }
//..
// If presented with invalid arguments, 'someFunc' (above) will produce output
// similar to the following:
//..
//  Assertion failed: Bad News, file bsls_assert.t.cpp, line 609
//  Abort (core dumped)
//..
// If a piece of code needs to be guaranteed to not return, the additional
// macro 'BSLS_ASSERT_INVOKE_NORETURN' is also available.  It behaves the same
// way as 'BSLS_ASSERT_INVOKE', but if the installed handler *does* return
// 'failByAbort' will be immediately called.  On supported platforms it is
// marked appropriately to not return to support compiler requirements and
// static analysis tools.
//
///Example 3: Runtime Configuration of the 'bsls::Assert' Facility
///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// By default, any assertion failure will result in the invocation of the
// 'bsls::Assert::failByAbort' handler function.  We can replace this behavior
// with that of one of the other static failure handler methods supplied in
// 'bsls::Assert' as follows.  Let's assume we are at the top of our
// application called 'myMain' (which would typically be 'main'):
//..
//  void myMain()
//  {
//..
// First observe that the default assertion-failure handler function is, in
// fact, 'bsls::Assert::failByAbort':
//..
//  assert(&bsls::Assert::failByAbort == bsls::Assert::violationHandler());
//..
// Next, we install a new assertion-failure handler function,
// 'bsls::Assert::failBySleep', from the suite of "off-the-shelf" handlers
// provided as 'static' methods of 'bsls::Assert':
//..
//  bsls::Assert::setViolationHandler(&bsls::Assert::failBySleep);
//..
// Observe that 'bsls::Assert::failBySleep' is the new, currently-installed
// assertion-failure handler:
//..
//  assert(&bsls::Assert::failBySleep == bsls::Assert::violationHandler());
//..
// Note that if we were to explicitly invoke the current assertion-failure
// handler as follows:
//..
//  BSLS_ASSERT_INVOKE("message");  // This will hang!
//..
// the program will hang since 'bsls::Assert::failBySleep' repeatedly sleeps
// for a period of time within an infinite loop.  Thus, this assertion-failure
// handler is useful for hanging a process so that a debugger may be attached
// to it.
//
// We may now decide to disable the 'setViolationHandler' method using the
// 'bsls::Assert::lockAssertAdministration()' method to ensure that no one else
// will override our decision globally.  Note, however, that the
// 'bsls::AssertFailureHandlerGuard' is not affected, and can still be used to
// supplant the currently installed handler (see below):
//..
//  bsls::Assert::lockAssertAdministration();
//..
// Attempting to change the currently installed handler now will fail:
//..
//      bsls::Assert::setViolationHandler(&bsls::Assert::failByAbort);
//
//      assert(&bsls::Assert::failByAbort != bsls::Assert::violationHandler());
//
//      assert(&bsls::Assert::failBySleep == bsls::Assert::violationHandler());
//  }
//..
//
///Example 4: Creating a Custom Assertion Handler
/// - - - - - - - - - - - - - - - - - - - - - - -
// Sometimes, especially during testing, we may need to write our own custom
// assertion-failure handler function.  The only requirements are that the
// function have the same prototype (i.e., the same respective parameter and
// return types) as the 'bsls::Assert::Handle' 'typedef', and that the function
// should not return (i.e., it must 'abort', 'exit', 'terminate', 'throw', or
// hang).  To illustrate, we will create a 'static' method at file scope that
// conforms to the required structure (notice the explicit use of 'std::printf'
// from '<cstdio>' instead of 'std::cout' from '<iostream>' to avoid
// interaction with the C++ memory allocation layer):
//..
//  static bool globalEnableOurPrintingFlag = true;
//
//  static
//  void ourFailureHandler(const bsls::AssertViolation& violation)
//      // Print the expression 'comment', 'file' name, and 'line' number from
//      // the specified 'violation' to 'stdout' as a comma-separated list,
//      // replacing null string-argument values with empty strings (unless
//      // printing has been disabled by the 'globalEnableOurPrintingFlag'
//      // variable), then unconditionally abort.
//  {
//      const char *comment = violation.comment();
//      if (!comment) {
//          comment = "";
//      }
//      const char *file = violation.fileName();
//      if (!file) {
//          file = "";
//      }
//      int line = violation.lineNumber();
//      if (globalEnableOurPrintingFlag) {
//          std::printf("%s, %s, %d\n", comment, file, line);
//      }
//      std::abort();
//  }
//..
// At the top level of our application we have the following:
//..
//  void ourMain()
//  {
//..
// First, let's observe that we can assign this new function to a function
// pointer of type 'bsls::Assert::Handler':
//..
//  bsls::Assert::ViolationHandler f = &ourFailureHandler;
//..
// Now we can install it just as we would any other handler:
//..
//  bsls::Assert::setViolationHandler(&ourFailureHandler);
//..
// We can now invoke the default handler directly:
//..
//  BSLS_ASSERT_INVOKE("str1");
//  }
//..
// With the resulting output something like as follows:
//..
//  str1, my_file.cpp, 17
//  Abort (core dumped)
//..
//
///Example 5: Using the 'bsls::AssertFailureHandlerGuard'
/// - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Sometimes we may want to replace, temporarily (i.e., within some local
// lexical scope), the currently installed assertion-failure handler function.
// In particular, we sometimes use the 'bsls::AssertFailureHandlerGuard' class
// to replace the current handler with one that throws an exception (because we
// know that such an exception is safe in the local context).  Let's start with
// the simple factorial function below, which validates, in "debug mode" (or
// "safe mode"), that its input is non-negative:
//..
//  double fact(int n)
//      // Return 'n!'.  The behavior is undefined unless '0 <= n'.
//  {
//      BSLS_ASSERT(0 <= n);
//
//      double result = 1.0;
//      while (n > 1) {
//          result *= n--;
//      }
//      return result;
//  }
//..
// Now consider the following integer-valued 'extern "C"' C++ function,
// 'wrapperFunc', which can be called from C and FORTRAN, as well as from C++:
//..
//  extern "C" int wrapperFunc(bool verboseFlag)
//  {
//      enum { GOOD = 0, BAD } result = GOOD; (void) verboseFlag;
//..
// The purpose of this function is to allow assertion failures in subroutine
// calls below this function to be handled by throwing an exception, which is
// then caught by the wrapper and reported to the caller as a "bad" status.
// Hence, when within the runtime scope of this function, we want to install,
// temporarily, the assertion-failure handler 'bsls::Assert::failByThrow',
// which, when invoked, causes an 'bsls::AssertTestException' object to be
// thrown.  (Note that we are not advocating this approach for "recovery", but
// rather for an orderly shut-down, or perhaps during testing.)  The
// 'bsls::AssertFailureHandlerGuard' class is provided for just this purpose:
//..
//      assert(&bsls::Assert::failByAbort == bsls::Assert::violationHandler());
//
//      bsls::AssertFailureHandlerGuard guard(&bsls::Assert::failByThrow);
//
//      assert(&bsls::Assert::failByThrow == bsls::Assert::violationHandler());
//..
// Next we open up a 'try' block, and somewhere within the 'try' we
// "accidentally" invoke 'fact' with an out-of-contract value (i.e., '-1'):
//..
//  #ifdef BDE_BUILD_TARGET_EXC
//      try
//  #endif
//          {
//
//          // ...
//
//          double d = fact(-1);        // Out-of-contract call to 'fact'.
//
//          // ...
//      }
//  #ifdef BDE_BUILD_TARGET_EXC
//      catch (const bsls::AssertTestException& e) {
//          result = BAD;
//          if (verboseFlag) {
//              std::printf( "Internal Error: %s, %s, %d\n",
//                           e.expression(),
//                           e.filename(),
//                           e.lineNumber() );
//          }
//      }
//  #endif
//      return result;
//  }
//..
// Assuming exceptions are enabled (i.e., 'BDE_BUILD_TARGET_EXC' is defined),
// if an 'bsls::AssertTestException' occurs below this wrapper function, the
// exception will be caught, a message will be printed to 'stdout', e.g.,
//..
//  Internal Error: bsls_assert.t.cpp:500: 0 <= n
//..
// and the 'wrapperFunc' function will return a bad status (i.e., 1) to its
// caller.  Note that if exceptions are not enabled,
// 'bsls::Assert::failByThrow' will behave as 'bsls::Assert::failByAbort', and
// dump core immediately:
//..
//  Assertion failed: 0 <= n, file bsls_assert.t.cpp, line 500
//  Abort (core dumped)
//..
// Finally note that the 'bsls::AssertFailureHandlerGuard' is not thread-aware.
// In particular, a guard that is created in one thread will also affect the
// failure handlers that are used in other threads.  Care should be taken when
// using this guard when more than a single thread is executing.
//
///Example 6: Using (BSLS) "ASSERT" Macros Along With 'BDE_BUILD_TARGET_SAFE_2'
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Recall that assertions do not affect binary compatibility; however, software
// built with 'BDE_BUILD_TARGET_SAFE_2' defined need not be binary compatible
// with software built otherwise.  In this example, we look at how we might use
// the (BSLS) "ASSERT" family of macros in conjunction with code that is
// incorporated (at compile time) only when 'BDE_BUILD_TARGET_SAFE_2' is
// defined.
//
// As a simple example, let's consider an elided implementation of a
// singly-linked integer list and its iterator.  Whenever
// 'BDE_BUILD_TARGET_SAFE_2' is defined, we want to defend against the
// possibility that a client mistakenly passes a 'ListIter' object into a
// 'List' object method (e.g., 'List::insert') where that 'ListIter' object did
// not originate from the same 'List' object.
//
// We'll start by defining a local helper 'List_Link' 'struct' as follows:
//..
//  struct List_Link {
//      List_Link *d_next_p;
//      int        d_data;
//      List_Link(List_Link *next, int data) : d_next_p(next), d_data(data) { }
//  };
//..
// Next, we'll define 'ListIter', which always identifies the current position
// in a sequence of links, but whenever 'BDE_BUILD_TARGET_SAFE_2' is defined,
// also maintains a pointer to its parent 'List' object:
//..
//  class List;                         // Forward declaration.
//
//  class ListIter {
//  #ifdef BDE_BUILD_TARGET_SAFE_2
//      List *d_parent_p;               // Exists only in "safe 2 mode".
//  #endif
//      List_Link **d_current_p;
//      friend class List;
//      friend bool operator==(const ListIter&, const ListIter&);
//    private:
//      ListIter(List_Link **current,
//               List *
//  #ifdef BDE_BUILD_TARGET_SAFE_2
//                     parent           // Not used unless in "safe 2 mode".
//  #endif
//              )
//      : d_current_p(current)
//  #ifdef BDE_BUILD_TARGET_SAFE_2
//      , d_parent_p(parent)            // Initialize only in "safe 2 mode".
//  #endif
//      { }
//    public:
//      ListIter& operator++() { /* ... */ return *this; }
//      // ...
//  };
//  bool operator==(const ListIter& lhs, const ListIter& rhs);
//  bool operator!=(const ListIter& lhs, const ListIter& rhs);
//..
// Finally we define the 'List' class itself with most of the operations
// elided; the methods of particular interest here are 'begin' and 'insert':
//..
//
//  class List {
//      List_Link *d_head_p;
//    public:
//      // CREATORS
//      List() : d_head_p(0) { }
//      List(const List&) { /* ... */ }
//      ~List() { /* ... */ }
//
//      // MANIPULATORS
//      List& operator=(const List&) { /* ... */ return *this; }
//
//      //| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
//      //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
//      //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//      ListIter begin()
//          // Return an iterator referring to the beginning of this list.
//      {
//          return ListIter(&d_head_p, this);
//      }
//      //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//
//      //| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
//      //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
//      //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//      void insert(const ListIter& position, int data)
//          // Insert the specified 'data' value into this list at the
//          // specified 'position'.
//      {
//  #ifdef BDE_BUILD_TARGET_SAFE_2
//          BSLS_ASSERT_SAFE(this == position.d_parent_p);  // "safe 2 mode"
//  #endif
//          *position.d_current_p = new List_Link(*position.d_current_p, data);
//      }
//      //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//
//      // ACCESSORS
//      void print()
//          // Output the contents of this list to 'stdout'.
//      {
//          printf( "[" );
//          for (List_Link *p = d_head_p; p; p = p->d_next_p) {
//              printf( " %d", p->d_data );
//          }
//          printf(" ]\n");
//      }
//  };
//..
// Outside of "safe 2 mode", it is possible to pass an iterator object obtained
// from the 'begin' method of one 'List' object into the 'insert' method of
// another, having, perhaps, unexpected results:
//..
//  void sillyFunc(bool printFlag)
//  {
//      List a;
//      ListIter aIt = a.begin();
//      a.insert(aIt, 1);
//      a.insert(aIt, 2);
//      a.insert(aIt, 3);
//
//      if (printFlag) {
//          std::printf( "a = "); a.print();
//      }
//
//      List b;
//      ListIter bIt = b.begin();
//      a.insert(bIt, 4);       // Oops!  Should have been: 'b.insert(bIt, 4);'
//      a.insert(bIt, 5);       // Oops!    "     "     "   '    "     "   5  '
//      a.insert(bIt, 6);       // Oops!    "     "     "   '    "     "   6  '
//
//      if (printFlag) {
//          std::printf( "a = "); a.print();
//          std::printf( "b = "); b.print();
//      }
//  }
//..
// In the example above, we have "accidentally" passed the iterator 'bIt'
// obtained from 'List' object 'b' into the 'insert' method for 'List' object
// 'a'.  The resulting undefined behavior (in other than "safe 2 mode") might
// produce output that looks as follows:
//..
//  a = [ 3 2 1 ]
//  a = [ 3 2 1 ]
//  b = [ 6 5 4 ]
//..
// If the same 'sillyFunc' were compiled in "safe 2 mode" (i.e., with
// 'BDE_BUILD_TARGET_SAFE_2' defined) the undefined behavior would be detected
// and the output would, by default, look more like the following:
//..
//  a = [ 3 2 1 ]
//  FATAL my_list.cpp:56 Assertion failed: this == position.d_parent_p
//  Abort (core dumped)
//..
// thereby quickly exposing the misuse by the client.
//
///Example 7: Conditional Compilation Associated with Enabled Assertion Levels
///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// In cases where we want to tie code, other than just an assertion, to a
// specific level of enabled assertions, we will want to use the corresponding
// intermediate predicate that enables that level of assertions:
//
//: o For 'BSLS_ASSERT_SAFE', use 'BSLS_ASSERT_SAFE_IS_ACTIVE'.
//:
//: o For 'BSLS_ASSERT', use 'BSLS_ASSERT_IS_ACTIVE'.
//:
//: o For 'BSLS_ASSERT_OPT', use 'BSLS_ASSERT_OPT_IS_ACTIVE'.
//
// Suppose that we have a class such as 'MyDate' (below) that, except for
// checking its invariants, would have a trivial destructor.  By not declaring
// a destructor at all, we may realize performance advantages, but then we lose
// the ability to validate our invariants in "debug" or "safe" mode.  What we
// want to do is to declare (and later define) the destructor in precisely
// those build modes for which we would want to assert invariants.
//
// An elided class 'MyDate', which is based on a serial-date implementation, is
// provided for reference:
//..
//  class MyDate {
//      // This class implements a value-semantic "date" type representing
//      // valid date values in the range '[ 0001Jan01 .. 9999Dec31 ]'.
//
//      // DATA
//      int d_serialDate;  // sequential representation within a valid range
//
//    public:
//       // CLASS METHODS
//
//       // ...
//
//       // CREATORS
//       MyDate();
//           // Create a 'MyDate' object having the value '0001Jan01'.
//
//       // ...
//
//       MyDate(const MyDate& original);
//           // Create a 'MyDate' object having the same value as the specified
//           // 'original' object.
//
//  #if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
//       ~MyDate();
//           // Destroy this object.  Note that in some build modes the
//           // destructor generated by the compiler is trivial.
//  #endif
//
//      // ...
//  };
//
// ...
//
// ========================================================================
//                  INLINE FUNCTION DEFINITIONS
// ========================================================================
//
// ...
//
// CREATORS
//  inline
//  MyDate::MyDate()
//  : d_serialDate(1)  // 0001Jan01
//  {
//  }
//
//  inline
//  MyDate::MyDate(const MyDate& original)
//  : d_serialDate(original.d_serialDate)
//  {
//  }
//
// ...
//
//  #if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
//  inline
//  MyDate::~MyDate()
//  {
//      BSLS_ASSERT_SAFE(1 <= d_serialDate);             // 0001Jan01
//      BSLS_ASSERT_SAFE(     d_serialDate <= 3652061);  // 9999Dec31
//  }
//  #endif
//
// ...
//..
// In practice, however, we would probably implement an 'isValidSerialDate'
// method in a lower-level utility class, e.g., 'MyDateImpUtil', leading to
// code that is more fine-grained, modular, and hierarchically reusable:
//..
//  struct MyDateImpUtil {
//      static bool isValidSerialDate(int d_date);
//          // Return 'true' if the specified 'd_date' represents a valid date
//          // value, and 'false' otherwise.
//  };
//
//  inline
//  bool MyDateImpUtil::isValidSerialDate(int d_date)
//  {
//      return 1 <= d_date && d_date <= 3652061;
//  }
//..
// Like other aspects of 'BSLS_ASSERT_SAFE', the example above violates the
// one-definition rule for mixed-mode builds.  Note that all code conditionally
// compiled based on 'BSLS_ASSERT_SAFE_IS_ACTIVE', 'BSLS_ASSERT_IS_ACTIVE', and
// 'BSLS_ASSERT_OPT_IS_ACTIVE' should be binary compatible for mixed-mode
// builds.  If the conditionally-compiled code would not be binary compatible,
// use 'BDE_BUILD_TARGET_SAFE_2' instead.
//
// WARNING - In practice, declaring a destructor in some build modes but not
// others has led to subtle and difficult-to-diagnose failures.  DON'T DO IT!
//
// Finally, in very rare cases, we may want to put in (redundant) defensive
// code (in the spirit of 'BSLS_ASSERT_OPT') that is not part of the
// component-level contract, yet (1) is known to have negligible runtime cost
// and (2) is deemed to be so important as to be necessary even for optimized
// builds.
//
// For example, consider again the 'MyDate' class above that now also declares
// a non-'inline' 'print' method to format the current date value in some
// human-readable, but otherwise unspecified format:
//..
// xyza_mydate.h
// ...
//  class MyDate {
//      // ...
//
//      // DATA
//      int d_serialDate;  // sequential representation within a valid range
//
//    public:
//      // ...
//      // ACCESSORS
//      // ...
//
//      std::ostream& print(std::ostream& stream, ...) const;
//          // Write the value of this object to the specified output 'stream'
//          // in some human-readable format, and return a reference to
//          // 'stream'.  Optionally specify ...
//
//      // ...
//
//  };
//..
// Successfully writing bad data is among the most insidious of bugs, because a
// latent error can persist and not be discovered until long after the program
// terminates.  Writing the value of a corrupted 'MyDate' object in a
// *machine-readable* (binary) format is an error so serious as to warrant
// invoking
//..
//  void testFunction(int d_serialDate) {
//      BSLS_ASSERT_OPT(MyDateImpUtil::isValidSerialDate(d_serialDate));
//  }
//..
// each time we attempt the output operation; however, printing the value in a
// human-readable format intended primarily for debugging purposes is another
// matter.  In anything other than a safe build (which in this case would
// enforce essentially all method preconditions), it would be unfortunate if a
// developer, knowing that there was a problem involving the use of 'MyDate',
// inserted print statements to identify that problem, only to have the 'print'
// method itself ruthlessly invoke the assert handler, likely terminating the
// process).  Moreover, it may also be unsafe even to attempt to format the
// value of a 'MyDate' object whose 'd_serialDate' value violates its
// invariants (e.g., due to a static table lookup).  In such cases we may, as
// sympathetic library developers, choose to implement different undefined
// (undocumented) redundant defensive behaviors, depending on the desired level
// of assertions:
//..
// xyza_mydate.cpp
// ...
// #include <xyza_mydateimputil.h>
// ...
//
//  std::ostream& MyDate::print(std::ostream& stream, ...) const
//  {
//      // BSLS_ASSERT(/* any *argument* preconditions for this function */);
//
//      // Handle case where the invariants have been violated.
//
//  #ifdef BSLS_ASSERT_OPT_IS_ACTIVE
//      // Note that if 'BSLS_ASSERT_LEVEL_NONE' has been set, this code --
//      // along with all 'BSLS_ASSERT_OPT' macros -- will not instantiate,
//      // enabling us to verify that the combined runtime overhead of all such
//      // (redundant) defensive code is at worst negligible, if not
//      // unmeasurable.
//
//      if (!MyDateImpUtil::isValidSerialDate(d_serialDate)) {
//
//          // Our invariant is corrupted.
//
//  #ifdef BSLS_ASSERT_IS_ACTIVE
//          // Providing debugging information in this mode would be useful.
//
//          std::cerr << "\nxyza::MyDate: Invalid internal serial date value "
//                    << d_serialDate << '.' << std::endl;
//
//  #endif // BSLS_ASSERT_IS_ACTIVE
//
//          // In safe mode, each of the 'MyClass' methods fully guards its
//          // preconditions: There is simply no easy way to get here!
//
//          BSLS_ASSERT_SAFE("Probable rogue memory overwrite!" && 0);
//
//          // If we get here, we're corrupted, but not in safe mode!
//
//          return stream << "(* Invalid 'MyDate' State "
//                        << d_serialDate
//                        << " *)" << std::flush;                     // RETURN
//
//      }
//  #endif // BSLS_ASSERT_OPT_IS_ACTIVE
//
//      // If we get here in a production build, this object is "sane": Do
//      // whatever this 'print' method would normally do, assuming that no
//      // method preconditions or object invariants are violated.
//
//      // ...  <*** Your (Normal-Case) Formatting Code Here! ***>
//
//      return stream;
//  }
//..
///Example 8: Conditional Compilation of Support Functions
///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Occasionally a function may exist only to support a specific set of
// assertions.  Often this can happen when a large expression that captures a
// complicated precondition wants to be refactored into a distinct location to
// ease understanding of it.  When this happens the function might still remain
// as a private implementation detail of the class.
//
// When the only assertion macros that use the function are disabled this can
// lead to a compiler warning about a function being unused, and the
// corresponding code bloat from having the function available might be an
// overhead that is not desired.
//
// In order to totally remove the function when it is not needed, the 'IS_USED'
// suffixed macros can be used to guard the declaration and definition of the
// function.  Suppose we have a 'class' with a function having a complex
// precondition, and that precondition check is both private and only needed
// when the assertions that use it are enabled.  In that case, we can guard the
// definitions and declarations against even being compiled like this:
//..
//  class ComplexObject {
//      // ...
//  #if defined(BSLS_ASSERT_SAFE_IS_USED)
//      bool isPurplish() const;
//          // Return 'true' if the current state of this object fits within
//          // the complex requirements of being sufficiently purple, false
//          // otherwise.
//  #endif
//      // ...
//  public:
//      // MANIPULATORS
//   void doSomethingPurpley();
//          // Do something purpley.  The behavior is undefined unless this
//          // object is currently purplish (contact customer support to know
//          // the current threshholds for purplishness).
//  };
//
//  #if defined(BSLS_ASSERT_SAFE_IS_USED)
//  bool ComplexObject::isPurplish() const
//  {
//      // The real implementation would encode the complex logic of needing to
//      // determine if this object feels purplish at the moment.
//      return true;
//  }
//  #endif
//
//  void ComplexObject::doSomethingPurpley()
//  {
//      BSLS_ASSERT_SAFE(isPurplish());
//  }
//..
// Now, the 'ComplexObject::isPurplish' function will only exist in a subset of
// builds:
//: o When 'BSLS_ASSERT_SAFE' assertions are enabled in assert or review mode,
//:   the function will be compiled and invoked.
//: o When 'BSLS_ASSERT_VALIDATE_DISABLED_MACROS' is defined the function will
//:   be compiled.  This will make sure that a future change does not
//:   invalidate the implementation of 'isPurplish()' even though it is not
//:   used.
//: o When 'BSLS_ASSERT_SAFE' assertions are assumed the function will be
//:   compiled and might be invoked, or at least have its implementation
//:   inspected by the compiler to improve code generation.
//
///Example 9: Conditional Compilation of Support Code
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Sometimes there is code that needs to run in a function before an assertion
// to gather information needed only by that assertion.  Often this can be
// capturing input values or other system state before it is modified and
// verifying at the end of a function that the values are changed (or not)
// appropriately.
//
// When the corresponding assertion macro is not active in assert or review
// mode the supporting code should not be executed at all.  Importantly,
// because the capturing of additional information is an extra cost, the
// assertion itself does not lend itself to being assumed.
//
// Suppose we have a function that wishes to swap the values of its input:
//..
//  struct MySwapper {
//      template <class T>
//      static void swap(T& lhs, T& rhs)
//          // Exchange the values of the specified 'lhs' and 'rhs'.
//      {
//          T tmp = lhs;
//          lhs = rhs;
//          rhs = tmp;
//      }
//  };
//..
// This works great as a simple 'swap' implementation, but we would like to
// assert in safe mode that it is doing the correct thing.  In order to do that
// we need to capture the initial values of our inputs before doing anything
// else, and we want to do this only when the respective assertions are
// enabled.  Here we would guard our code and our assertions in a check that
// 'BSLS_ASSERT_SAFE_IS_ACTIVE' is defined, like this:
//..
//  struct MySwapper {
//      template <class T>
//      static void swap(T& lhs, T& rhs)
//          // Exchange the values of the specified 'lhs' and 'rhs'.
//      {
//  #if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
//          T origLhs(lhs);
//          T origRhs(rhs);
//  #endif
//          T tmp = lhs;
//          lhs = rhs;
//          rhs = tmp;
//  #if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
//          BSLS_ASSERT_SAFE(rhs == origLhs);
//          BSLS_ASSERT_SAFE(lhs == origRhs);
//  #endif
//      }
//  };
//..

#include <bsls_annotation.h>
#include <bsls_assertimputil.h>
#include <bsls_buildtarget.h>
#include <bsls_compilerfeatures.h>
#include <bsls_keyword.h>
#include <bsls_performancehint.h>
#include <bsls_platform.h>
#include <bsls_review.h>

#ifdef BSLS_ASSERT_USE_CONTRACTS
#include <contract>
#endif

                       // =============================
                       // Checks for Pre-Defined macros
                       // =============================

#if defined(BSLS_ASSERT_OPT)
#error BSLS_ASSERT_OPT is already defined!
#endif

#if defined(BSLS_ASSERT_OPT_IS_ACTIVE)
#error BSLS_ASSERT_OPT_IS_ACTIVE is already defined!
#endif

#if defined(BSLS_ASSERT_OPT_IS_ASSUMED)
#error BSLS_ASSERT_OPT_IS_ASSUMED is already defined!
#endif

#if defined(BSLS_ASSERT_OPT_IS_REVIEW)
#error BSLS_ASSERT_OPT_IS_REVIEW is already defined!
#endif

#if defined(BSLS_ASSERT_OPT_IS_USED)
#error BSLS_ASSERT_OPT_IS_USED is already defined!
#endif

#if defined(BSLS_ASSERT)
#error BSLS_ASSERT is already defined!
#endif

#if defined(BSLS_ASSERT_IS_ACTIVE)
#error BSLS_ASSERT_IS_ACTIVE is already defined!
#endif

#if defined(BSLS_ASSERT_IS_ASSUMED)
#error BSLS_ASSERT_IS_ASSUMED is already defined!
#endif

#if defined(BSLS_ASSERT_IS_REVIEW)
#error BSLS_ASSERT_IS_REVIEW is already defined!
#endif

#if defined(BSLS_ASSERT_IS_USED)
#error BSLS_ASSERT_IS_USED is already defined!
#endif

#if defined(BSLS_ASSERT_SAFE)
#error BSLS_ASSERT_SAFE is already defined!
#endif

#if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
#error BSLS_ASSERT_SAFE_IS_ACTIVE is already defined!
#endif

#if defined(BSLS_ASSERT_SAFE_IS_ASSUMED)
#error BSLS_ASSERT_SAFE_IS_ASSUMED is already defined!
#endif

#if defined(BSLS_ASSERT_SAFE_IS_REVIEW)
#error BSLS_ASSERT_SAFE_IS_REVIEW is already defined!
#endif

#if defined(BSLS_ASSERT_SAFE_IS_USED)
#error BSLS_ASSERT_SAFE_IS_USED is already defined!
#endif

#if defined(BSLS_ASSERT_INVOKE)
#error BSLS_ASSERT_INVOKE is already defined!
#endif

#if defined(BSLS_ASSERT_INVOKE_NORETURN)
#error BSLS_ASSERT_INVOKE_NORETURN is already defined!
#endif

                     // =================================
                     // (BSLS) "ASSERT" Macro Definitions
                     // =================================

// Implementation Note: We wrap the 'if' statement below in a (seemingly
// redundant) do-while-false loop to require, syntactically, a trailing
// semicolon, and to ensure that the macro behaves properly in an if-then-else
// context -- even if one forgets to wrap, with curly braces, the body of an
// 'if' having just a single 'BSLS_ASSERT*' statement.

               // =============================================
               // Factored Implementation for Internal Use Only
               // =============================================

#if !(defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE)   ||                             \
      defined(BSLS_ASSERT_LEVEL_ASSERT)        ||                             \
      defined(BSLS_ASSERT_LEVEL_ASSERT_OPT)    ||                             \
      defined(BSLS_ASSERT_LEVEL_NONE)          ||                             \
      defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)    ||                             \
      defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT) ||                             \
      defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE))
    #define BSLS_ASSERT_NO_ASSERTION_MACROS_DEFINED 1
#else
    #define BSLS_ASSERT_NO_ASSERTION_MACROS_DEFINED 0
#endif

#ifdef BSLS_ASSERT_USE_CONTRACTS
#define BSLS_ASSERT_ASSERT_IMP(X,LVL) [[ assert check_never_continue : X ]]

#define BSLS_ASSERT_ASSUME_IMP(X,LVL) [[ assert assume : X ]]
#define BSLS_ASSERT_ASSUME_ENABLED

#ifdef BSLS_ASSERT_VALIDATE_DISABLED_MACROS
#define BSLS_ASSERT_DISABLED_IMP(X,LVL) [[ assert ignore : X ]]
#else
#define BSLS_ASSERT_DISABLED_IMP(X,LVL)
#endif

#else
#define BSLS_ASSERT_ASSERT_IMP(X,LVL) do {                                    \
        if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!(X))) {                    \
            BSLS_PERFORMANCEHINT_UNLIKELY_HINT;                               \
            BloombergLP::bsls::AssertViolation violation(                     \
                                                     #X,                      \
                                                     BSLS_ASSERTIMPUTIL_FILE, \
                                                     BSLS_ASSERTIMPUTIL_LINE, \
                                                     LVL);                    \
            BloombergLP::bsls::Assert::invokeHandler(violation);              \
        }                                                                     \
    } while (false)

#if defined(BSLS_PLATFORM_CMP_CLANG)

#define BSLS_ASSERT_ASSUME_IMP(X,LVL) __builtin_assume((X)?true:false)
#define BSLS_ASSERT_ASSUME_ENABLED

#elif defined(BSLS_PLATFORM_CMP_GNU)
// While a common practice with GCC is to implement assumptions using an
// expression of the form 'if (!(X)) __builtin_unreachable();', this idiom
// relies on the expression 'X' being inline and truly sideeffect free before
// GCC will consistently elide the check itself, making this a pessimisation
// when used arbitrarily.  Because of this we do not attempt to leverage
// assumption on GCC and leave the following commented out:
//..
// #define BSLS_ASSERT_ASSUME_IMP(X,LVL) if (!(X)) { __builtin_unreachable(); }
// #define BSLS_ASSERT_ASSUME_ENABLED
//..

#elif defined (BSLS_PLATFORM_CMP_MSVC)
#define BSLS_ASSERT_ASSUME_IMP(X,LVL) __assume((X)?true:false)
#define BSLS_ASSERT_ASSUME_ENABLED

#endif

#if !defined(BSLS_ASSERT_ASSUME_IMP)
// The above flavors of 'assumption' are the only available ones that we
// support, and the only platforms where we currently attempt to use
// assumption.
#define BSLS_ASSERT_ASSUME_IMP(X,LVL) BSLS_ASSERT_DISABLED_IMP(X,LVL)
#endif

#ifdef BSLS_ASSERT_VALIDATE_DISABLED_MACROS
#define BSLS_ASSERT_DISABLED_IMP(X,LVL) (void)sizeof((!(X))?true:false)
#else
#define BSLS_ASSERT_DISABLED_IMP(X,LVL)
#endif
#endif

                              // ================
                              // BSLS_ASSERT_SAFE
                              // ================

// Determine if 'BSLS_ASSERT_SAFE' should be active.

// Define the control macros, also usable from client code.
#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE)                                    \
    || BSLS_ASSERT_NO_ASSERTION_MACROS_DEFINED && (                           \
           defined(BDE_BUILD_TARGET_SAFE_2) ||                                \
           defined(BDE_BUILD_TARGET_SAFE)         )
    #define BSLS_ASSERT_SAFE_IS_ACTIVE
#elif defined(BSLS_REVIEW_SAFE_IS_ACTIVE)
    #define BSLS_ASSERT_SAFE_IS_REVIEW
#elif defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE) &&                               \
      !defined(BSLS_REVIEW_OPT_IS_ACTIVE) &&                                  \
      !defined(BSLS_REVIEW_IS_ACTIVE) &&                                      \
      !defined(BSLS_REVIEW_SAFE_IS_ACTIVE)
    #define BSLS_ASSERT_SAFE_IS_ASSUMED
#endif

// Indicate when 'BSLS_ASSERT_SAFE' arguments will be ODR-used.
#if defined(BSLS_ASSERT_SAFE_IS_REVIEW) ||                                    \
    defined(BSLS_ASSERT_SAFE_IS_ACTIVE) ||                                    \
    (defined(BSLS_ASSERT_SAFE_IS_ASSUMED)                                     \
     && defined(BSLS_ASSERT_ASSUME_ENABLED)) ||                               \
    defined(BSLS_ASSERT_VALIDATE_DISABLED_MACROS)
    #define BSLS_ASSERT_SAFE_IS_USED
#endif

// Define 'BSLS_ASSERT_SAFE' accordingly.

#if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
    #define BSLS_ASSERT_SAFE(X) BSLS_ASSERT_ASSERT_IMP(                       \
                                     X,                                       \
                                     BloombergLP::bsls::Assert::k_LEVEL_SAFE)
#elif defined(BSLS_ASSERT_SAFE_IS_REVIEW)
    #define BSLS_ASSERT_SAFE(X) BSLS_REVIEW_REVIEW_IMP(                       \
                                     X,                                       \
                                     BloombergLP::bsls::Assert::k_LEVEL_SAFE)
#elif defined(BSLS_ASSERT_SAFE_IS_ASSUMED)
    #define BSLS_ASSERT_SAFE(X) BSLS_ASSERT_ASSUME_IMP(                       \
                                     X,                                       \
                                     BloombergLP::bsls::Assert::k_LEVEL_SAFE)
#else
    #define BSLS_ASSERT_SAFE(X) BSLS_ASSERT_DISABLED_IMP(                     \
                                     X,                                       \
                                     BloombergLP::bsls::Assert::k_LEVEL_SAFE)
#endif


                                // ===========
                                // BSLS_ASSERT
                                // ===========

// Determine if 'BSLS_ASSERT' should be active.

// Define the control macros, also usable from client code.
#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) ||                                 \
    defined(BSLS_ASSERT_LEVEL_ASSERT)                                         \
    || BSLS_ASSERT_NO_ASSERTION_MACROS_DEFINED && (                           \
           defined(BDE_BUILD_TARGET_SAFE_2) ||                                \
           defined(BDE_BUILD_TARGET_SAFE)   ||                                \
           !defined(BDE_BUILD_TARGET_OPT)         )
    #define BSLS_ASSERT_IS_ACTIVE
#elif defined(BSLS_REVIEW_IS_ACTIVE)
    #define BSLS_ASSERT_IS_REVIEW
#elif (defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE) ||                              \
       defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)) &&                           \
      !defined(BSLS_REVIEW_OPT_IS_ACTIVE) &&                                  \
      !defined(BSLS_REVIEW_IS_ACTIVE) &&                                      \
      !defined(BSLS_REVIEW_SAFE_IS_ACTIVE)
    #define BSLS_ASSERT_IS_ASSUMED
#endif

// Indicate when 'BSLS_ASSERT' arguments will be ODR-used.
#if defined(BSLS_ASSERT_IS_REVIEW) ||                                         \
    defined(BSLS_ASSERT_IS_ACTIVE) ||                                         \
    (defined(BSLS_ASSERT_IS_ASSUMED)                                          \
     && defined(BSLS_ASSERT_ASSUME_ENABLED)) ||                               \
    defined(BSLS_ASSERT_VALIDATE_DISABLED_MACROS)
    #define BSLS_ASSERT_IS_USED
#endif

// Define 'BSLS_ASSERT' accordingly.

#if defined(BSLS_ASSERT_IS_ACTIVE)
    #define BSLS_ASSERT(X) BSLS_ASSERT_ASSERT_IMP(                            \
                                   X,                                         \
                                   BloombergLP::bsls::Assert::k_LEVEL_ASSERT)
#elif defined(BSLS_ASSERT_IS_REVIEW)
    #define BSLS_ASSERT(X) BSLS_REVIEW_REVIEW_IMP(                            \
                                   X,                                         \
                                   BloombergLP::bsls::Assert::k_LEVEL_ASSERT)
#elif defined(BSLS_ASSERT_IS_ASSUMED)
    #define BSLS_ASSERT(X) BSLS_ASSERT_ASSUME_IMP(                            \
                                   X,                                         \
                                   BloombergLP::bsls::Assert::k_LEVEL_ASSERT)
#else
    #define BSLS_ASSERT(X) BSLS_ASSERT_DISABLED_IMP(                          \
                                   X,                                         \
                                   BloombergLP::bsls::Assert::k_LEVEL_ASSERT)
#endif

                              // ===============
                              // BSLS_ASSERT_OPT
                              // ===============

// Determine if 'BSLS_ASSERT_OPT' should be active.

// Define the control macros, also usable from client code.
#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) ||                                 \
    defined(BSLS_ASSERT_LEVEL_ASSERT) ||                                      \
    defined(BSLS_ASSERT_LEVEL_ASSERT_OPT)                                     \
    || BSLS_ASSERT_NO_ASSERTION_MACROS_DEFINED
    #define BSLS_ASSERT_OPT_IS_ACTIVE
#elif defined(BSLS_REVIEW_OPT_IS_ACTIVE)
    #define BSLS_ASSERT_OPT_IS_REVIEW
#elif (defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE) ||                              \
       defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT) ||                            \
       defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)) &&                              \
      !defined(BSLS_REVIEW_OPT_IS_ACTIVE) &&                                  \
      !defined(BSLS_REVIEW_IS_ACTIVE) &&                                      \
      !defined(BSLS_REVIEW_SAFE_IS_ACTIVE)
    #define BSLS_ASSERT_OPT_IS_ASSUMED
#endif

// Indicate when 'BSLS_ASSERT_OPT' arguments will be ODR-used.
#if defined(BSLS_ASSERT_OPT_IS_REVIEW) ||                                     \
    defined(BSLS_ASSERT_OPT_IS_ACTIVE) ||                                     \
    (defined(BSLS_ASSERT_OPT_IS_ASSUMED)                                      \
     && defined(BSLS_ASSERT_ASSUME_ENABLED)) ||                               \
    defined(BSLS_ASSERT_VALIDATE_DISABLED_MACROS)
    #define BSLS_ASSERT_OPT_IS_USED
#endif

// Define 'BSLS_ASSERT_OPT' accordingly.

#if defined(BSLS_ASSERT_OPT_IS_ACTIVE)
    #define BSLS_ASSERT_OPT(X) BSLS_ASSERT_ASSERT_IMP(                        \
                                      X,                                      \
                                      BloombergLP::bsls::Assert::k_LEVEL_OPT)
#elif defined(BSLS_ASSERT_OPT_IS_REVIEW)
    #define BSLS_ASSERT_OPT(X) BSLS_REVIEW_REVIEW_IMP(                        \
                                      X,                                      \
                                      BloombergLP::bsls::Assert::k_LEVEL_OPT)
#elif defined(BSLS_ASSERT_OPT_IS_ASSUMED)
    #define BSLS_ASSERT_OPT(X) BSLS_ASSERT_ASSUME_IMP(                        \
                                      X,                                      \
                                      BloombergLP::bsls::Assert::k_LEVEL_OPT)
#else
    #define BSLS_ASSERT_OPT(X) BSLS_ASSERT_DISABLED_IMP(                      \
                                      X,                                      \
                                      BloombergLP::bsls::Assert::k_LEVEL_OPT)
#endif

                             // ==================
                             // BSLS_ASSERT_INVOKE
                             // ==================

// 'BSLS_ASSERT_INVOKE' is always active and never in review mode or disabled.
#define BSLS_ASSERT_INVOKE(X) do {                                            \
        BloombergLP::bsls::AssertViolation violation(                         \
                                  X,                                          \
                                  BSLS_ASSERTIMPUTIL_FILE,                    \
                                  BSLS_ASSERTIMPUTIL_LINE,                    \
                                  BloombergLP::bsls::Assert::k_LEVEL_INVOKE); \
        BloombergLP::bsls::Assert::invokeHandler(violation);                  \
    } while (false)

// 'BSLS_ASSERT_INVOKE_NORETURN' is always active and guaranteed to never
// return (by calling 'bsls::Assert::failByAbort') even if the installed
// handler does return.
#define BSLS_ASSERT_INVOKE_NORETURN(X) do {                                   \
        BloombergLP::bsls::AssertViolation violation(                         \
                                  X,                                          \
                                  BSLS_ASSERTIMPUTIL_FILE,                    \
                                  BSLS_ASSERTIMPUTIL_LINE,                    \
                                  BloombergLP::bsls::Assert::k_LEVEL_INVOKE); \
        BloombergLP::bsls::Assert::invokeHandlerNoReturn(violation);          \
    } while (false)

                    // ===================================
                    // BSLS_ASSERT_NORETURN_INVOKE_HANDLER
                    // ===================================

#ifdef BSLS_ASSERT_ENABLE_NORETURN_FOR_INVOKE_HANDLER
#define BSLS_ASSERT_NORETURN_INVOKE_HANDLER BSLS_ANNOTATION_NORETURN
#else
#define BSLS_ASSERT_NORETURN_INVOKE_HANDLER
#endif

// A nested include guard is needed to support the test driver implementation.
#ifndef BSLS_ASSERT_RECURSIVELY_INCLUDED_TESTDRIVER_GUARD
#define BSLS_ASSERT_RECURSIVELY_INCLUDED_TESTDRIVER_GUARD

namespace BloombergLP {
namespace bsls {

                           // =====================
                           // class AssertViolation
                           // =====================

class AssertViolation {
    // This class is an unconstrained *in-core* value-semantic class that
    // characterizes the details of a assert failure that has occurred.

    // DATA
    const char *d_comment_p;      // the comment associated with the violation,
                                  // generally representing the expression that
                                  // failed

    const char *d_fileName_p;     // the name of the file where the violation
                                  // occurred

    int         d_lineNumber;     // the line number where the violation
                                  // occurred

    const char *d_assertLevel_p;  // the level and type of the violation that
                                  // occurred, generally one of the 'k_LEVEL'
                                  // constants defined in 'bsls::Review' or
                                  // 'bsls::Assert'

  public:
    // CREATORS
    BSLS_KEYWORD_CONSTEXPR
    AssertViolation(const char *comment,
                    const char *fileName,
                    int         lineNumber,
                    const char *assertLevel);
        // Create a 'AssertViolation' with the specified 'comment', 'fileName',
        // 'lineNumber', and 'assertLevel'.  Note that the supplied
        // 'assertLevel' will usually be one of the 'k_LEVEL' constants defined
        // in 'bsls::Assert'

    // ACCESSORS
    const char *assertLevel() const;
        // Return the 'assertLevel' attribute of this object.

    const char *comment() const;
        // Return the 'comment' attribute of this object.

    const char *fileName() const;
        // Return the 'fileName' attribute of this object.

    int lineNumber() const;
        // Return the 'lineNumber' attribute of this object.
};

                                // ============
                                // class Assert
                                // ============

class Assert {
    // This "utility" class maintains a pointer containing the address of the
    // current assertion-failure handler function (of type
    // 'Assert::ViolationHandler') and provides methods to administer this
    // function pointer.  The 'invokeHandler' method calls the
    // currently-installed failure handler.  This class also provides a suite
    // of standard failure-handler functions that are suitable to be installed
    // as the current 'Assert::ViolationHandler' function.  Note that clients
    // are free to install any of these ("off-the-shelf") handlers, or to
    // provide their own ("custom") assertion-failure handler functions when
    // using this facility.  Also note that assertion-failure handler functions
    // must not return (i.e., they must 'abort', 'exit', 'terminate', 'throw',
    // or hang).
    //
    // Finally, this class defines the constant strings that are passed as the
    // 'reviewLevel' to the 'bsls_review' handler for checks that failed in
    // "review mode" (see {Assertion Modes}).

  public:
    // TYPES
    typedef void (*ViolationHandler)(const AssertViolation&);
        // 'ViolationHandler' is an alias for a pointer to a function returning
        // 'void', and taking, as a parameter a single 'const' reference to a
        // 'bsls::AssertViolation' -- e.g.,
        //..
        //  void myHandler(const bsls::AssertViolation&);
        //..

    typedef void (*Handler)(const char *, const char *, int);
        // 'Handler' is an alias for a pointer to a function returning 'void',
        // and taking, as parameters, two null-terminated strings and an 'int',
        // which is the structure of all assertion-failure handler functions
        // supported by this class -- e.g.,
        //..
        //  void myHandler(const char *text, const char *file, int line);
        //..

  private:
    // FRIENDS
    friend class AssertFailureHandlerGuard;

    // PRIVATE CLASS METHODS
    static void setViolationHandlerRaw(Assert::ViolationHandler function);
        // Make the specified handler 'function' the current assertion-failure
        // handler.

    static void setFailureHandlerRaw(Assert::Handler function);
        // Make the specified 'function' the current legacy handler and set the
        // current assertion-failure handler to 'failOnViolation'.

    static void failOnViolation(const AssertViolation& violation);
        // Get the 'comment', 'fileName', and 'lineNumber' from the specified
        // 'violation' and pass them to the registered 'Handler'.  This
        // function exists to provide support for the older signature for
        // assertion-failure handlers specified by 'Handler'.

  public:
    // PUBLIC CONSTANTS

                     // 'assertLevel' Strings

    static const char k_LEVEL_SAFE[];
    static const char k_LEVEL_OPT[];
    static const char k_LEVEL_ASSERT[];
    static const char k_LEVEL_INVOKE[];

    // PUBLIC CLASS DATA
    static const char *k_permitOutOfPolicyReturningAssertionBuildKey;
                                       // This constant has the value "No".
                                       // See {Assertion Handler Policy}.

    // CLASS METHODS

                      // Administrative Methods

    static void setViolationHandler(Assert::ViolationHandler function);
        // Make the specified violation handler 'function' the current
        // assertion-failure handler.  This method has no effect if the
        // 'lockAssertAdministration' method has been called.

    static void setFailureHandler(Assert::Handler function);
        // Make the specified handler 'function' the current assertion-failure
        // handler.  This method has no effect if the
        // 'lockAssertAdministration' method has been called.

    static void lockAssertAdministration();
        // Disable all subsequent calls to 'setFailureHandler'.  Note that this
        // method has no effect on the behavior of a
        // 'AssertFailureHandlerGuard' object.

    static Assert::Handler failureHandler();
        // Return the address of the currently installed assertion-failure
        // handler function if it is a 'Handler' (and not a
        // 'ViolationHandler'); otherwise, return 'NULL'.

    static Assert::ViolationHandler violationHandler();
        // Return the address of the currently installed assertion-failure
        // handler function.

                // Dispatcher Method (called from within macros)

    BSLS_ASSERT_NORETURN_INVOKE_HANDLER
    static void invokeHandler(const AssertViolation& violation);
        // Invoke the currently installed assertion-failure handler function
        // with the specified 'violation'.  The behavior is undefined if the
        // macro 'BSLS_ASSERT_ENABLE_NORETURN_FOR_INVOKE_HANDLER' is defined,
        // and the currently installed assertion-failure handler function
        // returns to the caller (i.e., the assertion handler does *not*
        // 'abort', 'exit', 'terminate', 'throw', or hang).  Note that this
        // function is intended for use by the (BSLS) "ASSERT" macros, but may
        // also be called by clients directly as needed (preferably with
        // 'BSLS_ASSERT_INVOKE').  Also note that the configuration macro
        // 'BSLS_ASSERT_ENABLE_NORETURN_FOR_INVOKE_HANDLER' is intended to
        // support static analysis tools, which require an annotation to see
        // that a failed "ASSERT" prevents further execution of a function with
        // "bad" values.

    BSLS_ASSERT_NORETURN_INVOKE_HANDLER
    static void invokeHandler(const char *text, const char *file, int line);
        // !DEPRECATED!: Use 'invokeHandler(const AssertViolation&)' instead.
        //
        // Invoke the currently installed assertion-failure handler function
        // with the specified expression 'text', 'file' name, and 'line' number
        // as its arguments.  The behavior is undefined if the macro
        // 'BSLS_ASSERT_ENABLE_NORETURN_FOR_INVOKE_HANDLER' is defined, and the
        // currently installed assertion-failure handler function returns to
        // the caller (i.e., the assertion handler does *not* 'abort', 'exit',
        // 'terminate', 'throw', or hang).  Note that this function is
        // deprecated, as the (BSLS) "ASSERT" macros all now use the
        // 'bsls::AssertViolation' overload of 'invokeHandler' instead.

    BSLS_ANNOTATION_NORETURN
    static void invokeHandlerNoReturn(const AssertViolation &violation);
        // Invoke the currently installed assertion-failure handler function
        // with the specified 'violation'.  If the handler returns normally,
        // invoke 'bsls::Assert::failByAbort'.

#ifdef BSLS_ASSERT_USE_CONTRACTS
    static void invokeLanguageContractHandler(
                                     const std::contract_violation& violation);
        // Call 'invokeHandler' with an 'AssertViolation' with properties from
        // the specified 'violation'.
#endif

                      // Standard Assertion-Failure Handlers

    BSLS_ANNOTATION_NORETURN
    static void failByAbort(const AssertViolation& violation);
        // (Default Handler) Emulate the invocation of the standard 'assert'
        // macro with a 'false' argument, using the expression 'comment',
        // 'file' name, and 'line' number from the specified 'violation' to
        // generate a helpful output message and then, after logging,
        // unconditionally aborting.  Note that this handler function is the
        // default installed assertion handler.

    BSLS_ANNOTATION_NORETURN
    static void failBySleep(const AssertViolation& violation);
        // Use the expression 'comment', 'file' name, and 'line' number from
        // the specified 'violation' to generate a helpful output message and
        // then, after logging, spin in an infinite loop.  Note that this
        // handler function is useful for hanging a process so that a debugger
        // may be attached to it.

    BSLS_ANNOTATION_NORETURN
    static void failByThrow(const AssertViolation& violation);
        // Throw an 'AssertTestException' whose attributes are the 'comemnt',
        // 'file', 'line', and 'level' from the specified 'violation' provided
        // that 'BDE_BUILD_TARGET_EXC' is defined; otherwise, log an
        // appropriate message and abort the program (similar to
        // 'failByAbort').

    BSLS_ANNOTATION_NORETURN
    static void failAbort(const char *comment, const char *file, int line);
        // !DEPRECATED!: Use 'failByAbort' instead.
        //
        // Emulate the invocation of the standard 'assert' macro with a 'false'
        // argument, using the specified expression 'comment', 'file' name, and
        // 'line' number to generate a helpful output message and then, after
        // logging, unconditionally aborting.

    BSLS_ANNOTATION_NORETURN
    static void failSleep(const char *comment, const char *file, int line);
        // !DEPRECATED!: Use 'failBySleep' instead.
        //
        // Use the specified expression 'comment', 'file' name, and 'line'
        // number to generate a helpful output message and then, after logging,
        // spin in an infinite loop.  Note that this handler function is useful
        // for hanging a process so that a debugger may be attached to it.

    BSLS_ANNOTATION_NORETURN
    static void failThrow(const char *comment, const char *file, int line);
        // !DEPRECATED!: Use 'failByThrow' instead.
        //
        // Throw an 'AssertTestException' whose attributes are the specified
        // 'comemnt', 'file', 'line', and 'level' provided that
        // 'BDE_BUILD_TARGET_EXC' is defined; otherwise, log an appropriate
        // message and abort the program (similar to 'failAbort').


                    // Assertion Handler Policy Enforcement

    static bool abortUponReturningAssertionFailureHandler();
        // Return 'true' if 'k_permitOutOfPolicyReturningAssertionBuildKey'
        // does not have the value "bsls-PermitOutOfPolicyReturn" or
        // 'permitOutOfPolicyReturningFailureHandler' has not previously been
        // invoked, and 'false' otherwise.  Note that returning 'true'
        // indicates that 'bsls::Assert' should abort the task if the currently
        // installed assertion-failure handler returns normally (after the
        // detection of a failed assertion).

    static void permitOutOfPolicyReturningFailureHandler();
        // DO NOT USE!  It is a violation of Bloomberg policy to invoke this
        // function without having prior authorization from senior management.
        //
        // Allow an assertion handler to return control to the calling function
        // (after a failed assertion).  The behavior is undefined if
        // 'BSLS_ASSERT_ENABLE_NORETURN_FOR_INVOKE_HANDLER' is defined (and
        // thus 'invokeHandler' would not be able to return anyway).  Note
        // that, by default, an assertion handler that attempts to return
        // normally will cause the program to be aborted.
        //
        // Internal Bloomberg users should contact the BDE team if they feel
        // their application might need to violate Bloomberg policy by allowing
        // the currently installed assertion handler to return normally (after
        // a failed assertion).
};

                      // ===============================
                      // class AssertFailureHandlerGuard
                      // ===============================

class AssertFailureHandlerGuard {
    // An object of this class saves the current assert handler and installs
    // the one specified on construction.  On destruction, the original assert
    // handler is restored.  Note that two objects of this class cannot be
    // safely used concurrently from two separate threads (but may of course
    // appear sequentially, including in nested blocks and function invocations
    // within a single thread).  Note that the behavior of objects of this
    // class is unaffected by the ('static') 'Assert::lockAssertAdministration'
    // method (i.e., the temporary replacement will occur, regardless of
    // whether that method has been invoked.)

    // DATA
    Assert::ViolationHandler d_original;       // original handler
    Assert::Handler          d_legacyOriginal; // original legacy handler

  private:
    // NOT IMPLEMENTED
    AssertFailureHandlerGuard(const AssertFailureHandlerGuard&);
    AssertFailureHandlerGuard& operator=(const AssertFailureHandlerGuard&);

  public:
    // CREATORS
    explicit AssertFailureHandlerGuard(Assert::ViolationHandler temporary);
    explicit AssertFailureHandlerGuard(Assert::Handler temporary);
        // Create a guard object that installs the specified 'temporary'
        // failure handler and automatically restores the original handler on
        // destruction.

    ~AssertFailureHandlerGuard();
        // Restore the failure handler that was in place when this object was
        // created and destroy this guard.
};

}  // close package namespace

#ifndef BDE_OPENSOURCE_PUBLICATION  // BACKWARD_COMPATIBILITY

// ============================================================================
//                           BACKWARD COMPATIBILITY
// ============================================================================

// BDE_VERIFY pragma: push
// BDE_VERIFY pragma: -SLM01
// BDE_VERIFY pragma: -CP01
// BDE_VERIFY pragma: -TR04
// BDE_VERIFY pragma: -TR17

#ifndef BDE_OMIT_INTERNAL_DEPRECATED
                         // =========================
                         // BDE_ASSERT_H (deprecated)
                         // =========================

// Active in "Safe Mode"

#define BDE_ASSERT_H(X) BSLS_ASSERT_SAFE(X)
#define BSL_ASSERT_H(X) BSLS_ASSERT_SAFE(X)    // introduced during migration

                        // ===========================
                        // BDE_ASSERT_CPP (deprecated)
                        // ===========================

// Active in "Safe Mode" and "Debug Mode"

#define BDE_ASSERT_CPP(X) BSLS_ASSERT(X)
#define BSL_ASSERT_CPP(X) BSLS_ASSERT(X)       // introduced during migration

typedef bsls::Assert bdes_Assert;
    // This alias is defined for backward compatibility.

typedef bsls::AssertFailureHandlerGuard bdes_AssertFailureHandlerGuard;
    // This alias is defined for backward compatibility.

                         // ==========================
                         // BSLS_ASSERT_H (deprecated)
                         // ==========================

// Old 'BSLS_ASSERT' implementation macro that was incorrectly used externally.

#define BSLS_ASSERT_ASSERT(X) BSLS_ASSERT_ASSERT_IMP(                         \
                                   X,                                         \
                                   BloombergLP::bsls::Assert::k_LEVEL_ASSERT)

#endif // BDE_OMIT_INTERNAL_DEPRECATED

typedef bsls::Assert bsls_Assert;
    // This alias is defined for backward compatibility.

typedef bsls::AssertFailureHandlerGuard bsls_AssertFailureHandlerGuard;
    // This alias is defined for backward compatibility.

#endif  // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY

// BDE_VERIFY pragma: pop

// ============================================================================
//                      INLINE FUNCTION DEFINITIONS
// ============================================================================

namespace bsls {
                           // ---------------------
                           // class AssertViolation
                           // ---------------------

// CREATORS
BSLS_KEYWORD_CONSTEXPR
inline
AssertViolation::AssertViolation(const char *comment,
                                 const char *fileName,
                                 int         lineNumber,
                                 const char *assertLevel)
: d_comment_p((comment == 0) ? "" : comment)
, d_fileName_p((fileName == 0) ? "" : fileName)
, d_lineNumber(lineNumber)
, d_assertLevel_p((assertLevel == 0) ? "" : assertLevel)
{
}

// ACCESSORS
inline
const char *AssertViolation::assertLevel() const
{
    return d_assertLevel_p;
}

inline
const char *AssertViolation::comment() const
{
    return d_comment_p;
}

inline
const char *AssertViolation::fileName() const
{
    return d_fileName_p;
}

inline
int AssertViolation::lineNumber() const
{
    return d_lineNumber;
}

}  // close package namespace
}  // close enterprise namespace

#endif // deeper include guard

          // ========================================================
          // UNDEFINE THE LOCALLY-SCOPED IMPLEMENTATION DETAIL MACROS
          // ========================================================

#undef BSLS_ASSERT_NORETURN_INVOKE_HANDLER
#undef BSLS_ASSERT_NO_ASSERTION_MACROS_DEFINED
#undef BSLS_ASSERT_ASSUME_ENABLED

                 // =========================================
                 // IMPLEMENTATION USING THE C++ PREPROCESSOR
                 // =========================================
//
// At most one of the following build options may be set during the compilation
// of any component that includes 'bsls_assert.h':
//..
//  BSLS_ASSERT_LEVEL_ASSERT_SAFE
//  BSLS_ASSERT_LEVEL_ASSERT
//  BSLS_ASSERT_LEVEL_ASSERT_OPT
//  BSLS_ASSERT_LEVEL_NONE
//  BSLS_ASSERT_LEVEL_ASSUME_SAFE
//  BSLS_ASSERT_LEVEL_ASSUME_ASSERT
//  BSLS_ASSERT_LEVEL_ASSUME_OPT
//..
// ----------------------------------------------------------------------------

#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) &&                                 \
    defined(BSLS_ASSERT_LEVEL_ASSERT)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSERT
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) &&                                 \
    defined(BSLS_ASSERT_LEVEL_ASSERT_OPT)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSERT_OPT
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) &&                                 \
    defined(BSLS_ASSERT_LEVEL_NONE)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT_SAFE and ..._LEVEL_NONE
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) &&                                 \
    defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSUME_OPT
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) &&                                 \
    defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSUME_ASSERT
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE) &&                                 \
    defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT_SAFE and ..._LEVEL_ASSUME_SAFE
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT) &&                                      \
    defined(BSLS_ASSERT_LEVEL_ASSERT_OPT)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT and ..._LEVEL_ASSERT_OPT
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT) &&                                      \
    defined(BSLS_ASSERT_LEVEL_NONE)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT and ..._LEVEL_NONE
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT) &&                                      \
    defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT and ..._LEVEL_ASSUME_OPT
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT) &&                                      \
    defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT and ..._LEVEL_ASSUME_ASSERT
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT) &&                                      \
    defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT and ..._LEVEL_ASSUME_SAFE
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) &&                                  \
    defined(BSLS_ASSERT_LEVEL_NONE)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT_OPT and ..._LEVEL_NONE
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) &&                                  \
    defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT_OPT and ..._LEVEL_ASSUME_OPT
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) &&                                  \
    defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT_OPT and ..._LEVEL_ASSUME_ASSERT
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSERT_OPT) &&                                  \
    defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSERT_OPT and ..._LEVEL_ASSUME_SAFE
#endif

#if defined(BSLS_ASSERT_LEVEL_NONE) &&                                        \
    defined(BSLS_ASSERT_LEVEL_ASSUME_OPT)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_NONE and ..._LEVEL_ASSUME_OPT
#endif

#if defined(BSLS_ASSERT_LEVEL_NONE) &&                                        \
    defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_NONE and ..._LEVEL_ASSUME_ASSERT
#endif

#if defined(BSLS_ASSERT_LEVEL_NONE) &&                                        \
    defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_NONE and ..._LEVEL_ASSUME_SAFE
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSUME_OPT) &&                                  \
    defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSUME_OPT and ..._LEVEL_ASSUME_ASSERT
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSUME_OPT) &&                                  \
    defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSUME_OPT and ..._LEVEL_ASSUME_SAFE
#endif

#if defined(BSLS_ASSERT_LEVEL_ASSUME_ASSERT) &&                               \
    defined(BSLS_ASSERT_LEVEL_ASSUME_SAFE)
#error incompatible BSLS_ASSERT levels:                                       \
..._LEVEL_ASSUME_ASSERT and ..._LEVEL_ASSUME_SAFE
#endif

#endif

// ----------------------------------------------------------------------------
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------