<!DOCTYPE html>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<style type="text/css">
pre {font-family: "Consolas", "Lucida Console", monospace; margin-left:20pt; }
code {font-family: "Consolas", "Lucida Console", monospace; }
pre > i   { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
code > i  { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
pre > em  { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
code > em { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }

p.example   { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2

code.extract { background-color: #F5F6A2; }
pre.extract  { margin-left: 2em; background-color: #F5F6A2;  border: 1px solid #E1E28E; }

p.function    { }
.attribute    { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

.editor { color: #4444BB; font-style: normal; background-color: #DDDDDD; }

tab { padding-left: 4em; }
tab3 { padding-left: 3em; }

.link { float: right }

blockquote.std    { color: #000000; background-color: #F1F1F1;  border: 1px solid #D1D1D1;  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;  color: #000000; background-color: #FFEBFF;  border: 1px solid #ECD7EC;  padding-left: 0.5em; padding-right: 0.5em; ; }
blockquote.stdins { text-decoration: underline;  color: #000000; background-color: #C8FFC8;  border: 1px solid #B3EBB3; padding: 0.5em; }
table.header { border: 0px; border-spacing: 0;  margin-left: 0px; font-style: normal; }
table { border: 1px solid black; border-spacing: 0px;  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;  padding-left: 0.4em; border: none;  padding-right: 0.4em; border: none; }
td { text-align: left;  padding-left: 0.4em; border: none;  padding-right: 0.4em; border: none; }

.revision   { /*color: #005599;*/ }
.grammar { list-style-type:none }

</style>

<title>Minimum Contract Support: either Ignore or Check_and_abort</title>

</head>
<body>

<table class="header"><tbody>
  <tr>
    <th>Document number:&nbsp;&nbsp;</th><th> </th><td>P2388R1</td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;</th><th> </th><td>2021-08-14</td>
  </tr>
  <tr>
    <th>Audience:&nbsp;&nbsp;</th><th> </th><td>SG21</td>
  </tr>
  <tr>
    <th>Reply-to:&nbsp;&nbsp;</th><th> </th><td><address>Andrzej Krzemieński &lt;akrzemi1 at gmail dot com&gt;</address>
    <address>Gašper Ažman &lt;gasper dot azman at gmail dot com&gt;</address>
      </td>
  </tr>
</tbody></table>

<h1>Minimum Contract Support: either <em>Ignore</em> or <em>Check_and_abort</em></h1>

<p>
This paper proposes a minimal contract support framework for C++.
It is the first phase of the plan in
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2182r1.html">[P2182R1]</a>. As such, it is the
Minimum Viable Product (MVP) achieving the following goals:
</p>

<ol>
  <li>Be a coherent whole, and provide a value to multiple groups of developers.</li>
  <li>Be small enough to progress through the standardization pipeline for c++23.</li>
  <li>Side-step all controversial design issues to obtain consensus.</li>
</ol>

<p>As a sketch: a function containing an assertion annotation:</p>

<pre>bool fun(int a, int b)
{
  [[assert: are_compatible(a, b)]]; <em>// assertion annotation</em>
  return transform(a, b);
}</pre>

<p>In <em>Check_and_abort</em> mode, this renders runtime code equivalent to:</p>

<pre>bool fun(int a, int b)
{
  [&amp;]() noexcept {
    if (are_compatible(a, b)) {} else {
      CONTRACT_VIOLATION_HANDLER("are_compatible(a, b)");
      std::abort();
    }
  }(); <em>// immediately invoked lambda</em>

  return transform(a, b);
}</pre>

<p> That is: a runtime check is performed, and if it returns something <code>false</code>y, an implementation-defined message is displayed
    to the stream buffer associated with the object <code>stderr</code> and <code>std::abort()</code> is called. If any exception is thrown during the evaluation of the predicate or the
    logging statement, <code>std::terminate()</code> is called.</p>

<p>In <em>Ignore</em> mode, the code is rendered without calling the lambda (thus odr-using the predicate, but not evaluating it).</p>


<h2><a name="rev">0. Revision history <span class="link">{rev}</span></a></h2>


<h3><a name="rev.r01">0.1. R0 → R1<span class="link">{rev.r01}</span></a></h3>

<ol>
  <li>Added the proposed wording.</li>
  <li>Added new design point: incompatible contract annotations in different translation units.</li>
  <li>Added new design point: referencing value and rvalue references function arguments in postconditions.</li>
  <li>Resolved open issue: objects are not treated as const in contract predicates.</li>
  <li>Resolved open issue: implementations may (but don't have to)
runtime-check contract annotations in core constant expressions even in
<em>Ignore</em> mode.</li>
  <li>Added an open issue: alternate postcondition syntax.</li>
  <li>Expanded the design details and rationale section, based on feedback from SG21.</li>
</ol>

<h2><a name="term">1. Terminology <span class="link">{term}</span></a></h3>

<p> In this document we use the following terms recommended in
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2038r0.html">[P2038R0]</a> and
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2358r0.pdf">[P2358R0]</a>:</p>

<dl>
<dt>Abstract machine violation</dt>
<dd>This is what the Standard defines as Undefined Behavior in Clause 4
through Clause 15, which is often called a "hard undefined behavior" or
"language undefined behavior",
    which includes things like <code>++INT_MAX</code>, <code>1/0</code> or null pointer dereference.</dd>
<dt>BizBug</dt>
<dd>A situation where a function is invoked in a way that is disallowed
by its specification; or when it returns a value or has a side effect
    disallowed by the specification. (This presupposes the existence of
function "specification".)</dd>

<dt>Contract annotation</dt>
<dd>Declaration of a precondition or a postcondition or an assertion, such as <code>[[pre: i != 0]]</code> or <code>[[assert: x != y]]</code>.
    Contract annotations can express a subset of function specification.</dd>
</dl>

<h2><a name="ovr">2. Proposal <span class="link">{ovr}</span></a></h2>

<p>There are three kinds of contract annotations: <strong>preconditions</strong> and <strong>postconditions</strong> on function declarations, and <strong>assertions</strong> inside function bodies.</p>

<p>Contract annotations use an attribute-like syntax:</p>

<pre>int select(int i, int j)   <em>// first declaration</em>
  [[pre: i &gt;= 0]]
  [[pre: j &gt;= 0]]
  [[post r: r &gt;= 0]];      <em>// r names the return value</em>

int select(int i, int j);  <em>// subsequent declarations can</em>
                           <em>// repeat or ignore the annotations</em>

int select(int i, int j)   <em>// the definition</em>
{
  [[assert: _state &gt;= 0]];

  if (_state == 0) return i;
  else             return j;
}
</pre>

<p>We specirfy the semantics of two modes of program translation:</p>

<ol>
  <li><strong><em>Ignore</em></strong>: compiler checks the validity of expressions in contract annotations,
      but the annotations have no effect on the generated binary. Functions appearing in the predicate are ODR-used.
      </li>
  <li><strong><em>Check_and_abort</em></strong>: each contract annotation is checked at runtime.
      The check evaluates the corresponding predicate; if the result equals <code>false</code>,
      an implementation-defined <em>contract violation handler</em> is invoked.
      </li>
</ol>

<p> We recommend (the ISO word "should") that the default mode is <em>Check_and_abort</em>.

<h3><em>Check_and_abort</em> contract violation handler semantics</h3>

<p>The semantics of the contract violation handler are implementation-defined, subject to the following constraint:
    <b>control never leaves the violation handler</b>.
    It can stop the program, hit a breakpoint, or run forever after emailing a sysadmin, for instance.
    If the program exits, it must signal unsuccessful termination appropriately for the context, such at returning a non-zero error code (as with <code>abort()</code>).
    We recommend (the ISO word "should") that the violation handler output a diagnostic message to the standard diagnostic stream and call <code>std::abort()</code>.
    This corresponds to what <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2358r0.pdf">[P2358R0]</a>
    calls "Unspecified but never returns" and what <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1606r0.pdf">[P1606R0]</a>
    calls "check_never_continue".</p>

<h3>Name lookup in pre-/post-conditions</h3>

<p> Name lookup for preconditions and postconditions is performed as in the trailing return type.
  
<h3>Access control</h3>

<p>
Access control is performed as if the predicate was evaluated inside the body of
the function, making private and protected members of the containing class
accessible to predicates of preconditions and postconditions of member and
befriended functions.
</p>

<p> Preconditions and postconditions are checked (in <em>Check_and_abort</em> mode)
    even if the function is called through a pointer.</p>

<h3>Side-effects</h3>

<p> Side effects are supported in the predicates of contract annotations.
    Implementations are allowed to both remove or duplicate these side effects,
    so they cannot be relied upon. This is similar to the existing rules around eliding copy-constructor side-effects.

<p> Looking at the source code with contract annotations alone — that is, not looking at compiler switches —
    the programmer has no guarantee if predicates in contract annotation will be evaluated at runtime or not, or
    if the program is stopped after such evaluation. Whether the side effects of predicates are evaluated
    (one or more times) or not — even in <em>Check_and_abort</em> mode — is unspecified.</p>

<h3>Mixed-mode linking</h3>

<p> Implementations are allowed to provide a mixed mode, where some translation units are translated in
    <em>Ignore</em> mode and others in <em>Check_and_abort</em> mode. This may be necessary for linking
    the user program with compiled libraries.</p>

<h2><a name="not">3. Deferred features</a></h2>

<p>These features are deferred due to unresolved issues. This proposal makes sure not to block any of these being proposed in the future.</p>

<ul>
<li>assertion levels: unresolved issues around fallthrough, among many other things. Expecting future proposals in this space.</li>
<li>continuation mode: unresolved issues around fallthrough. Expecting future proposals in this space.</li>
<li>ability to install a custom violation handler: unresolved issues around pretty much everything.</li>
<li>a way to express preconditions and postconditions for lambdas: name lookup is already problematic
    in lambdas in the face of lambda captures. This problem is pursued in
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2036r1.html">[P2036R1]</a>,
    and until it has been solved we see no point in delaying the minimum contract support proposal.</li>
</ul>

<h2><a name="faq">4. FAQ: can I do X?<span class="link">{faq}</span></a></h3>

<h3>4.1 What you can do with this proposal:</h3>

<ol>
  <li>Programmer: The ability to declare parts of your functions' contract in the source
      code in a portable way. This alone adds value: it may help you better
      understand your function contracts. It may help your users understand
      your functions' contracts.</li>
  <li>Programmer: The ability to run your program locally in mode that checks
      all your assertions expressed in contract annotations, and aborts the program
      if any bug is detected. (This experience is similar to using C
      <code>assert()</code>, except that you can put annotations in more places.)</li>
  <li>Programmer: The ability to build your program in a mode that adds not a
      single instruction to your code, even if you put contract annotations.</li>
  <li>Static analyzer vendor: contract annotations written by your users
      can help you generate new and better diagnostics.</li>
</ol>


<h3>4.2 What you cannot do with this proposal:</h3>

<ol>
  <li>Programmer: You may not be able to (depending on the compiler) to
      runtime-check contract annotations in your code but ignore them in the
      library you link with. Libraries may need to ship binaries in two versions:
      with contract checking enabled and disabled. (The Standard Library does
      not have to introduce contracts.)
      </li>
  <li>Programmer: You will not be able to selectively disable the checking of
      some contracts. If some checks would be too expensive, you would have to
      leave them out unannotated.
      </li>
  <li>Programmer: You will not be able to run the program in test mode, where
      contract violations are reported but program is allowed to execute further.
      </li>
  <li>Library vendor: You will not be able to insert "experimental" contract
      annotations without the risk of terminating your user's program.
      </li>
      <li>Library vendor: throwing from a failed contract test is not a supported way of unit-testing contract annotations. Death-tests are available in popular testing frameworks such as google test and should work for this scenario.
      </li>
</ol>


<p> We consider these use cases valid and important. Our choice is not to
    support them in the MVP, but to ultimately enable their support in the future.
    Their omission from this paper serves one purpose: enable programmers to
    declare contract annotations as soon as possible.
    </p>


<h3><a name="ovr.lib">4.3. How does linking with 3rd-party libraries work?
    <span class="link">{ovr.lib}</span></a></h3>

<p>A library does not have to declare contract annotations
    (even the Standard Library). If so, this is as now.
</p>

<p>Libraries that declare contract annotations and ship compiled binaries
    will have to ship two versions: one compiled in <em>Ignore</em> mode, and one in <em>Check_and_abort</em>.
    This also applies to the Standard Library.
    </p>

<p>One can also see toolchains supporting mangling the contract mode into the symbol name and emitting code for both into the same fat binary.</p>


<h2><a name="mot">5. Motivation <span class="link">{mot}</span></a></h2>

<p> The motivation for adding contract support to the language has already been provided multiple times, for example in
    <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2004/n1613.pdf">[N1613]</a>,
    <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1800.pdf">[N1800]</a>,
      <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4110.pdf">[N4110]</a>,
      <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4075.pdf">[N4075]</a>,
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4135.pdf">[N4135]</a>,
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0380r0.pdf">[P0380R0]</a>,
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2182r1.html">[P2182R1]</a>.
    In brief, contract annotations allow the programmers to encode what they consider a
    bug in code. This information can be used by tools in a number of ways.</p>

<p> The motivation for starting with a minimal set of features has been provided in
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2182r1.html">[P2182R1]</a>.
    In summary, it is to minimize the risk of having the discussion or disagreement about
    the secondary features of the contract support framework impede or prevent the addition of the primary
    functionality: the ability for the programmer to communicate what is considered a bug in the program.
    The plan for the MVP is therefore to find a minimal uncontroversial subset,
    gather consensus around it, polish, and deliver it quickly.</p>

<p>The secondary features can then be proposed on top of this stable core;
   but, since it has shipped, the core part of contract support framework will not be
   at risk of being removed or postponed even if they run into issues.</p>

<p>We have observed that even the portions of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2182r1.html">[P2182R1]</a>
    arose controversies. This paper to removes these portions.
    </p>


<h3><a name="mot.two">5.1. Two programming models
    <span class="link">{mot.two}</span></a></h3>


<p> There are at least two views on what a contract violation means among the stakeholders.</p>

<p> One view is that contract violation indicates a bug, and this situation is as serious as dereferencing
    a null pointer or making an invalid access to memory. If this situation is detected at run-time,
    the only acceptable default action is to immediately abort the execution of the program
    to prevent any further damage.</p>

<p> The other view is that the contract violation is just a piece of information, usually about a bug
    (but not always: for instance, in unit tests a programmer may violate a contract on purpose), that can
    be processed in a number of ways. Program termination is one, but the program might as well just
    continue with the normal execution or jump to a different location, for example, by throwing an exception.
    </p>

<p> The two views conflict in whether anything other than program termination should be allowed after
    a runtime-confirmed contract violation, but they also have overlapping parts:</p>

<ol>
  <li>The common syntax for contract annotations.</li>
  <li>The common understanding that contract violation, at least outside of unit tests,
      indicates a bug, which programmers intend to avoid or fix.</li>
  <li>Even the second view allows for the mode where the program is just aborted.</li>
</ol>

<p> We believe that this overlapping part is already useful for many groups of programmers.
    It allows the programmers to declare what they know to be a bug in their components.
    It allows tools other than compilers — such as static analyzers or IDEs —
    to diagnose or help diagnose bugs in programs statically. The <em>Check_and_abort</em> mode
    gives a guarantee to programmers that if a bug is detected at run-time, the program —
    apart from aborting — will do no further damage. This enables UB-sanitizers to diagnose
    not only abstract machine violations ("hard" UB) but also contract violations in a uniform way
    (provided that this way does not require the program to continue after the reported violation).
    </p>

<p> Because this proposal is — we believe — a common part of the two views,
    we hope that proponents of either view should find nothing unacceptable, other than
    that it is missing features.</p>


<h3><a name="mot.too">5.2. Is the proposal not too small?
    <span class="link">{mot.too}</span></a></h3>


<p> It may appear that what is proposed is too small and not
    usable in many real-life use cases. In particular, the ability
    to continue the program execution after a runtime correctness
    check has failed is brought up in this context.</p>

<p> In section <a href="#rat.con">{rat.con}</a>, we describe
    why the design of the continuation mode, such that it
    avoids introducing surprising new reasons for undefined behavior
    and gathers consensus, will take a long time, and thus not be ready for C++23.
    </p>

<p> We can see two options:</p>

<ol>
    <li>Deliver a feature-rich solution for C++26, or later, or never.</li>
    <li>Deliver a reduced set of features for C++23; deliver the remaining features for C++26, or later or never.</li>
    </ol>

<p> The latter option subsumes the former, even if one
    disagrees that the reduced feature set is "viable" for one's use cases.
    </p>

<h2><a name="des">6. Design details <span class="link">{des}</span></a></h2>


<h3><a name="des.gol">6.1. Design goals <span class="link">{des.gol}</span></a></h3>


<p> We want to provide a uniform notation, usable in different contexts &mdash;
    in this proposal these contexts are function declarations and function
    bodies &mdash; for expressing runtime conditions, the violation of which necessarily constitutes
    a bug in the program. Such information can be consumed in a number of ways, by many different
    tools, most of which are outside of the scope of the C++ Standard; we
    want all the tools to consume the same notation. </p>

<p> We want the proposal &mdash; the number of features, the amount of wording
    changes &mdash; to be as small as possible, and remain as open for future
    extensions as possible. The goal is to deliver a small piece fast.
    We demonstrate how additional &mdash; often requested &mdash; features
    can be added on top of this proposal while preserving backwards compatibility.
   </p>

<p> We want the proposed to be zero-overhead: programmers should be able to
    add contract annotations and compile the program in a mode that doesn't add
    a single instruction to the compiled program.</p>

<p> We want other programmers to get the guarantee that the program never continues
    once it has been determined, through the correctness annotations, that it
    has encountered an illegal state. This goal seems somewhat contradictory with the previous one,
    but we manage to combine them through the introduction of <em>translation
    modes</em>. This means that a correctness annotation can have different
    effects on the compiled program, depending on what translation mode it was
    compiled with.


<h3><a name="des.pre">6.2. Predicates <span class="link">{des.pre}</span></a></h3>



<p> In addition to the grammar of contract annotations, this proposal includes the facility that uses them:
    the ability to check them at runtime, and stop the program if the check fails.

<pre>int fun(int i)
{
  [[assert: i != 0]]; <em>// correctness annotation</em>
  return i;
}

int main()
{
  fun(0);
  std::cout &lt;&lt; "hello\n";
}</pre>

<p> Running this program can have two different effects, depending on whether we enable
    the generation of runtime-checks. If we don't, the program will output "hello"
    and exit 0; but if we enable them, this program will exit via
    <code>std::abort()</code> before printing "hello".

<p> <code>[[assert:</code> <em>Pred</em><code>]]</code> is a correctness annotation:
    one that appears inside function body, as a statement. <em>Pred</em> names a
    predicate. If the predicate returns <code>false</code> it means we have a bug.
    If it returns <code>true</code>, we do not know if we have any bug or not.</p>

<p> In order for such a runtime test to work, <em>Pred</em> has to be a valid C++
    expression convertible to <code>bool</code>. However, it differs slightly
    from just any other expression.
    </p>

<p> Another consumer of contract annotations is a static analyzer that is able
    to perform a symbolic evaluation of the program and determine if any control
    path leads to a bug. (Correctness annotations provide a formal definition of
    a bug.)
    </p>

<pre>int get_count();

int fun(int i)
  [[pre: i &gt; 0]] <em>// correctness annotation</em>
{
  return i - 1;
}

int main()
{
  int count = get_count();

  if (i &lt; 0)
    return fun(-i);
  else
    return fun(i);
}</pre>

<p> <code>[[pre:</code> <em>Pred</em><code>]]</code> is <em>precondition</em>:
    it is another correctness annotation: one that appears in a function
    declaration. It says that whenever this function is called &mdash;
    just after the function arguments have been initialized &mdash; the
    predicate must <em>hold</em>, otherwise we have a bug.</p>

<p> The static analyzer could determine that if function <code>get_count()</code>
    returns 0, then function <code>fun()</code> is called such that the predicate
    in the precondition does not hold.</p>

<p> Here, a precondition "hold"ing implies having a predicate in the mathematical sense:
    one that returns a true-false answer, and has no effect on the environment,
    since in mathematics there is no such thing as an "environment".
    However, in an imperative language like C++, expressions have <em>side effects</em>.
    The expression in the precondition above doesn't have side effects, so the
    meaning is clear, but a static analyzer would have a hard time (and we also)
    if the precondition on the function read:
    </p>

<pre>int fun(int i)
  [[pre: --i &gt;= 0]]
{
  return i;
}</pre>

<p> Therefore, while the predicates in contract annotations are C++ expressions,
    we take some measures to address the situations where these expressions have
    side effects. Thus, they are not 100% C++ expressions.</p>

<p> Our choice of notation accounts for the fact that we have to address these
    two, quite different, use cases.</p>

<p> Features added in the future may further increase the difference between
    predicates in contract annotations and normal C++ expressions. One such
    extension would be a notation for inexpressible conditions as discussed in
    <a href="https://isocpp.org/files/papers/P2176R0.html">[P2176r0]</a>.
    </p>



<h3><a name="des.ret">6.3. Naming the return value
       <span class="link">{des.ret}</span></a></h3>



    <p> A postcondition expresses the effects that a function guarantees when:</p>

<ul>
   <li>its preconditions are satisfied, and</li>
   <li>when it returns normally (not via an exception or <code>longjmp</code>).</li>
</ul>

<p> One of such guarantees is the state of the returned value: </p>

<pre>char get_digit()
  [[post c: is_digit(c)]];</pre>

<p> <code>[[post</code> <em>Name</em><code>:</code> <em>Pred</em><code>]]</code>
    is a <em>postcondition</em>: it is another correctness annotation that
    appears in a function declaration.
    </p>

<p> In a function declaration the return value (or reference) doesn't have
    a name, so there is a way to introduce it. The predicate can refer to this
    name. The type of the return value is usually visible in the declaration,
    except when we use a return placeholder type and do not provide the
    definition from which the type could be deduced:</p>

<pre>auto get_digit()
  [[post c: is_digit(c)]]; <em>// error: decltype(c) unknown</em>
</pre>

<p> The compiler has to parse the contract annotation in order to determine if
    the expression is well formed, but this task is impossible when we do not
    know the type of the object. This problem does not occur in a function
    template declaration, because the task of verifying the validity of the
    expression is deferred until instantiation time:</p>

<pre>template &lt;int I&gt;
auto get_digit()
  [[post c: is_digit(c)]]; <em>// OK</em>
</pre>

<p> The problem also does not occur when we provide the body of the function
    from which the type of the return value can be deduced:</p>

<pre>auto get_digit()
  [[post c: is_digit(c)]] <em>// OK: decltype(c) is char</em>
{
  return '0';
}
</pre>

<p> This has been discussed in detail in
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1323r2.html">[P1323R2]</a>.
    </p>



<h3><a name="des.arg">6.4. Function arguments in postconditions
    <span class="link">{des.arg}</span></a></h3>


<p> A postcondition may describe a relation between the returned value and
    and function arguments:</p>

<pre>int generate(int lo, int hi)
  [[pre lo &lt;= hi]]
  [[post r: lo &lt;= r &amp;&amp; r &lt;= hi]];
</pre>

<p> The intention of the above declaration seems quite obvious. The function
    guarantees that:</p>

<ul>
  <li>The objects the user used to call the function will not be modified.</li>
  <li>The generated number will fall between the limits that the user passed.</li>
</ul>

<p> The postcondition needs to have access to the returned value, so it is
    called after the function has initialized it. In order for
    the postcondition to check the condition that the caller expects, we have to
    make sure that the function has not modified the values of function
    arguments. In order to achieve that we require that non-reference function
    arguments referenced in the postcondition must be declared const in function
    definition:</p>

<pre>int generate(int lo, int hi) <em>// error: hi and lo not const</em>
{
  return lo;
}

int generate(const int lo, const int hi) <em>// OK</em>
{
  return lo;
}
</pre>

<p> This may have the effect that if the function argument
    is returned from the function, the added <code>const</code>
    will change the implicit move into a copy, which may add an
    overhead, and may make the program ill-formed, if the type
    is not copyable. However, this will not happen behind the
    programmer's back. the programmer is first informed
    (in form of an error message) that the argument has to be
    declared <code>const</code>. It will be the programmer's
    decision to make this change. An alternative decision might
    be to not declare postcondition annotations on functions
    that cannot be rewritten so that they take their
    postcondition-referenced arguments as <code>const</code>.
    </p>

<p> Another way to put this is that postconditions referring
    to non-reference function arguments make these arguments
    part of the interface: the function no longer has freedom
    to use it at will.
    </p>

<p>This restriction does not apply to references:</p>

<pre>int generate(int&amp; lo, int&amp; hi) <em>// OK</em>
  [[pre lo &lt;= hi]]
  [[post r: lo &lt;= r &amp;&amp; r &lt;= hi]]
{
  return lo;
}
</pre>

<p> Pointers are values, so when they are passed by value, they are subject to
    the same constraints as other types passed by value.</p>



<h3><a name="des.eff">6.5. Side effects in predicates
    <span class="link">{des.eff}</span></a></h3>


<p> Side effects are allowed in predicates. Some side effects
    are desired, as described in section <a href="#rat.eff">{rat.eff}</a>,
    but they have to be "self contained": removing them
    (or a well defined portion thereof) should not affect the program behavior.
    </p>

<p> Generally, a compiler is allowed to apply code transformations as if
    the expressions in contract predicates were side-effect-free. We do not
    require or expect that the predicates are referentially transparent, because
    it is often desired to refer from them to global variables, even if they
    are mutable.</p>

<p> The compiler is allowed to replace any subexpression appearing in a contract
    annotation with just the value of this expression. There are two cases where
    the compiler has enough information to do this:</p>

<ol>
  <li>When it can peek inside the expression and observe that in order to
      provide the result, it doesn't have to evaluate the entire function
      body:

<pre>bool is_positive(int i)
{
  printf("is_positive() called\n"); <em>// this does not affect the result</em>
  return i &gt; 0;
}
</pre>
      </li>

  <li>When the same expression has already been evaluated during the
      same sequence of precondition and postcondition tests:

<pre>int produce() [[post r: p(r) &amp;&amp; q(r)]];
void consume(int i) [[pre: p(i)]] [[pre: q(i)]];

consume(produce());
</pre>

      Here, it is enough to call <code>p()</code> and <code>q()</code>
      only once, and compiler is allowed to reuse these results rather than
      calling <code>p()</code> and <code>q()</code> again.
      </li>
  </ol>

<p> However, for the second case to work, an evaluation of any predicate
    in the sequence cannot have side effects that would affect the results
    of other predicates in the sequence. This cannot be enforced
    statically, so we call it undefined behavior.</p>

<p> It is undefined behavior if evaluation of one predicate or
    subexpression thereof affects the result of any other predicate or a
    subexpression thereof in the same test sequence. It is also
    undefined behavior if the evaluation of a predicate modifies the value
    of function arguments, the returned value, or any other objects
    odr-used by the predicate. Any other side effects are allowed and
    valid.</p>

<pre>void f(int i) [[pre: ++i]]; <em>// UB if evaluated</em>
</pre>

<p>The compiler is also allowed to call the predicate twice:</p>

<pre>void f(int i) [[pre: p(i)]] [[pre: q(i)]];
</pre>

<p> When function <code>f()</code> is evaluated, it might cause
    the following sequence of precondition tests: <code>p(i)</code>,
    <code>q(i)</code>, <code>p(i)</code>, <code>q(i)</code>.
    This allows the implementations to test the preconditions
    both inside and outside the function body. This ability is
    useful for generating good error messages from preconditions:
    they have to be evaluated inside the function, in case the call
    is made through a pointer. But when a call is made directly,
    we can evaluate it outside, and then the error message points at
    the caller, rather than the callee.</p>

<p> A possible, hypothetical but valid, implementation of a
    contract annotation check would be to start a transaction,
    evaluate the predicate, save the result
    on the side, cancel the transaction (thereby erasing all
    side effects since the beginning of the transaction), and
    just using the stored value instead as a result.</p>



<h3><a name="des.ptr">6.6. Indirect function calls
        <span class="link">{des.ptr}</span></a></h3>


<p> Function pointers and references cannot have contract annotations,
    but functions with contract annotations can be assigned to them:</p>

<pre>using fpa = int(*)(int) [[pre: true]]; <em>// error</em>

using fptr = int(*)(int);
int (int i) [[pre: i &gt;= 0]];

fptr fp = f;  <em>// OK</em>
fp(1);        <em>// precondition is checked</em>
</pre>

<p> In other words, contract annotations are not part of function type.
    Thanks to this decision, you can write code like:
    </p>

<pre>int fast(int i) [[pre: i &gt; 0]];
int slow(int i) [[pre: true]];  <em>// no precondition</em>

int f(int i)
{
  int (*fp) (int) = i &gt; 0 ? fast : slow;
  return fp(i);  <em>// if fast() is called, its precondition is checked</em>
}
</pre>

<p> The consequence of this behavior is that an implementation cannot check
    the precondition in the place where function is called. The check has to
    be performed inside the function. Therefore, it is a reasonable
    implementation strategy to implement the precondition check inside the
    function in case it is called indirectly, but where the function is
    called directly, check it in the caller, in order to provide the source
    location that is the culprit of contract violation. This may sometimes
    result in checking the same precondition twice.</p>

<p> The same mechanism works for function wrappers:</p>

<pre>
using fp = int(*)(int);
int f(int i) [[pre: i &gt;= 0]];

function&lt;int(int)&gt; fp = f;  <em>// OK</em>
fp(1);   <em>// precondition is checked</em>
</pre>



<h3><a name="des.vir">6.7. Virtual functions
        <span class="link">{des.vir}</span></a></h3>


<p> You can put contract annotations on virtual functions, however they
    behave in a certain way in the overriding functions. You can omit
    contract annotations in the overriding function. The overriding function
    then has the same contract annotations as the virtual function in the base
    class, and the names in the predicates are looked up in the context of the
    base class.</p>

<pre>
static const int N = 1; <em>// #1</em>

struct Base
{
  virtual void f() [[pre: N == 1]];
};

template &lt;int N&gt;       <em>// N is shadowed</em>
struct Deriv : Base
{
  void f() override;
};

int main()
{
  Deriv&lt;2&gt;{}.f(); <em>// precondition test passes</em>
}
</pre>

<p> The precondition in the overriding function is <code>N == 1</code>,
    but the name lookup is performed in the context of class <code>Base</code>,
    so it sees the global variable <code>N</code> declared in line #1.</p>

<p> You cannot declare a contract annotation in the overriding function
    if the virtual function in the base class doesn't have a corresponding
    contract annotation.
    </p>

<p> You can declare a contract annotation in the overriding function, but it has
    to be identical (modulo the names of function parameters) to the
    corresponding contract in the overridden function. However, the program is
    ill formed, no diagnostic required, if name lookup in the predicate finds
    different entities than if the name lookup were performed in the context
    of the base class:</p>

<pre>
static const int N = 1; <em>// #1</em>

struct Base
{
  virtual void f()
    [[pre: N == 1]]
    [[post: sizeof(*this) &lt; 100]];
};

template &lt;int N&gt;       <em>// N is shadowed</em>
struct Deriv : Base
{
  int i[100];

  void f() override
    [[pre: N == 1]]                 <em>// IF-NDR, finds different N</em>
    [[post: sizeof(*this) &lt; 100]];  <em>// IF-NDR, inspects different class</em>
};
</pre>

<p> We do not allow the preconditions in the overriding function to be "wider"
    and the postconditions to be "narrower" than in the overridden function.
    Inheritance also means inheriting the contract. If you need the overridden
    function to be called out of contract of the base class, you have to provide
    a separate function:
    </p>

<pre>
struct Base
{
  virtual int fun(int i)
    [[pre: i &gt;= 0]]
    [[post r: r &gt;= 0]];
};

template &lt;int N&gt;
struct Deriv : Base
{
  int fun_wide(int i)
  {
    return i;
  }

  virtual int fun(int i)
    [[pre: i &gt;= 0]]
    [[post r: r &gt;= 0]]
  {
    return fun(int i);
  }
};
</pre>


<p> The above example also illustrates that a feature request "I want the
    postcondition in the overriding to be the same or narrower than the
    postcondition in the overridden function" is conceptually wrong.
    Function <code>fun_wide()</code> has a wider postcondition than
    <code>fun()</code>, but it is still substitutable for <code>fun()</code>.
    This is because <code>fun_wide()</code> will never return a negative number
    as long as it does not obtain a negative number as input. A postcondition
    can never be treated in isolation from the function's precondition.
    </p>



<h2><a name="rat">7. Design rationale <span class="link">{rat}</span></a></h2>



<h3><a name="rat.att">7.1. Why not use attributes
    <span class="link">{rat.att}</span></a></h3>

<p> An alternative syntax for contract annotations would be to use attributes:</p>

<pre><em>// not proposed</em>
int f(int i)
  [[pre(i &gt;= 0)]]
  [[post(r: r &gt;= 0)]];
</pre>

<p> We do not propose this for two reasons. One is social: we do not want to depart
    from what the previous proposal settled upon and what EWG agreed to. Second is technical.
    This syntax will not work for assertions in function bodies:</p>

<pre>int f(int i)
{
  [[assert(i &gt;= 0)]]; <em>// interpreted as macro</em>
  return i;
}
</pre>

<p> Here, the <code>assert</code> is interpreted as C macro and expanded, causing a compiler error.
    This problem is not present when identifier <code>assert</code> is followed by a colon.</p>

<p> This problem would disappear if we used some other name than <code>assert</code>. However,
    name <code>assert</code> is a well established name, not only in C++, and abandoning it
    would make the learning curve unnecessarily steeper.
    </p>



<h3><a name="rationale.tu_incompat">7.2. Incompatible contract annotation across translation units</a></h3>


<p> Because we do not require contract annotations to be repeated on subsequent function declarations,
    it is possible that two translation units can see different sets of contract annotations for the
    same function:
    </p>

<table><tbody><tr><td>
<pre><em>// translation unit 1</em>
<em>// ------------------</em>

<em>// first declaration in this TU:</em>
void f(int i) [[pre: i &gt; 0]];

void f(int i)
{
  <em>// ...</em>
}</pre>
</td><td>
<pre><em>// translation unit 2</em>
<em>// ------------------</em>

<em>// first declaration in this TU:</em>
void f(int i); <em>// no precondition</em>

int main()
{
  f(0); <em>// precondition checked or not?</em>
}</pre>
</td></tr></tbody></table>

<p> In this context, the question whether pre- and postconditions "belong"
    to the caller or the called function, obtains a new dimension. A similar
    issue occurs for default function arguments. Ideally, from the user perspective,
    we would like the above situation to be an error diagnosable by the implementations.
    However, because this cannot be diagnosed from a single translation unit,
    it may be too burdensome to require of the implementations to diagnose it.
    </p>

<p> This looks similar to ODR violation. The consequences in the run-time behavior
    in <em>Check_and_abort</em> mode are that the wrong set of contract annotations
    gets executed or that both sets are executed, if the implementation decides to
    test the pre-/postconditions both inside and outside the function.
    </p>

<p> However, inconsistent contract annotations have consequences on static analysis.
    What conditions should a static analyzer look for? It may turn out to be
    incompatible with the runtime checks.
    </p>

<p>We can see a couple of ways to address this.</p>

<ol>
    <li>If such incompatible declarations occur in the program, it is ill-formed, no diagnostic required (IF-NDR).</li>
    <li>It is ok to have such incompatible declarations as long as the function is not called. If it is, the behavior is undefined (UB).</li>
    <li>Allow calling such function, but make it unspecified which set
of pre-/postconditions, or both, is called in Abort_and_continue mode.</li>
</ol>

<p> We choose option 2 (undefined behavior). It makes more programs well formed than option 1.
    We do not go with option 3 in order to keep consistency with static analysis:
    if the program is correct (no UB, no IF-NDR) runtime checks are compatible with
    static analysis results.
    </p>

<p> While option 3 opens no new undefined behavior (either UB or IF-NDR),
    it would make the runtime checks behave in an incompatible way with
    static analysis. We have to know what set of contract annotations
    a function has. The answer cannot be "it depends on which file you
    are compiling".
    </p>

<p> For a similar reason we do not go with option 2, even though option 1
    leaves fewer situations undefined. Simply having a function with two
    different sets of contract annotations is an error, even if this error
    cannot be diagnosed by the implementation.
    </p>



<h3><a name="rat.arg">7.3. Why require <code>const</code> for non-reference args?
    <span class="link">{rat.arg}</span></a></h3>


<p> As indicated in section <a href="#des.arg">{des.arg}</a>, a non-reference
    function parameter referenced in a postcondition must be declared
    <code>const</code> in function definition. This is to prevent any
    modification of the parameter.
    </p>

<p> In order to show why this is necessary, consider the following example:</p>

<pre><em>// declaration that the user sees:</em>
int generate(int lo, int hi)
  [[pre lo &lt;= hi]]
  [[post r: lo &lt;= r &amp;&amp; r &lt;= hi]];

<em>// definition that only the author sees:</em>
int generate(int lo, int hi)
{
  int result = lo;
  while (++lo &lt;= hi) <em>// note: lo modified</em>
  {
    if (further())
      ++result;      <em>// incremented slower than lo</em>
  }
  return result;
}
</pre>

<p> Because <code>lo</code> is modified as the function is executed, we get an ambiguous situation where:
    </p>

<ul>
    <li>the returned value is no smaller than the <em>initial</em> value of <code>lo</code>;</li>
    <li>but it might be smaller than the value of <code>lo</code> as observed upon the exit from the function.</li>
</ul>

<p> We could just followed the rule: postcondition is evaluated at the end of
    the function, and whatever values function arguments have at that point,
    we read them. This would make the model for postconditions "simple", but
    it would give the semantic meaning to the postcondition that is clearly
    against the intent of the contract:</p>

<pre>
int generate(int lo, int hi)
  [[pre lo &lt;= hi]]
  [[post r: lo &lt;= r &amp;&amp; r &lt;= hi]];
</pre>

<p> The consumers of the contract only see the declaration. And the declaration
    clearly states:</p>

<ul>
  <li>The objects you passed to my functions will not be modified (because I
      will make copies).</li>
  <li>The generated number will fall between the limits that you passed
      (not between the values that I created during the course of function
      execution).</li>
</ul>

<p> This is how humans will read this declaration; and this is how the tools
    (like static analyzers) will read this declaration. So, in order for both
    tools and the C++ runtime checks to have the same meaning, we have to
    exclude some otherwise valid implementations of the function. The easiest
    way is to require that these parameters be visibly <code>const</code>.

<p> A similar problem, albeit more difficult to spot, is when the function
    argument is implicitly moved from:</p>

<pre><em>// declaration:</em>

string forward(string str)
  [[post r: r == str]];

<em>// definition:</em>

string forward(string str) <em>// disallowed in our proposal</em>
{
  <em>// ...</em>
  return str; <em>// implicit move</em>
}             <em>// postcondition reads the moved-from state</em>
</pre>

<p> If we don't require the argument to be <code>const</code> we end up with the
    postcondition reading the moved-from state. A programmer may not be even aware
    that a move is taking place. Adding <code>const</code> prevents
    the move.</p>

<h3> Why do we require it only for non-reference arguments?</h3>

<p> First, there is no
    way to require it for reference arguments: they cannot be <code>const</code>.
    Second, there is no need to. Reference function arguments clearly indicate
    in the declaration that we are interested in modifying the objects that the
    caller sees. In fact this may be the desire of the caller to have the
    called function modify these objects, and this can even be reflected in the
    postcondition:<p>

<pre>void fix_limits(int&amp; lo, int&amp; hi)
  [[post: lo &lt;= hi]];
</pre>

<p> Is this measure enough? What about pointers? Even if they are const,
    the value they point to can be mutated.</p>

<p> The answer is the same as for the references: you can clearly see from the
    declaration that the function is allowed access to objects from your scope,
    so you are prepared and maybe expect them to change:</p>

<pre>void fix_limits(int* lo, int* hi)
  [[post: *lo &lt;= *hi]];
</pre>

<p> It has to be kept in mind that pointers, including smart pointers, are
    value-semantic types: their value is the address: not the value they point
    to.</p>

<p> The protective measure with adding <code>const</code> does not work for
    types that violate value semantics:</p>

<pre>
class Book
{
  shared_ptr&lt;string&gt; _title = make_shared&lt;string&gt;(); <em>// poor choice</em>

public:
  string const&amp; title() const { return *_title; }
  void set_title(string t) { *_title = std::move(t); }
  friend auto operator &lt;=&gt;(Book const&amp;, Book const&amp;) = default;
};
</pre>

<p> When we copy objects of this type, the copy is tied to the original,
    so when we modify the copy, this automatically modifies the original.
    We believe it is a fair compromise to not take care about types like this.
    </p>

<p> The downside of the solution with adding <code>const</code> is that
    when you add a postcondition to a function declaration, it can cause
    the definition of the function to be come ill-formed. Adding <code>const</code>
    may not suffice, because the implementation might be modifying function
    parameters.</p>

<p> There are some combinations of types and functions for which an alternative
    implementation may not exist if we make function parameters <code>const</code>.
    Consider the following example by Ville Voutilainen:</p>

<pre>struct X { int v = 0; };

void f(propagate_const&lt;shared_ptr&lt;X&gt;&gt; x)
  <em>// [[post: x->v == 42]]</em>
{
  x->v = 42;
}
</pre>

<p> For such cases, programmers will not be able to declare a postcondition.</p>

<p> Other options for solving non-reference arguments in postconditions have
    been considered. C++20 allowed them, but called it undefined behavior if
    such parameter was modified during the evaluation of the function. This
    included the situation where the parameter was implicitly moved from.
    </p>

<p> That solution encouraged too many silent bugs. The present solution looks
    superior. First, potential bugs are detected at compile time. Second,
    we leave more doors open for the future. An illegal declaration can be
    turned into a legal declaration with undefined behavior. The reverse
    is not possible.</p>

<p> Another option would be to, rather than requiring the programmer to manually
    type <code>const</code> on function arguments, make these arguments implicitly
    const. This spares some typing, but has downsides. It is not as future proof
    as the proposed solution: the syntax is well formed with well defined semantics,
    so we cannot change it in the future. Second, this alternative can cause
    confusion. When an argument is changed implicitly to <code>const</code>,
    overload resolution starts selecting different overloads, and the programmer
    cannot easily figure out why, as there is no <code>const</code> in sight.
    </p>

<p> Another option: disallow postconditions to reference function arguments.
    This is possible, but the proposed solution is superior. Referencing
    non-const non-reference parameter is already an error; we just make it easier
    for people who can afford to put <code>const</code> in the definition.
    </p>

<p> Another option: silently make a copy of every non-reference parameter
    referenced in the postcondition. this copy would be only visible to the
    postcondition, so there is no way a function can possibly change it.
    While attractive, this would require making silent copies. This may not be
    satisfactory if a type is expensive to copy, or simply non-copyable,
    and is a bad trade-off in situations where the function does not modify
    the parameter anyway. It is a possible future opt-in extension, described
    in section <a href="#fut.old">{fut.old}</a>.
    </p>

<p> Finally, there is an option to remove postconditions from this
    proposal. This will however make the same problem reappear
    once we try to add postconditions in the future.
    </p>

<h3><a name="rat.con">7.4. Why disallow continuation (for now)
    <span class="link">{rat.con}</span></a></h3>


<p> The behavior of runtime-checking, logging but not aborting has a number of surprising and non-obvious effects.</p>

<p>First, in case the precondition is guarding against the Abstract Machine Violation (hard UB),
   reaching the point of the abstract machine violation might result in what would be observed
   as removing the log entry for the previous contract violation. This is discussed in detail in <a href="#apa">appendix A</a>.</p>

<p> Second, a mechanical transformation of every contract annotation to "check, log and continue"
    can introduce a new Abstract Machine Violation (hard UB)
   if the programmer assumes the short-circuiting behavior for subsequent contract
    annotations. Consider the following example. </p>

<pre>int f(int * p)
  [[pre: p]] [[pre: *p &gt; 0]]
{
  if (!p)      throw Bug{};  <em>// safety double-check </em>
  if (*p &lt;= 0) throw Bug{};  <em>// safety double-check </em>

  return *p - 1;             <em>// (*) business logic</em>
}</pre>

<p> This program upon <code>p == nullptr</code> behaves in a way that (1) does not cause abstract machine violation and
    (2) guarantees that the business logic, indicated with *, is never reached. This happens for both <em>Ignore</em>
    and <em>Check_and_abort</em> mode. However, in a mode that allows the program to continue, this causes abstract machine violation
    upon runtime-checking the second precondition. This is explained in detail in <a href="#apa">appendix A</a>.</p>

<p> We believe that "the continuation mode" is a useful feature that is necessary for some essential applications
    (like adding contracts in libraries in stages). Our motivation for omitting it from the MVP is the timing
    concerns: we want to deliver a small but relatively useful feature quickly.</p>


<h3><a name="rat.exc">7.5. Why disallow throwing on contract violation  (for now)
    <span class="link">{rat.exc}</span></a></h3>

<p> We propose to disallow throwing upon detected contract violation because it falls
    outside of one of the presented programming models: the one that says that it is unacceptable to allow
    the program with a detected bug to continue.</p>

<p> By disallowing throwing we also avoid exploring and describing many aspects observable behavior that this would
    trigger:</p>

<ol>
  <li>How contracts interact with <code>noexcept</code>.</li>
  <li>If the precondition is evaluated before the function call or inside the function.</li>
</ol>

<p> This makes the proposal smaller, and therefore more likely to progress faster through the WG21 process.</p>


<h3><a name="rat.hnd">7.6. Why no user-provided violation handler (for now)</a>
    <span class="link">{rat.hnd}</span></h3>

<p> Not proposing the ability to install user-provided violation handlers is again motivated by timing constraints.
    This way we avoid the necessity to specify the interface for the violation handler and its constraints.</p>

<p> However, the way we specify the handler (mostly implementation defined) allows for things like programmer installing
    a callback in an implementation-defined way.</p>



<h3><a name="rat.eff">7.7. Why allow side effects in predicates
    <span class="link">{rat.eff}</span></a></h3>


<p> We intuitively expect that predicates in contract annotations
    have no side effects. This expectation is reflected in terms
    like "if the precondition <em>holds</em>". However, it is
    impossible to enforce such constraint in an imperative
    language like C++.
    </p>

<p> It is often impossible for programmers to even know if the
    function they use has any side effects. For instance,
    the specification of <code>std::vector&lt;T&gt;::size() const</code>
    does not prevent the implementations from
    performing side effects, such as logging.
    </p>

<p> Some side effects are practical to have, and they do not
    affect the reasoning about predicates in the mathematical sense.
    These side effects include:</p>

<ol>
  <li>Logging, which never affects subsequent computations.</li>
  <li>Modifying private mutable data members for the purpose of caching function results.</li>
  <li>Using mathematical functions from <code>&lt;cmath&gt;</code>, which store error results in global (thread-local)
      variable <code>errno</code>.</li>
  <li>Performing scoped locking inside the function, which may affect the execution of other threads.</li>
  <li>Causing a contract violation handler when runtime-checking the precondition of the function called in the predicate.</li>
</ol>

<p> Our choice follows the existing practice with <code>assert()</code>: it allows side effects, but a lot of advice
    comes with it, saying that side effects in the predicate cannot be relied upon.</p>

<p> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0542r5.html">[P0542R5]</a> specified that invoking
    any side effect inside a contract annotation predicate is undefined behavior. This allowed certain practical optimizations,
    such as not performing two consecutive evaluations of the same predicate, which is often the case when postcondition of
    one function is the same as the precondition of another function. It also allowed checking the same predicate twice,
    for instance once inside the function body, and the second time in the calling context.</p>

<p> While we drop this undefined behavior on any
    side effects in a contract predicate, we allow
    similar code transformations, and introduce narrower
    cases that trigger undefined behavior: in situations where
    the programmer is clearly doing something nasty.</p>

<p> Why not just follow <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0542r5.html">[P0542R5]</a>
    and say that any side effect inside a predicate is undefined behavior?
    Because we do not want programs with "benign" side effects
    to be penalized, and render additional surprises.
    Only "malignant" side effects should trigger undefined behavior.
    We have a pretty good definition of "benign" side effect in a predicate:
    it does not modify any object that it odr-uses and it does not affect
    the result of any other subsequent predicate in the same correctness test
    sequence.
    </p>

<p> Why not just use simpler wording and say that a predicate listed in
    a contract annotation can be evaluated an unspecified number of times
    (including 0 times)? While this would send a clear signal to the users,
    that the side effects cannot be relied upon, it would not allow the
    predicate transformations that we described earlier.
    </p>



<h3><a name="rat.eli">7.8. Why include side effect elision in the MVP
    <span class="link">{rat.eli}</span></a></h3>


<p> First, it cannot be added later, because then it would be a breaking change. User may start to rely
    on the mandated side effects in <em>Check_and_abort</em> mode, as per the Hyrum's Law, and these would
    suddenly disappear in future releases.</p>

<p> Second, it gives a strong encouragement to the users not to put side effects in their predicates.
    Their side effects may disappear, even in <em>Check_and_abort</em> mode; or they can be duplicated.</p>



<h3><a name="rationale.access">7.9. Why allow access to private and protected members</a></h3>

<p> Programming guidelines often recommend that in contract predicates of public member
    functions one should only use the public interface of the class. This is in case the
    class user needs to manually check if the contract is satisfied for an object whose
    state is not known. However, this is only a guideline, and enforcing it in the language
    would break other use cases that do not subscribe to the above advice.
    </p>

<p> In general, the users must <em>ensure</em> that the precondition of the called function is satisfied.
    If they do that, they do not have to check the precondition.
    </p>

<p> Allowing the access to protected and private members enables a practical usage scheme.
    In general, function precondition is something that cannot be fully expressed as C++ expression.
    Implementer choose how much of the function precondition they want to check. They may choose
    to check some parts of the precondition by accessing private members that they do not want
    to expose to the users, for instance, because the private implementation may change over time
    or under configuration:
    </p>

<pre>class callback
{
#if !defined NDEBUG
  mutable int _call_count = 0;
#endif

  <em>// ...</em>

public:
  void operator() const
    <em>// real contract: this function can be called no more than 8 times,</em>
    <em>// so the precondition is that the function has been called 7 or less times</em>

#if !defined NDEBUG
    <em>// attempt to check the precondition</em>
    [[pre: _call_count &lt;= 7]];
#endif
};</pre>

<p> In the above example, the precondition can only be checked in debugging mode.
    Once <code>NDEBUG</code> is defined, member <code>_call_count</code> is removed
    and there is no way to test the precondition.
    </p>

<p> Also, a hypothetical constraint to use only public members in contract predicates
    could result in programmers turning their private and protected members into public
    members only to be able to express the pre- and postconditions, which does not
    sound like a good class design.

</p><p> This has been described in detail in
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1289r1.pdf">[P1289R1]</a>,
    and in fact adopted by EWG. </p>



<h3><a name="rationale.no_default">7.10. Why not mandate a default translation mode</a></h3>


<p> We recommend that the default mode is <em>Check_and_abort</em>, but we do not require this of the
    implementations. The reason for that is that we believe that it is not possible to mandate this
    behavior in this International Standard.</p>

<p> Our ideal is that users get safety by default and performance on request.
    ("Safety" in this context is understood as "do not let the program with a bug execute".)
    But what the users often use is an IDE. Even if we were able to require of the compiler
    that its default mode is <em>Check_and_abort</em>, the IDE can provide its own defaults
    which map on non-default values of compiler switches.
    </p>

<p> This has been discussed in detail in
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1769r0.html">[P1769R0]</a>.
   </p>



<h3><a name="rationale.no_const">7.11. No gratuitous <code>const</code> qualification</a></h3>


<p> Ideally, we would like contract predicates to be referentially transparent
    (have no side effects, depend on nothing else but the objects directly
    referenced in the expression). This goal is not realistically attainable.
    We could get closer, however, if we required that all objects referenced
    in the predicate are treated as if they were <code>const</code>. Thus,
    only operators and functions (including member functions) that take
    arguments by value or a reference to <code>const</code> are allowed.
    </p>

<p> This could cause some discrepancies in case we have two overloads:
    one for type <code>T const&amp;</code> and the other for <code>T&amp;</code>
    doing different things:
    </p>

<pre>struct X
{
  bool is_fine() const { return <em>/* impl 1 */</em>; }
  bool is_fine()       { return <em>/* impl 2 */</em>; }

  friend void fun(X&amp; x)
    [[pre: x.is_fine()]]    <em>// uses impl 1</em>
  {
    [[asset: x.is_fine()]]; <em>// uses impl 2</em>
  }
};</pre>

<p> Also, there exist referentially transparent functions that do not
    mark their reference arguments as <code>const</code>. While programmers are
    often advised to mark any functions that do not modify their
    arguments by contract as <code>const</code>, this is just and device, and does
    not have to be followed. And it is not clear if such functions
    should be excluded from contract predicates.
    </p>

<p> Because of these issues, and unclear gains, we do not propose
    to treat objects as <code>const</code> inside contract annotations.
    </p>



<h3><a name="rationale.constexpr">7.12. Interaction with <code>constexpr</code> functions</a></h3>


<p> During core constant expression evaluation in <em>Check_and_abort</em>
    mode when any function precondition, postcondition or
    assertion is violated, the program is ill-formed.
    </p>

<p> Ideally, we would like such evaluation to be ill-formed
    even in <em>Ignore</em> mode. However, we are not sure if this is easily
    implementable on all platforms. This proposal allows but not requires this.
    </p>



<h3><a name="rat.sec">7.13. Unimplementable security restrictions
    <span class="link">{rat.sec}</span></a></h3>


<p> C++20 had wording "There should be no programmatic way of setting, modifying,
    or querying the build level of a translation unit." Technically,
    we could add a similar requirement for the translation mode.</p>

<p> We decided to drop this requirement, as there is no way to actually test if it is
    satisfied, and it is unrealistic to expect that of the implementations. For instance,
    A program can open a configuration file of the project that lists the translation mode.
    Should programs be banned from opening and reading such file?</p>



<h3><a name="rationale.security">7.14. No placeholder syntax for "meta-annotations" on contract annotations</a></h3>


<p> It is clear that at some point there will have to be a way to annotate contract annotations with additional information
    controlling how contract annotations should be interpreted, such as:</p>

<ol>
    <li>That a precondition is a new one, and if it is runtime-checked and fails, it should not trigger a call to <code>std::abort()</code>.</li>
    <li>That a precondition is expensive to evaluate, relative to the cost of function body.</li>
    <li>That the expression in the precondition cannot be odr-used, and therefore evaluated.</li>
</ol>

<p> We could provide the placeholder syntax for these annotations still in the MVP,
    so that C++ compilers can start parsing it as soon as possible, before we standardize individual "meta-annotations".
    This way, programs written in C++30 would compile in C++23 compilers (assuming this paper is accepted for C++23).</p>

<p> The serious concern about this idea is that while these meta-annotations will be parsed in C++23, they will have different
    semantics than in the future revisions of C++. This silent change of semantics is unacceptable. For this reason, we do not
    propose the placeholder syntax for meta-annotations.</p>

<p>We would end up in the situation, where the same program compiles on both older and newer contract support
    frameworks, but has different semantics. Consider the
    following program, with possible future extensions:
    </p>

<pre>
void f(const char* s)
  [[pre{axiom}: is_null_terminated(s)]]; <em>// name must not odr-used</em>

bool binary_search(container&lt;Val&gt;&amp; c, Val const&amp; v)
  [[pre{audit}: is_sorted(c)]];          <em>// must not be evaluated</em>

bool foo(int i)
  [[pre{review}: i &gt;= 0]];               <em>// must not abort</em>

bool bar(int i)
  [[pre{default}: i &gt;= 0]];              <em>// must evaluate and abort</em>
</pre>

<p> No single semantic that doesn't understand the additional syntax
    can accommodate these expectations.</p>


<h3><a name="rationale.interleaving">7.15. Interleaving preconditions and postconditions</a></h3>


<p>This proposal allows to declare preconditions and postconditions in arbitrary order:</p>

<pre>int f(int x, int y)
  [[post r: p(r)]]
  [[pre: p(x)]]
  [[post r: q(r)]]
  [[pre: p(y)]];
</pre>

<p> We could be stricter about is and require that no precondition annotation can follow any precondition annotation. However:</p>

<ul>
<li>There is no ambiguity when these annotations are declared in arbitrary order.</li>
<li>This looks more like a question of good style, which can be enforced by other tools or coding practices.</li>
<li>It can sometimes add clarity when pairs precondition-postcondition are grouped together:

<pre>int f(int x)
  [[pre: neat(x)]]
  [[post r: neat(r)]]

  [[pre: nice(x)]]
  [[post r: nice(r)]];
</pre>

</li>
</ul>



<h3><a name="rationale.abort_or_term">7.16. <code>abort()</code> vs <code>terminate()</code></a></h3>

<p> In this proposal, throwing from the predicate calls <code>std::terminate()</code> while a failed runtime check
    calls <code>std::abort()</code>. (We simply forbid the implementations
    to end the violation handler by throwing an exception: it is up to implementations how this requirement is satisfied.)
    </p>

<p> The above distinction reflects the fundamental difference between the two situations.
    Throwing from the predicate is a random, unpredictable, but correct situation in the program. Maybe a comparison
    had to allocate memory, and this allocation failed, because today the server is exceptionally busy. We want to
    handle it the way we usually handle exceptions when there is no suitable handler: <code>std::terminate()</code>
    is an exception handler, with its unique control flow, however harsh.</p>

<p> In contrast, failing a runtime correctness test is an indication of a bug, and it is not clear if <code>std::terminate()</code>,
    which is the second level of exception handling mechanism, is a suitable tool.</p>




<h3><a name="rationale.assert_statement">7.17. <code>[[assert:]]</code> is not an expression</a></h3>


<p> In this proposal <code>[[assert:]]</code> can only appertain to a null statement, which effectively makes it a statement,
    and it cannot be used as an expression. This is a downside compared to macro <code>assert()</code>, which can be used
    as a subexpression of a bigger expression and therefore be used to protect things like initialization of variables:
    </p>

<pre>MyClass::MyClass(int i)
  : member((assert(i &gt; 0), i))
{}
</pre>

<p> In the future <code>[[assert:]]</code> could be extended and become an expression.
    However, this is not in scope of the Minimum Viable Product.</p>



<h3><a name="rat.cbo">7.18 Contract-based optimizations
    <span class="link">{rat.cbo}</span></a></h3>


<p> This proposal does not allow code transformations based on assumption that
    predicates in correctness annotations always evaluate to <code>true</code>.
    Such transformations could change the program (even parts far before the
    contract annotation) in a surprising way.</p>

<p> We believe that removing this provision increases the level of consensus.</p>

<p> On the other hand, we believe that the Standard does not have to explicitly
    allow such transformations. First, they can never be guaranteed or required:
    a compiler vendor must choose to make an effort and implement them. If a
    compiler vendor implements such transformations, it can offer the feature
    as a non-conforming extension, such as <code>__builtin_unreachable()</code>.
    </p>

<p> In fact, this proposal indirectly allows the programmer to achieve the same
    effect, provided that the compiler vendor provides the necessary parts.
    This proposal says that what happens in response to contract violation is
    implementation defined. A conforming implementation may allow the programmer
    to install a callback to be called on such occasion (a contract violation
    handler). The programmer may then choose to put <code>__builtin_unreachable()</code>
    inside the handler. The implementation then would have to guarantee that
    the handler is inlined.</p>

<p> This should not be alarming to people focused on safety, because the above
    scenario requires the usage of <code>__builtin_unreachable()</code>, which
    is easily detectable through simple mechanical checks, and cannot be installed at runtime.
    </p>


<h2><a name="fut">8. Future compatibility
    <span class="link">{fut}</span></a></h2>


<p> While we propose to drop a number of features from the MVP, this proposal does not close the door for
    adding them in the future, once (if) the MVP has been agreed upon and baked. </p>


<p> To guarantee backward compatibility as we add features in the future,
    all semantics added in the MVP must not change. Therefore all new features will have to be opt-ins:
    enabled either through new syntax/annotations, or through new translation modes.</p>

<p> The ability to install a custom violation handler (along with the handler's interface) can be provided
    as a future extension, with the behavior mandated by the MVP being the semantics of the default
    violation handler.</p>

<p> The ability to continue after logging the contract violation has two use cases: </p>

<ol>
  <li>Apply the "continue" semantics for all contract annotations when running the variant of a program with contract
      checking enabled for the first time.</li>
  <li>Applying the "continue" semantics selectively only for the newly added contract annotations.</li>
</ol>

<p> In the first case, the application of the "continue" semantics is not a default behavior, and would require that
    a person who assembles the program instructs the compiler to use the special behavior. This can be added in the future
    as a third mode of translating the source code with contract annotations (in addition to <em>Ignore</em> and <em>Check_and_abort</em>).
    </p>

<p> In the second case, there is a need to discriminate the newly added
    contract annotations from the stable ones. This would require
    some additional syntax to mark such annotations, for instance:</p>

<pre>int f(int * p)
  [[pre: p]]            <em>// stable annotation </em>
  [[pre: *p &gt; 0; <strong>new</strong>]]  <em>// new annotation </em>
;</pre>

<p> This can be added in the future by introducing a new syntax for the
    newly added annotations and allowing the programmer to control
    separately what runtime code should be generated from these "new"
    annotations.</p>

<p> The syntax space for additional information in contract annotations is
    quite broad. The alternatives include:</p>

<pre>  [[post r: r &gt; 0: new]]
  [[post{new} r: r &gt; 0]]
  </pre>

<p> Regarding the throwing violation handlers, the only known and
    well explored use case is for "negative" unit-testing.
    We note that this ability would only be used in special programs:
    ones that execute unit tests. It would also require of the tested
    functions not to be marked as <code>noexcept</code>. For this
    special case it seems reasonable to expect of the person that assembles the
    program that they instruct the compiler in an explicit way
    that a unit-test program is built. This ability could be added as a
    future extension by introducing a yet another translation
    mode where exceptions thrown from violation handlers are not
    immediately turned into a call to <code>std::terminate()</code>
    (but they can still be turned into <code>std::terminate()</code> when <code>noexcept</code> functions are executed in unit-test programs).
    </p>

<p>It is also possible to do negative testing of preconditions and postconditions by offering a set of reflection features tailored to that eventuality, without even running the function. A strawman proposal could be <code>std::are_preconditions_satisfied(f, x, y, z) -> bool</code>.</p>

<p> This might look like a lot of modes of translation, but it should be kept in mind that the perspective of a person that looks
    at the code will not have modes: a declaration starting with <code>[[pre:</code> is always a precondition: something that
    evaluates to <code>true</code> in correct programs. The modes will be visible only to the person assembling the program,
    and in this case, having a lot of fine grained control is desired.</p>

<p> The point of this section is to illustrate that dropping features
    like violation handlers, continuation after a failed runtime check or
    throwing violation handlers from the MVP does not build any technical
    barriers that would prevent the addition of these features in the future
    revisions of the contract support framework. We also expect that
    once the syntax for declaring contract annotations has been
    standardized, compiler vendors will offer non-standard extensions
    that will allow the users to experiment with additional features
    and become a basis for the future standardization.
    </p>



<h3><a name="fut.old">8.1. Capturing state on function entry
    <span class="link">{fut.old}</span></a></h3>



<p> It is sometimes desirable to express in the postcondition how the state
    of the program upon return from the function is different from the state
    that the program had when the function was entered. One notable example
    of this is when we want to check that after a successful
    <code>push_back</code>, the size of the sequence container upon return is
    greater by one than the size of the container upon function entry.
    However, by the time the precondition is evaluated, the previous state of
    the container is no more. We would have to make a <em>copy</em> of the
    portions of the program state that would be later inspected in the
    postcondition.</p>

<p> There could be at least two ways to express this. One is to introduce even more
    names in the postcondition declaration, and use a syntax similar to the
    one used in lambda-captures:</p>

<pre>int f(int&amp; i, array&lt;int, 8&gt;&amp; arr)
  [[post r, old_i = i: r &gt;= old_i]]        <em>// value of i upon entry</em>
  [[post r, old_7 = arr[7]: r &gt;= old_7]];  <em>// value of arr[7] upon entry</em>
</pre>

<p> The other option is to use a new keyword (or token) for this purpose,
    like <code>oldof</code> proposed in
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1962.html">[N1962]</a>:

</p><pre>int f(int&amp; i, array&lt;int, 8&gt;&amp; arr)
  [[post r: r &gt;= oldof(i)]]        <em>// value of i upon entry</em>
  [[post r: r &gt;= oldof(arr[7])]];  <em>// value of arr[7] upon entry</em>
</pre>

<p> This future addition would also address the case where a postcondition
    refers to the non-reference function parameter (see section
    <a href="#rat.arg">{rat.arg}</a>), but the function cannot
    afford to add <code>const</code>:</p>

<pre>
template&lt;class ForwardIt, class T&gt;
ForwardIt find(ForwardIt first, ForwardIt last, const T&amp; value)
  [[post r: distance(oldof(first), r) &gt;= 0u]]  <em>// `first` not referenced</em>
  [[post r: distance(r, last) &gt;= 0u]]
{
  for (; first != last; ++first) {
    if (*first == value) {
      return first;
    }
  }
  return last;
}
</pre>

<p> This proposal is open for either of these syntax variants (in the future).
    </p>


<h2><a name="ope">9. Open issues
    <span class="link">{ope}</span></a></h2>

<h3><a name="ope.syn">9.1. Syntax for introducing names in postconditions
    <span class="link">{ope.syn}</span></a></h3>

<p> It has been suggested that postconditions could have a better syntax for
    introducing the name of the returned value.
    Any such exploration of syntactic space should take into account that
    postconditions might need to introduce more names, as described in section
    <a href="#fut.old">{fut.old}</a>.
    </p>

<pre>int f(int&amp; i, array&lt;int, 8&gt;&amp; arr)
  [[post r, old_i = i: r &gt;= old_i]]        <em>// value of i upon entry</em>
  [[post r, old_7 = arr[7]: r &gt;= old_7]];  <em>// value of arr[7] upon entry</em>
</pre>

<p> An alternate syntax for postconditions that does not preclude the
    option above in the future would be to use parentheses:</p>

<pre>int f(int&amp; i, array&lt;int, 8&gt;&amp; arr)
  [[post(r): r &gt;= 0]]                       <em>// for the MVP</em>
  [[post(r, old_i = i): r &gt;= old_i]]        <em>// future</em>
  [[post(r, old_7 = arr[7]): r &gt;= old_7]];  <em>// future</em>
</pre>





<h2><a name="wor">7. Wording <span class="link">{wor}</span></a></h2>





<p>Wording changes are against N4892.</p>

<div class="editor">

<p>The text in bluish font indicates comments that are intended to easily map the wording onto the
   overview part of the proposal, and to give a rationale for the wording choices. We use the following terms:
   </p>

<ul>
  <li><em>contract annotation</em> — either a precondition or a postcondition. </li>
  <li><em>correctness annotation</em> — either an assertion or a contract annotation. </li>
  <li><em>correctness test</em> — is an "event" corresponding to a correctness annotation &mdash;
      it may be a no-op in <em>Ignore</em> mode or produce instructions in <em>Check_and_abort</em> &mdash;
      which can be sequenced before or after other instructions.</li>
</ul>

</div>

<p>In 6.3/13 [basic.def.odr], add a new bullet after bullet 13.13:</p>

<blockquote class="stdins">
<p>if <code>D</code> invokes a function with a contract annotation,
  or is a function that contains an assertion or has a contract annotation (9.12.4.2),
 it is implementation-defined under which conditions all definitions of
 <code>D</code> shall be
 translated using the same translation mode (9.12.4.3); and</p>
</blockquote>

<p class="editor">The above permits the implementations to allow the co-existence of two
   definitions of the same function compiled in two different translation modes.
  The above takes into account that postconditions, much like preconditions,
   can also be evaluated outside of their function.</p>


<p>Modify the beginning of 6.9.1/11 [intro.execution] as follows:</p>

<blockquote class="std">
<p>When invoking a function (whether or not the function is inline),
every argument expression and the postfix expression designating the called
 function are sequenced before
<ins>the function's precondition test sequence (9.12.4.3); the function's precondition test sequence
is sequenced before</ins> every expression or statement in the body of the called function.</p>
</blockquote>



<p>In 11.4.1/7 [class.mem.general], add a new bullet after bullet 7.4:</p>

<blockquote class="stdins">
<p>— contract annotation (9.12.4.2), or</p>
</blockquote>


<p>In 7.6.1.3 [expr.call], add a new paragraph after paragraph 7:</p>

<blockquote class="stdins">
<p>The function's precondition test sequence (9.12.4.3) is sequenced after the initialization
of function parameters. The function's postcondition test sequence (9.12.4.3) is sequenced
before the destruction of function parameters.</p>
</blockquote>

<p>In 7.7/5 [expr.const], add a new bullet after bullet 5.12:</p>

<blockquote class="stdins">
<p>— an unsuccessful correctness test (9.12.4.3), or</p>
</blockquote>


<p>In 9.12.1/1 [dcl.attr.grammar], modify the production for <em>attribute-specifier</em> as follows:</p>

<blockquote class="std">
  <blockquote class="grammar">
    <p>…<br>
    <i>attribute-specifier</i>:<p>
    <ul class="grammar">
      <li><tt>[ [ </tt><i>attribute-using-prefix<sub>opt</sub>&nbsp;&nbsp;attribute-list</i><tt> ] ]</tt></li>
      <li><ins><i>correctness-specifier</i></ins></li>
      <li><i>alignment-specifier</i></li>
    </ul>
    <p>…</p>
  </blockquote>
</blockquote>

<p class="editor"> Contract annotations are not regular attributes, but we still define them in [dcl.attr]
    because (1) they share some characteristics of attributes, and (2) we follow the precedent of
    <code>alignas</code>.</p>



<p>Add a new section 9.12.4 Correctness specifiers [dcl.correct] ([dcl.attr.deprecated] becomes 9.12.5).</p>

<p>Add a new section 9.12.4.1 Syntax [dcl.correct.syn]:</p>

<blockquote class="stdins">

<p> 1.

  Correctness specifiers are used to specify preconditions, postconditions, and assertions for functions. </p>

  <blockquote class="grammar">
  <p><i>correctness-specifier</i>:</p>
  <ul class="grammar">
    <li><tt>[ [ pre :</tt>&nbsp;<i>conditional-expression</i><tt> ] ]</tt></li>
    <li><tt>[ [ post </tt><i>identifier<sub>opt</sub> </i><tt>:</tt>&nbsp;<i>conditional-expression</i><tt> ] ]</tt></li>
    <li><tt>[ [ assert :</tt>&nbsp;<i>conditional-expression</i><tt> ] ]</tt></li>
  </ul>
  </blockquote>

<p> 2.

  A <i>correctness-specifier</i> using <tt>pre</tt> is a <i>precondition</i>.

  The specifier may be applied to the function type of a function declaration.

  [<i>Note</i>: A precondition expresses a predicate, which can be evaluated
  upon entry into the function. If evaluated and the result is <code>false</code>,
  this indicates that the program contains a bug. — <i>end note</i>].
  </p>

</blockquote>

<p class="editor">Term "bug" seems fine inside a non-normative note. This formulation in the note
 looks more unambiguous than an alternative that would say "function's expectation".</p>

<blockquote class="stdins">

<p> 3.

  A <i>correctness-specifier</i> using <tt>post</tt> is a <i>postcondition</i>.

  The specifier may be applied to the function type of a function declaration.

  [<i>Note</i>: A postcondition expresses a predicate which can be evaluated
  when the function returns to its caller. If evaluated
  and the result is <code>false</code>, this indicates that the program contains a bug. — <i>end note</i>]

  A postcondition may introduce an identifier to represent the glvalue result or the prvalue result object of
  the function. When the declared return type of a non-templated function contains a placeholder type, the
  optional <em>identifier</em> shall be present only in a definition.

[<i>Example</i>:</p>

<pre>int f(int&amp; p)
  [[post: p &gt;= 0]]     <em>// OK</em>
  [[post r: r &gt;= 0]];  <em>// OK</em>

auto g(auto&amp; p)
  [[post: p &gt;= 0]]     <em>// OK</em>
  [[post r: r &gt;= 0]];  <em>// OK</em>

auto h(int&amp; p)
  [[post: p &gt;= 0]]     <em>// OK</em>
  [[post r: r &gt;= 0]];  <em>// error: cannot name the return value</em>

auto h(int&amp; p)
  [[post: p &gt;= 0]]     <em>// OK</em>
  [[post r: r &gt;= 0]]   <em>// OK</em>
{
  return p = 0;
}
</pre>
<p> — <i>end example</i>]</p>
<p></p>


<p> 4.
  A <i>correctness-specifier</i> using <tt>assert</tt> is an <i>assertion</i>.

  The specifier may be applied to a null statement (8.3).

  An assertion correctness test (9.12.4.3) is performed as part of the
  evaluation of the null statement the assertion applies to.

  [<i>Note</i>: An assertion expresses a predicate.
  If evaluated and the result is <code>false</code>,
  this indicates that the program contains a bug. — <i>end note</i>]
</p>

<p>5. Preconditions, postconditions, and assertions are collectively called <em>correctness annotations</em>.
The <em>conditional-expression</em> in a correctness annotation is contextually converted to <code>bool</code> (7.3);
the converted expression is called the <em>predicate</em> of the correctness annotation.

[<i>Note</i>: The predicate of a correctness annotation is potentially evaluated (6.3). — <i>end note</i>]
</p>

</blockquote>



<p>Add a new section 9.12.4.2 Contract annotations [dcl.correct.anno]:</p>


<blockquote class="stdins">

<p> 1.
  A <i>contract annotation</i> is a precondition or a postcondition.

  A contract annotation may be applied to the function type of a function declaration.

  The first declaration of a function <em>D</em> shall specify all contract annotations (if any) of the function.
  Other declarations of the function reachable (10.7) from <em>D</em> shall either specify no contract annotations
  or the same list of contract annotations;
  no diagnostic is required if corresponding conditions will always evaluate to the same value.

  If declarations of function <em>F</em> appear in two translation units, the first declarations of <em>F</em>
  in either translation unit their lists of contract annotations shall be the same; no diagnostic required;
  also no diagnostic is required if corresponding conditions will always evaluate to the same value.

  If a friend declaration <em>D</em> is the first declaration of the function in a translation unit
  and has a contract annotation, that declaration shall be a definition
  and there shall be no other
  declaration of the function or function template which is reachable from <em>D</em>
   or from which <em>D</em> is reachable.

  </p>


</blockquote>

<p class="editor">The above means that if a friend function declaration introduces a new function and has contract annotations,
  it has to be a "hidden friend". This requirement was copied from [P0542R5].</p>

<blockquote class="stdins">

<p> 2.

  Two lists of contract annotations are the same if they consist of the same contract annotations in the same order.

  Two contract annotations are the same if their predicates are the same.

  Two predicates contained in <i>correctness-specifier</i>s are the same if they would satisfy the one-definition rule
  (6.3 <tt><b>[basic.def.odr]</b></tt>) were they to appear in function definitions, except for renaming of parameters,
  return value identifiers (if any), and renaming of template parameters.
  </p>

<p> 3.

[<i>Note</i>: A function pointer cannot include contract conditions. [<i>Example</i>:

</p><pre>typedef int (*pfa)() [[post r: r != 0]]; <em>// error: contract annotation not on a function declaration</em>

int g(int x)
  [[pre: x != 0]]
  [[post r: r != 0]];

int (*pf)(int) = g; <em>// OK</em>
int x = pf(5);      <em>// contract annotations of g are tested</em>
</pre>
<p>— <i>end example</i>] — <i>end note</i>]</p>

<p></p>

<p> 4.

The predicate of a contract condition has the same semantic restrictions as if it appeared in the
<em>noexcept-specification</em> of the function it applies to, except that the return type of the function is
known in a contract condition appertaining to its definition, even if the return type contains a placeholder
type.

[<i>Example</i>:

</p><pre>class X {
private:
  int m;
public:
  void f() [[pre: m &gt; 0]];             <em>// OK</em>
  friend void g(X x) [[pre: x.m &gt; 0]]; <em>// OK</em>
};

void h(X x) [[pre: x.m &gt; 0]];          <em>// error: m is a private member</em>
</pre>
<p>— <i>end example</i>]</p>

<p></p>


<p> 5.
A precondition test (9.12.4.3) is performed immediately before starting evaluation of the function
body. [<i>Note</i>: The function body includes the <em>function-try-block</em> (Clause 14) and the <em>ctor-initializer</em> (11.9.3).
— <i>end note</i>] A postcondition test is performed immediately before returning control to
the caller of the function. [<i>Note</i>: The lifetime of local variables and temporaries has ended. Exiting via an
exception or via <code>longjmp</code> (17.13.3) is not considered returning control to the caller of the function. — <i>end
note</i>]
</p>


<p> 6.

The <em>basic precondition test sequence</em> of a given function <code>f</code> is the sequence of
precondition tests corresponding to the list of preconditions of <code>f</code>.

For two precondition annotations <em>P1</em> and <em>P2</em> applied to a function,
if <em>P1</em> appears lexically before <em>P2</em> then the precondition test corresponding to
<em>P1</em> is sequenced before the precondition test corresponding to <em>P2</em>.

If a function has multiple postconditions,
their tests (if any) will be performed in the order they appear lexically.

The <em>basic postcondition test sequence</em> of a given function is the sequence of
postcondition tests corresponding to the list of postconditions of the function.

For two postcondition annotations <em>P1</em> and <em>P2</em> applied to a function,
if <em>P1</em> appears lexically before <em>P2</em> then the postcondition test corresponding to
<em>P1</em> is sequenced before the postcondition test corresponding to <em>P2</em>.

[<i>Note</i>: A basic precondition test sequence can be empty if the function has
 not preconditions. — <i>end note</i>]

[<i>Example</i>:
</p><pre>void f(int* p, int*&amp; q)
  [[post: q != nullptr]] <em>// #4</em>
  [[pre:  p != nullptr]] <em>// #1</em>
  [[post: *q &gt;= 0]]      <em>// #5</em>
  [[pre:  *p &gt;= 0]]      <em>// #2</em>
{
  q = p;                 <em>// #3</em>
}
</pre>

<p>The numbers indicate the order in which expressions in preconditions,
postconditions and function body are evaluated. The basic precondition test sequence
consists of two precondition tests corresponding to #1 and #2.
The basic postcondition test sequence consists of two postconditions corresponding to
#4 and #5.
— <i>end example</i>]
</p>

<p> 7.

If a predicate in the postcondition odr-uses (6.3) a non-reference parameter,
this parameter shall be defined <code>const</code> inside the function definition.

[<i>Example</i>:</p>

<pre>int f(int i)
  [[post r: r == i]];

int g(int i)
  [[post r: r == i]];

int f(const int i)  <em>// OK</em>
{
  return i;
}

int g(int i)        <em>// error: i is not declared const</em>
{
  return i;
}</pre>
<p>— <i>end example</i>]</p>

<p> 8.

The postcondition test sequence (9.12.4.3) is
sequenced after the initialization of the returned value, and
after the destruction of objects with automatic
storage duration declared in the function body.

The postcondition test sequence is sequenced before
the destruction of function arguments.

[<i>Note</i>: Therefore, a postcondition can inspect the state of
the return value and function arguments. — <i>end note</i>]

</p>

</blockquote>




<p>Add a new section 9.12.4.3 Testing contract annotations [dcl.correct.test]:</p>


<blockquote class="stdins">

<p> 1.

A translation may be performed in one of the following <em>translation modes</em>: <em>ignore</em>, or <em>enforce</em>.

The mechanism for selecting the translation mode is implementation-defined.

The translation of a program consisting of translation units where the translation mode is not the same
in all translation units is conditionally-supported with implementation-defined semantics.

</p>

<p> 2.

<i>Recommended practice</i>: If no translation mode is explicitly selected, <em>enforce</em> should be the default translation mode.

</p>

</blockquote>

<p class="editor">C++20 had wording "There should be no programmatic way of
    setting, modifying, or querying the build level of a translation unit."
     We omit is as explained in section <a href="#rat.sec">{rat.sec}</a>.
  </p>

<blockquote class="stdins">

<p> 3.

An <em>ignored correctness annotation test</em> performs no operation.

[<i>Note</i>: The predicate is potentially-evaluated (6.3). —<i>end note</i>]

</p>

<p> 4.

An <em>enforced correctness annotation test</em> is performed as follows.
The predicate is evaluated. If the evaluation exits via an exception, <code>std::terminate()</code> is called.
If the evaluation exits via a call to <code>longjmp</code> (17.13.3) the behavior is undefined.
An implementation is allowed to substitute the evaluation of a predicate <code>P</code>
that returns to the caller with an alternative predicate
that returns the same value as <code>P</code> but has no side effects.
An enforced correctness annotation test where the evaluation of <code>P</code>
 returns <code>false</code> is called <em>unsuccessful</em>.

For an unsuccessful correctness annotation test the <em>contract violation handler</em> is invoked.
The contract violation handler does not exit via an exception or via a call to <code>longjmp</code> (17.13.3).
The semantics of the contract violation handler are implementation defined.

</p>

<p> 5.

<i>Recommended practice</i>: The contract violation handler should by
default output to the stream buffer associated with the object
<code>stderr</code>, declared in <code>&lt;cstdio&gt;</code> (29.13.1),
the message containing the textual representation of the predicate and
the location in the source code where the predicate was evaluated.
For preconditions the source location should be
that where the function containing the corresponding contract annotation
 was called. For postconditions, the source location should be inside
the function definition.

</p>

<p> 6.

[<i>Note</i>: The contract violation handler does not have to be a
function with any linkage. An implementation may provide a way to
customize
the behavior of the contract violation handler.  — <i>end note</i>]

</p>
</blockquote>

<p class="editor">However, an implementation might want to implement it as a global pointer to function, lest when in the future
   the Standard starts to require an installable violation handler, this should cause an ABI breakage.
  </p>

<blockquote class="stdins">
<p> 7.

After the contract violation handler is executed, the program exits and an implementation-defined form of the status <em>unsuccessful termination</em> is returned.
No destructors for objects of automatic, thread,
or static storage duration are executed. Functions passed to <code>atexit()</code> (6.9.3.4) are not called.
</p>

<p> 8.

In translation mode <em>enforce</em> all correctness annotation tests are enforced. In translation mode <em>Ignore</em>
 during constant evaluation (7.7) it is implementation-defined whether
correctness annotation tests are ignored or enforced. In all other
situations in <em>Ignore</em> translation mode all correctness annotation tests are ignored.

</p>

<p> 9.

If a correctness annotation test modifies the value of
any object odr-used (6.3) in its predicate, the behavior is undefined.

</p>

<p>10.
Let <code>PRE</code> denote the basic precondition test sequence of a given function <code>f</code>.
When performing enforced contract annotation tests, it is unspecified if <code>PRE</code> is performed one or two times.
This is called a <em>precondition test sequence</em>.

Let <code>POST</code> denote the basic postcondition test sequence of a given function <code>f</code>.
When performing enforced contract annotation tests, it is unspecified if <code>POST</code> is performed one or two times.
This is called a <em>postcondition test sequence</em>.

[<i>Note</i>: This allows the implementations to test the precondition
and postcondition of a function both inside and outside of the function
body. — <i>end note</i>]

</p>


<p> 11.

When the results of functions <code>fs</code> are used to initialize
function arguments of a function <code>g</code>, the <em>combined test
sequence</em> is a sequence of postcondition test sequences of <code>fs</code>
followed by a precondition test sequence of <code>g</code>.

[<i>Example</i>:</p>

<pre>int f1() [[post r: p1(r)]];
int f2() [[post r: p2(r)]];
void g(int i1, int i2) [[pre: p1(i1)]] [[pre: p2(i2)]];

g(f1(), f2());
</pre>

<p>The combined test sequence of this function call graph is
<code>p1(r)</code>, <code>p2(r)</code>, <code>p1(i1)</code>, <code>p2(i2)</code>. — <i>end example</i>]

If two expressions <code>E1</code> and <code>E2</code> appearing
in a combined test sequence are same (9.12.4.2) and <code>E1</code>
is sequenced before <code>E2</code> the implementation is allowed
to replace the evaluation of <code>E2</code> with the result of
<code>E1</code>. If such substitution changes the result of
the test containing <code>E1</code> and te test is performed,
the behavior is undefined.

[<i>Example</i>:</p>

<pre>int f1() [[post r: p1(r)]];
int f2() [[post r: p2(r)]];
void g(int i1, int i2) [[pre: pg()]] [[pre: p1(i1) &amp;&amp; p2(i2)]];

g(f1(), f2());
</pre>

<p>The implementation is allowed to skip the evaluation of
<code>p1(i1)</code> and <code>p2(i2)</code> and instead use
the values previously returned by <code>p1(r)</code> and <code>p2(r)</code>. — <i>end example</i>]

[<i>Example</i>:</p>

<pre>int f1() [[post: q()]];
int f2() [[post: q()]];
void g(int i1, int i2);

g(f1(), f2());
</pre>

<p>The implementation is not allowed to substitute any
evaluation of <code>q()</code> with the result of the other,
because their corresponding tests are indeterminately
sequenced. — <i>end example</i>]

</p>


</blockquote>



<p>In 11.7.3 [class.virtual] add a new paragraph after 11.7.3/17:</p>


<blockquote class="stdins">

<p> 18.

If an overriding function specifies contract annotations (9.12.4), it shall specify the same list of contract
annotations as its overridden functions; no diagnostic is required if predicates of corresponding contract annotations always
evaluate to the same value. Otherwise, it is considered to have the list of contract annotations from one of
its overridden functions; the names in the contract annotations are bound, and the semantic constraints are
checked, at the point where the contract annotations appear. Given a virtual function <code>f</code> with a contract
annotation that odr-uses <code>*this</code> (6.3), the class of which <code>f</code> is a direct member shall be an unambiguous and
accessible base class of any class in which <code>f</code> is overridden. If a function overrides more than one function, all
of the overridden functions shall have the same list of contract annotations (9.12.4); no diagnostic is required if
predicates in corresponding annotations will always evaluate to the same value. [<i>Example</i>:

</p><pre>struct A {
  virtual void g() [[pre: x == 0]];
  int x = 42;
};

int x = 42;
struct B {
  virtual void g() [[pre: x == 0]];
}

struct C : A, B {
  virtual void g(); <em>// error: precondition annotations of overridden functions are not the same</em>
};
</pre>

<p>— <em>end example</em>]</p>

</blockquote>


<p>In 13.8.3.3/3 [temp.dep.expr] add a bullet after bullet 3.6:</p>

<blockquote class="stdins">

<p>
— an <em>identifier</em> introduced in a postcondition ([dcl.correct])
to represent the result of a templated function whose declared return type contains a placeholder type,
</p>

</blockquote>

<p>In 13.9.4 [temp.expl.spec] add a note after 13.9.4/13:</p>

<blockquote class="stdins">

<p> 14.
[<i>Note</i>: For an explicit specialization of a function template, the contract annotations (9.12.4) of the explicit
specialization are independent of those of the primary template.— <i>end note</i>]
</p>

</blockquote>


<p>In 14.5.1/1 [except.terminate] add a new bullet after bullet 1.7:</p>

<blockquote class="stdins">
<p>
— when a correctness annotation test (9.12.4) exits via an exception, or
</p>
</blockquote>








<h2><a name="ack">8. Acknowledgments
    <span class="link">{ack}</span></a></h2>

<p>Daveed Vandevoorde offered useful feedback on the syntax of contract annotations.</p>

<p>Joshua Berne reviewed this document, including the wording, and offered many useful suggestions.</p>

<p>Walter Brown reviewed the document, and offered many a correction, clarification and improvement.</p>

<p>Nathan Myers offered insights and guidance on the tricky corner cases of contract annotations.</p>

<p>Jens Maurer reviewed the proposed wording and offered significant improvements.</p>

<p>Ville Voutilainen offered numerous useful suggestions to improve the quality of the paper.</p>

<p>John McFarlane offered useful suggestions that improved the quality of the paper.</p>


<h2><a name="ref">9. References
    <span class="link">{ref}</span></a></h2>

<ul>

  <li>[N1613] — Thorsten Ottosen,
      "Proposal to add Design by Contract to C++" <br>
      (<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2004/n1613.pdf">http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2004/n1613.pdf</a>).
      </li>

  <li>[N1800] — Lawrence Crowl, Thorsten Ottosen,
      "Contract Programming For C++0x" <br>
      (<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1800.pdf">http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1800.pdf</a>).
      </li>

  <li>[N1962] — Lawrence Crowl, Thorsten Ottosen,
      "Proposal to add Contract Programming to C++ (revision 4)" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1962.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1962.html</a>).
      </li>

  <li>[N4110] — J. Daniel Garcia,
      "Exploring the design space of contract specifications for C++" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4110.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4110.pdf</a>).
      </li>

  <li>[N4075] — John Lakos, Alexei Zakharov, Alexander Beels,
      "Centralized Defensive-Programming Support for Narrow Contracts(Revision 6)" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4075.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4075.pdf</a>).
      </li>

  <li>[N4135] — John Lakos, Alexei Zakharov, Alexander Beels, Nathan Myers,
      "Language Support for Runtime Contract Validation (Revision 8)" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4135.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4135.pdf</a>).
      </li>

  <li>[P0380R0] — G. Dos Reis, J. D. Garcia, J. Lakos, A. Meredith, N. Myers, B. Stroustrup,
      "A Contract Design" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0380r0.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0380r0.pdf</a>).
      </li>

  <li>[P1494R1] — S. Davis Herring, "Partial program correctness" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1494r1.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1494r1.html</a>).
      </li>

  <li>[P2176r0] — Andrzej Krzemieński, "A different take on inexpressible conditions" <br>
          (<a href="https://isocpp.org/files/papers/P2176R0.html"
          >https://isocpp.org/files/papers/P2176R0.html</a>).
          </li>

  <li>[P2339R0] — Andrzej Krzemieński, "Contract violation handlers" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2339r0.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2339r0.html</a>).
      </li>

  <li>[P2358R0] — Gašper Ažman, John McFarlane, Bronek Kozicki, "Defining Contracts" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2358r0.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2358r0.pdf</a>).
      </li>

  <li>[P0542R5] — G. Dos Reis, J. D. Garcia, J. Lakos, A. Meredith, N. Myers, B. Stroustrup,
      "Support for contract based programming in C++" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0542r5.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0542r5.html</a>).
      </li>

  <li>[P1289R1] — J. Daniel Garcia, Ville Voutilainen, "Access control in contract conditions" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1289r1.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1289r1.pdf</a>).
      </li>

  <li>[P1323R2] — Hubert S.K. Tong, "Contract postconditions and return type deduction" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1323r2.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1323r2.html</a>).
      </li>

  <li>[P1606R0] — Joshua Berne, "Requirements for Contract Roles" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1606r0.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1606r0.pdf</a>).
      </li>

  <li>[P1769R0] — Ville Voutilainen, Richard Smith, "The «default»
contract build-level and continuation-mode should be
implementation-defined"<br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1769r0.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1769r0.html</a>).
      </li>

  <li>[P2038R0] — Andrzej Krzemieński, Ryan McDougall, "Proposed nomenclature for contract-related proposals" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2038r0.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2038r0.html</a>).
      </li>

  <li>[P2182R1] — Andrzej Krzemieński, Joshua Berne, Ryan McDougall,
      "Contract Support: Defining the Minimum Viable Feature Set" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2182r1.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2182r1.html</a>).
      </li>

  <li>[P2036R1] — Barry Revzin, "Change scope of lambda <em>trailing-return-type</em>"<br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2036r1.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2036r1.html</a>).
      </li>

</ul>







<h2><a name="apa">Appendix A. Open issues with continuing violation handlers
    <span class="link">{apa}</span></a></h2>

<p> We are aware of two unintuitive consequences of continuing violation handlers. First,
    in case the precondition is guarding against the abstract machine violation (hard UB),
    logging and then reaching the point of the abstract machine violation might result in
    what would be observed as removing the log entry for the contract violation.
    This has been described in detail in
   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2339r0.html">[P2339R0]</a> as well as in
   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1494r1.html">[P1494R1]</a>.
   This is no worse than disabling runtime checking altogether (which is uncontroversial),
   but can really fool whoever troubleshoots the bug: we see no contract-violation log entry,
   so we think control never reached this point, even though it did. Thus, the continuing violation
   handler has the potential to deceive whoever uses contract violation logs. There is no agreement
   on how realistic the possibility of encountering this effect is. The solution presented in
   <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1494r1.html">[P1494R1]</a>
    has the potential to address the above issue. But until this is explored, any wider contract proposal that
    allows continuation would be blocked on <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1494r1.html">[P1494R1]</a>.</p>

<p> Second, the continuation mode can introduce new abstract machine violations. Going back to the example provided earlier:</p>

<pre>int f(int * p)
  [[pre: p]]
  [[pre: *p &gt; 0]]
{
  if (!p)             <em>// safety double-check </em>
    throw Bug{};

  if (*p &lt;= 0)        <em>// safety double-check </em>
    throw Bug{};

  return *p - 1;
}</pre>

<p> If this function is invoked in a program that doesn't runtime-check contract annotations,
    it behaves in a tolerable way for <code>p == nullptr</code>: it throws an exception.
    But when runtime checking is enabled and the program is allowed to
    continue after the failed check, this code is equivalent to:</p>

<pre>int f(int * p)
{
  if (!p)             <em>// (1)</em>
    log_violation();

  if (*p &lt;= 0)        <em>// (2)</em>
    log_violation();

  if (!p)             <em>// safety double-check </em>
    throw Bug{};

  if (*p &lt;= 0)        <em>// safety double-check </em>
    throw Bug{};

  return *p - 1;
}</pre>

<p> If <code>p</code> happens to be null, check (1) will fail and the
violation will get logged. The program will proceed
    to check (2) and there, it will dereference the null pointer causing
 an Abstract Machine Violation (hard UB).
    The key observation here is that the defensive checks that throw
exceptions (or return) have the "short circuiting" property: if one
fails,
    the subsequent ones are not executed:</p>

<pre>int f(int * p)
{
  if (!p)
    throw Bug{};

  if (*p &lt;= 0)        <em>// null `p` never dereferenced </em>
    throw Bug{};

  return *p - 1;
}</pre>

<p> Short-circuiting is also guaranteed for subsequent precondition annotations, provided that the contract violation
    logging ends in calling <code>std::abort()</code>. But short-circuiting is gone,
    when the handler allows the program flow to continue. </p>

<p>Splitting a precondition into smaller chunks is used for at least two purposes:</p>

<ol>
  <li>Obtaining as fine-grained information as possible from contract violation logs.</li>
  <li>Differentiating cheap and expensive checks, for the purpose of controlling their behavior separately.</li>
</ol>


<p> Until this problem is addressed, the continuation after a runtime-evaluated check is a potentially dangerous
    feature that can introduce an Abstract Machine Violation (hard UB) on top of a BizBug (a programmer bug).
    While this problem may be solvable, the analysis and solution will take time, which will delay the
    adoption of the minimum contract support if it allows the continuation. </p>



</body></html>
