6 Basics [basic]

6.10 Contract assertions [basic.contract]

6.10.1 General [basic.contract.general]

Contract assertions allow the programmer to specify properties of the state of the program that are expected to hold at certain points during execution.
Each contract assertion has a contract-assertion predicate, which is an expression of type bool.
[Note 1: 
The value of the predicate is used to identify program states that are expected.
— end note]
An invocation of the macro va_start ([cstdarg.syn]) shall not be a subexpression of the predicate of a contract assertion, no diagnostic required.
[Note 2: 
Within the predicate of a contract assertion, id-expressions referring to variables declared outside the contract assertion are const ([expr.prim.id.unqual]), this is a pointer to const ([expr.prim.this]), and the result object can be named if a result-name-introducer ([dcl.contract.res]) has been specified.
— end note]

6.10.2 Evaluation [basic.contract.eval]

An evaluation of a contract assertion uses one of the following four evaluation semantics: ignore, observe, enforce, or quick-enforce.
Observe, enforce, and quick-enforce are checking semantics; enforce and quick-enforce are terminating semantics.
It is implementation-defined which evaluation semantic is used for any given evaluation of a contract assertion.
[Note 1: 
The range and flexibility of available choices of evaluation semantics depends on the implementation and need not allow all four evaluation semantics as possibilities.
The evaluation semantics can differ for different evaluations of the same contract assertion, including evaluations during constant evaluation.
— end note]
Recommended practice: An implementation should provide the option to translate a program such that all evaluations of contract assertions use the ignore semantic as well as the option to translate a program such that all evaluations of contract assertions use the enforce semantic.
By default, evaluations of contract assertions should use the enforce semantic.
The evaluation of a contract assertion using the ignore semantic has no effect.
[Note 2: 
The predicate is potentially evaluated ([basic.def.odr]), but not evaluated.
— end note]
The evaluation A of a contract assertion using a checking semantic determines the value of the predicate.
It is unspecified whether the predicate is evaluated.
Let B be the value that would result from evaluating the predicate.
[Note 3: 
To determine whether a predicate would evaluate to true or false, an alternative evaluation that produces the same value as the predicate but has no side effects can occur.
[Example 1: struct S { mutable int g = 5; } s; void f() pre(( s.g++, false )); // #1 void g() { f(); // Increment of s.g might not occur, even if #1 uses a checking semantic. } — end example]
— end note]
There is an observable checkpoint ([intro.abstract]) C that happens before A such that any other operation O that happens before A also happens before C.
A contract violation occurs when
  • B is false,
  • the evaluation of the predicate exits via an exception, or
  • the evaluation of the predicate is performed in a context that is manifestly constant-evaluated ([expr.const]) and the predicate is not a core constant expression.
[Note 4: 
If B is true, no contract violation occurs and control flow continues normally after the point of evaluation of the contract assertion.
The evaluation of the predicate can fail to produce a value without causing a contract violation, for example, by calling longjmp ([csetjmp.syn]) or terminating the program.
— end note]
If a contract violation occurs in a context that is manifestly constant-evaluated ([expr.const]), and the evaluation semantic is a terminating semantic, the program is ill-formed.
[Note 5: 
A diagnostic is produced if the evaluation semantic is observe ([intro.compliance]).
— end note]
[Note 6: 
Different evaluation semantics chosen for the same contract assertion in different translation units can result in violations of the one-definition rule ([basic.def.odr]) when a contract assertion has side effects that alter the value produced by a constant expression.
[Example 2: constexpr int f(int i) { contract_assert((++const_cast<int&>(i), true)); return i; } inline void g() { int a[f(1)]; // size dependent on the evaluation semantic of contract_assert above } — end example]
— end note]
When the program is contract-terminated, it is implementation-defined (depending on context) whether
  • std​::​terminate is called,
  • std​::​abort is called, or
  • execution is terminated.
    [Note 7: 
    No further execution steps occur ([intro.progress]).
    — end note]
[Note 8: 
Performing the actions of std​::​terminate or std​::​abort without actually making a library call is a conforming implementation of contract-termination ([intro.abstract]).
— end note]
If a contract violation occurs in a context that is not manifestly constant-evaluated and the evaluation semantic is quick-enforce, the program is contract-terminated.
If a contract violation occurs in a context that is not manifestly constant-evaluated and the evaluation semantic is enforce or observe, the contract-violation handler ([basic.contract.handler]) is invoked with an lvalue referring to an object v of type const std​::​contracts​::​contract_violation ([support.contract.violation]) containing information about the contract violation.
Storage for v is allocated in an unspecified manner except as noted in [basic.stc.dynamic.allocation].
The lifetime of v persists for the duration of the invocation of the contract-violation handler.
If the contract violation occurred because the evaluation of the predicate exited via an exception, the contract-violation handler is invoked from within an active implicit handler for that exception ([except.handle]).
If the contract-violation handler returns normally and the evaluation semantic is observe, that implicit handler is no longer considered active.
[Note 9: 
The exception can be inspected or rethrown within the contract-violation handler.
— end note]
If the contract-violation handler returns normally and the evaluation semantic is enforce, the program is contract-terminated; if violation occurred as the result of an uncaught exception from the evaluation of the predicate, the implicit handler remains active when contract termination occurs.
[Note 10: 
If the contract-violation handler returns normally and the evaluation semantic is observe, control flow continues normally after the point of evaluation of the contract assertion.
— end note]
There is an observable checkpoint ([intro.abstract]) C that happens after the contract-violation handler returns normally such that any other operation O that happens after the contract-violation handler returns also happens after C.
[Note 11: 
The terminating semantics terminate the program if execution would otherwise continue normally past a contract violation: the enforce semantic provides the opportunity to log information about the contract violation before terminating the program or to throw an exception to avoid termination, and the quick-enforce semantic is intended to terminate the program as soon as possible as well as to minimize the impact of contract checks on the generated code size.
Conversely, the observe semantic provides the opportunity to log information about the contract violation without having to terminate the program.
— end note]
If a contract-violation handler invoked from the evaluation of a function contract assertion ([dcl.contract.func]) exits via an exception, the behavior is as if the function body exits via that same exception.
[Note 12: 
A function-try-block ([except.pre]) is the function body when present and thus does not have an opportunity to catch the exception.
If the function has a non-throwing exception specification, the function std​::​terminate is invoked ([except.terminate]).
— end note]
[Note 13: 
If a contract-violation handler invoked from an assertion-statement ([stmt.contract.assert])) exits via an exception, the search for a handler continues from the execution of that statement.
— end note]
To evaluate in sequence a list R of contract assertions:
  • Construct a list of contract assertions S such that
    • all elements of R are in S,
    • each element of R may be repeated an implementation-defined number of times within S, and
    • if a contract assertion A precedes another contract assertion B in R, then the first occurrence of A precedes the first occurrence of B in S.
  • Evaluate each element of S such that, if a contract assertion A precedes a contract assertion B in S, then the evaluation of A is sequenced before the evaluation of B.
[Example 3: void f(int i) { contract_assert(i > 0); // #1 contract_assert(i < 10); // #2 // valid sequence of evaluations: #1 #2 // valid sequence of evaluations: #1 #1 #2 #2 // valid sequence of evaluations: #1 #2 #1 #2 // valid sequence of evaluations: #1 #2 #2 #1 // invalid sequence of evaluations: #2 #1 } — end example]
Recommended practice: An implementation should provide an option to perform a specified number of repeated evaluations for contract assertions.
By default, no repeated evaluations should be performed.

6.10.3 Contract-violation handler [basic.contract.handler]

The contract-violation handler of a program is a function named ​::​handle_contract_violation.
The contract-violation handler shall have a single parameter of type “lvalue reference to const std​::​contracts​::​contract_violation” and shall return void.
The contract-violation handler may have a non-throwing exception specification.
The implementation shall provide a definition of the contract-violation handler, called the default contract-violation handler.
[Note 1: 
No declaration for the default contract-violation handler is provided by any standard library header.
— end note]
Recommended practice: The default contract-violation handler should produce diagnostic output that suitably formats the most relevant contents of the std​::​contracts​::​contract_violation object, rate-limited for potentially repeated violations of observed contract assertions, and then return normally.
It is implementation-defined whether the contract-violation handler is replaceable ([dcl.fct.def.replace]).
If the contract-violation handler is not replaceable, a declaration of a replacement function for the contract-violation handler is ill-formed, no diagnostic required.