# Adding a global contract assumption mode P1730R0 Published: 2019-06-14 Authors: Hyman Rosen (hrosen4@bloomberg.net) John Lakos (jlakos@bloomberg.net) Alisdair Meredith (ameredith1@bloomberg.net) ## Abstract This paper proposes adding a global contract assumption mode, in order to permit the addition of contracts without affecting the behavior of code that already interacts with the contract conditions. ## Rationale Contracts provide a means for programs to state truths in ways that programming systems may act upon. It is anticipated that when contracts are adopted in C++, existing programs will be augmented with them to express such truths currently written as comments or implemented through ordinary condition checks. It is important that there be a way to add contracts such that programs do not begin behaving in undesired ways when checking is disabled. Otherwise adding contracts becomes a dangerous activity rather than a means for enhancing program correctness - programs that currently check for out-of-contract conditions and handle them may become erroneous by the addition of a contract. Furthermore, making unchecked contracts cause undefined behavior when their predicate is false is confusingly different from the similar feature provided by _cassert_. In that case, when the `NDEBUG` macro is defined, asserted conditions are ignored, not assumed to be true. Similarly, contracts in the Ada programming language are controlled by `pragma Assertion_Policy(_policy_);`, and the language defines two policies, `Check` and `Ignore` (with the implementation permitted to add additional ones). ## Example Suppose we have the following function. ``` int foo(int x) // Return the result of dividing 100 by the specified 'x'. // The behavior is unspecified unless 'x' is positive. { if (x <= 0) throw std::domain_error("foo - parameter not positive"); return 100 / x; } ``` With contracts available, we would like to add a precondition. ``` int foo(int x) [[ expects: x > 0 ]] ``` However, if the program is built with checks disabled, the programming system is currently permitted to elide the range check within the function, leading to formal undefined behavior if the function is called with argument 0. ## Wording In `[dcl.attr.contract.check]/4`, modify as follows: **_A translation may be performed with one of the following contract assumption modes: off or on. If no contract assumption mode is explicitly selected, the default contract assumption mode is off._** During constant expression evaluation (7.7), only predicates of checked contracts are evaluated. In other contexts, it is unspecified whether the predicate for a contract that is not checked under the current build level is evaluated; if the predicate of such a contract would evaluate to false **_and contract assumption mode is on_**, the behavior is undefined. ## Conclusion Having contracts silently add new forms of undefined behavior can cause existing programs to which contracts have been added to begin behaving erroneously. Such a feature should be enabled by specific request, not by default.