<!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: 2em; }

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>Contract support &mdash; Working Paper</title>

</head>
<body>

<table class="header"><tbody>
  <tr>
    <th>Document number:&nbsp;&nbsp;</th><th> </th><td>P2521R0</td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;</th><th> </th><td>2022-01-17</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>Gašper Ažman &lt;gasper dot azman at gmail dot com&gt;</address>
		<address>Joshua Berne &lt;jberne4 at bloomberg dot net&gt;</address>
		<address>Bronek Kozicki &lt;brok at spamcop dot net&gt;</address>
		<address>Andrzej Krzemieński &lt;akrzemi1 at gmail dot com&gt;</address>
    <address>Ryan McDougall &lt;mcdougall dot ryan at gmail dot com&gt;</address>
		<address>Caleb Sunstrum &lt;caleb dot sunstrum at gmail dot com&gt;</address>
				
      </td>
  </tr>
</tbody></table>


<h1>Contract support &mdash; Working Paper</h1>

<p> This paper is a yet another proposal to add a minimum contract support framework to C++. It proposes nothing that hasn't
    already been described in either 
		<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html">[P2388R4]</a> or
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2461r1.pdf">[P2461R1]</a>.

<p> The goal in this paper is to structure the proposal in a different way in order 
    to reflect what SG21 has consensus on and what remains a controversy. We treat the following as open issues:</p>
    
<ol>
<li>The choice of syntax.</li>
<li>Side effect elision and duplication.</li>
<li>The treatment of non-reference function parameters referenced in postconditions.</li>
</ol>

<p> We assume that the reader is already famliar with <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html">[P2388R4]</a>.</p>


<h2><a id="mot">1. Motivation <span class="link">{mot}</span></a></h2>

<p> The motivation for adding contract support framework to C++ is to enable the programmers to define in a formal way what constitutes
    a contact violation (an therefore a bug) in their programs. This information can be later used by different tools to perform
    static or dynamic analysis of the program, add instrumentation code, or generate documentation or programmer hints in the IDE.
		It has been described in more detail in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html">[P2388R4]</a>.</p>

<p> The motivation for producing another paper is to focus on documenting the consensus of SG21.<p>



<h2><a id="not">2. Notation <span class="link">{not}</span></a></h2>

<p>Because the choice of syntax for contract annotations has no consensus yet, in this paper we use placeholder notation:</p>

<pre>
int select(int i, int j)
  PRE(i &gt;= 0)               <em>// precondition</em>
  PRE(j &gt;= 0)
  POST(r: r &gt;= 0)           <em>// postcondition; r names the return value</em>
{
  ASSERT(_state &gt;= 0);      <em>// assertion; not necessarily an expression</em>

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


<h2><a id="pro">3. Proposed characteristics <span class="link">{pro}</span></a></h2>


<h3><a id="pro.tri">3.1. Three declarations: preconditions, postconditions and assertions<span class="link">{pro.tri}</span></a></h3>

<p>We propose that all three types of declarations are included in the minimum contract support:</p>

<ol>
<li>Preconditions.</li>
<li>Postconditions.</li>
<li>Assertions.</li>
</ol>

<p>Although it is possible to add only preconditions to the language and gain minimal benefit, we believe that only the three components
   added together bring sufficient value to warrant the modification of the language. We also believe that the syntax and semantics of preconditions
   must be compatible with these of the postconditions. So even if the preconditions were to be added in isolation, we would have to
   have a polished design for postconditions. This means that preconditions are blocked on the postcondition design even for the "only preconditions" variant.
   </p>


<h3><a id="pro.mod">3.2. Two translation modes<span class="link">{pro.mod}</span></a></h3>

<p> We propose that there are two modes that a translation unit can be translated in:</p>

<ol>
  <li><strong><em>No_eval</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>Eval_and_abort</em></strong>: each contract annotation is checked at runtime.
      The check evaluates the corresponding predicate; if the result equals <code>false</code>,
      the program is stopped an error return value.
      </li>
</ol>

<p> The implementation may, but does not have to, allow the translation of different translation units in different modes. Too many modes are not 
    necessary for the minimum contract implementation. The <em>No_eval</em> is required to provide no-overhead guarantee. The 
    <em>Eval_and_abort</em> is required to actually assign any semantics to contract annotations.
    </p>
    

<h3><a id="pro.lok">3.3. Name look-up<span class="link">{pro.lok}</span></a></h3>

<p> We propose that names referred in preconditions and postconditions are looked up as if they appeared in a <code>noexcept</code> specification,
    if the function had one. In particular, this means that private members can appear in pre/post-conditions.</p>
		
<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.
    The implementers 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 id="pro.ret">3.4. Naming the return value <span class="link">{pro.ret}</span></a></h3>

<p> It is possible to name the return value (or reference) in the postcondition, except for one situation: 
    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> 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="pro.ptr">3.5. Indirect function calls
        <span class="link">{pro.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="pro.vir">3.6. Virtual functions
        <span class="link">{pro.vir}</span></a></h3>

<p> When a virtual function is overridden, the overriding function has the
    same set of preconditions and postconditions as the overridden function,
    whether the contract annotations are repeated in the overriding function or not:</p>

<pre>
struct Base {
  virtual void f() PRE(p1());
};

struct Deriv1 : Base {
  void f() override;            <em>// ok: Deriv1::f has precondition p1()</em>
};

struct Deriv2 : Base {
  void f() override PRE(p1());  <em>// ok: Deriv2::f has the same precondition as Base</em>
};

struct Deriv3 : Base {
  void f() override PRE(p2());  <em>// error: Deriv3::f has different precondition than Base</em>
};
</pre>
		
<p> 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> This means that we do not allow the preconditions in the overriding function to be "wider"
    and the postconditions to be "narrower" than in the overridden function,
    even though this idea &mdash; one aspect of the Liskov Substitution Principle &mdash; is well explored and implemented in other languages.
		The reason for this is that we do not yet have a good understanding of what effect this principle should have on the feature design.
		Should it be just a "best practice" that the programmers are taught? Or should it be enforced by the language? But how?
		We could think of a number of ways. Given the declarations:</p>
		
<pre>
struct Base {
  virtual void f() PRE(p1());
};

struct Deriv : Base {
  void f() override PRE(p2());
};
</pre>

<ol>
<li> Should compiler be able to prove (even if it cannot see the definitions of <code>p1</code> and <code>p2</code>) 
    that the latter is no stricter than the former?</li>
<li> Shall the compiler report an error unless
    the precondition in the overriding function has the form <code>p1() || p2()</code>? </li>
<li> Or should the compiler accept this code and evaluate <code>p1() &amp;&amp; p2()</code> when <code>Deriv::f</code> is called through the <code>Base</code> interface,
     but evaluate predicate <code>p2()</code> when <code>Deriv::f</code> is called directly?     		
</ol>
		
<p>Option 1 is clearly impossible. The other options might be implementable, but it is more like a guess,
    as we know of no implementation experience with these.</p>

<p> However, the decision to add support for this feature can be deferred for later, because the way we specify the feature now
    (ill formed, no diagnostic required) remains open for future extensions in any of the three directions.
		</p> 		

	
	
<h3><a name="pro.imm">3.7. Contract annotations and the immediate context
    <span class="link">{pro.imm}</span></a></h3>


<p> In this proposal the predicates in contract annotations are <em>not</em> in the
    immediate context of the function. They behave similarly to exception specification:</p>

<pre>
template &lt;std::regular T&gt;
void f(T v, T u)
  PRE(v &lt; u); <em>// not part of std::regular</em>

template &lt;typename T&gt;
constexpr bool has_f =
  std::regular&lt;T&gt; &amp;&amp;
  requires(T v, T u) { f(v, u); };

static_assert( has_f&lt;std::string&gt;);         <em>// OK: has_f returns true</em>
static_assert(!has_f&lt;std::complex&lt;float&gt;&gt;); <em>// ill-formed: has_f causes hard instantiation error</em>
</pre>


<p> As a consequence, we may have a function template that works well for
    a given type, but stops working the moment we add a contract annotation.
    This also affects how concepts would be taught: a good concept should express
    not only the operations that are necessary in the <em>implementation</em>
    of the generic algorithms, but also these that are necessary in the
    specification of contract annotations in these algorithms.
    </p>


<h3><a name="pro.end">3.8. <code>abort()</code> vs <code>terminate()</code> <span class="link">{pro.end}</span></a></h3>

<p> In this proposal, throwing from the predicate calls <code>std::terminate()</code> while a failed runtime check
    aborts the application even more abruptly: close to calling <code>std::abort()</code>, but we do not require 
		the actual call to <code>std::abort()</code>, as the function may not be present in freestanding. </p>

<p>	We do not encourage the implementations to allow the users to install custom contract violation handlers, nor do we
    specify any interface describing how this is done. However, we do not actively forbid the implementations form performing some logic,
		as long as it never throws or calls <code>longjmp()</code>.
    </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. The call to <code>std::terminate()</code>
    either calls <code>std::abort()</code> or calls a terminate handler installed by the user. In case the contract is
    violated, and we can be sure the program contains a bug, calling a user-installed function may be unsafe,
    and can pose a security risk.</p>

<p> More, <code>std::terminate()</code> is not available in freestanding implementations. </p>


<h3><a name="pro.log">3.9. No runtime error message<span class="link">{pro.log}</span></a></h3>

<p> This revision of the paper does not require or encourage
    any error message to be displayed to standard diagnostic stream, or anywhere
    in <em>Eval_and_abort</em> mode.
    There are two reasons. First, there is no standard diagnostic stream on
    freestanding implementations, and we want contract support to be available on
    those platforms. Second, for security reasons. When an application is in a confirmed
    incorrect state, performing IO operations may pose a security risk.
    As the primary focus of this proposal is safety, we choose a conservative
    approach.</p>
		

<h3><a name="pro.dec">3.10. Contract annotations upon the first declaration<span class="link">{pro.dec}</span></a></h3>

<p> We require that if a given function <code>f</code> has declared preconditions and postconditions, they shall be visible in the first
    declaration of <code>f</code> in a translation unit (TU): otherwise the program is ill-formed. Subsequent declarations can either omit 
    contract annotations ore repeat them in the identical form (modulo parameter names). If <code>f</code> is declared in more than one TU,
    the corresponding first declarations of <code>f</code> shall be identical (modulo parameter names): otherwise the program is ill-formed with no
    diagnostic required. As a consequence, the following is illegal:</p>
		
<pre>
int select(int i, int j);  <em>// first declaration</em>
	
int select(int i, int j)   <em>// second declaration</em>
  PRE(i &gt;= 0)              <em>// error: initial decl had different (no) contract annotations</em>
  PRE(j &gt;= 0)
  POST(r: r &gt;= 0); 
</pre>

<p>The reason for this restriction is implementability issues, similar to those for default function arguments.</p>


<h2><a id="con">4. Controversial aspects <span class="link">{con}</span></a></h2>	

<p>This section lists points of controversy inside SG21 for the recent contract design. For each of these points, we
   require a poll to be taken, to determine the group direction.</p>

<h3><a id="con.syn">4.1. The choice of syntax<span class="link">{con.syn}</span></a></h3>


<p> There are two visions for the syntax to describe contract annotations with significant support in SG21.</p>

<p>One is to use notation similar to attributes (but not 100% compatible with attributes):</p>

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

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

<p>The other is to use notation similar to lambdas (but not 100% compatible with lambdas):</p>

<pre>int select(int i, int j)
  pre{ i &gt;= 0 }
  pre{ j &gt;= 0 }
  post(r){ r &gt;= 0 }      <em>// r names the return value</em>
{
  assert{ _state &gt;= 0 };

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

<p> The rationale for using the later syntax has been provided in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2461r1.pdf">[P2461R1]</a>.
    The analysis of pros and cons of using the former syntax has been provided in
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2487r0.html">[P2487R0]</a>.
		</p>

<p> The primary argument in favor of quasi-attribute notation is to stress semantic characteristics similar to attributes. 
    The common understanding of attributes is that they are hints for generating warnings or performing optimizations. Their removal,
		should not affect the correctness of the program (even though it is easy to construct an example using <code>no_unique_address</code>
		that contradicts this claim).</p>
		
<p> Contract annotations &mdash; at least one model thereof &mdash; shares similar features: they are hints for tools for generating warnings
    or emitting an instrumentation code. If these annotations are removed <em>from a correct program</em> (one that does not violate the declared
		contract annotations), this does not affect the correctness of the program.
    </p> 
		
<p> The primary arguments in favor of quasi-lambda syntax is to avoid the problems reported for quasi-attribute syntax 
    (e.g., that they look like attributes but do not follow other characteristics of attributes) and to offer an intuitive
		syntax for one of the future extensions: making copies of function arguments for use in postconditions.


<h3><a id="con.eff">4.2. Removal and duplication of side effects in predicates<span class="link">{con.eff}</span></a></h3>

<p> An implementation may need to evaluate the same predicate in a precondition twice. For direct calls,
    it is desired to insert the instrumentation code in the caller: this gives better diagnostics, 
		so it is preferred whenever possible. However this is impossible when a function is called indirectly,
    either trough a pointer or <code>std::function</code>: from the pointer signature we do not know if a function called
		has a precondition or not. Because of these cases the precondition check may need to be compiled into the function.
		This results in the situation where a function is called directly, but the body is in a different translation unit, and we want
		to make the check in the caller for better diagnostic, and inside the body to cover the indirect calls. we want to enable such implementation strategies.
		The end result for the programmer is that when the predicate has side effects, these effects occur twice.</p>

<p> For performance reasons an implementation may want not to evaluate the predicate, if it already knows what its result would be.
    This can happen when a function that produces a value has sufficiently similar postcondition <code>p</code> to the precondition of another function
    that subsequently consume the same value, and we do not see the body of <code>p</code>:</p>
		
<pre>
bool p(int); <em>// defined in a different TU</em>

int produce() POST(r: p(r));
void consume(int i) PRE(p(i));

int main() {
  consume(produce()); <em>// can p() be called once</em>
}
</pre>

<p> This seems redundant to call the same predicate twice. Of course, this seems so only if <code>p()</code> doesn't have side effects.
    If it does, and the program (or the programmer) relies on them, this elision can make the comprehension of the program harder,
		and the effects surprising.</p>

<p> Both	<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html">[P2388R4]</a> and
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2461r1.pdf">[P2461R1]</a> propose this capability to remove and duplicate the
		evaluation of the predicates. However, concerns have been expressed about it.</p>


<p> Note that <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html">[P2388R4]</a> additionally proposes the 
    "partial elision" of side effects in a predicate. We received a feedback that the group is against it, so this "partial elision" is 
		not considered in this paper.</p>		


<h3><a id="con.arg">4.3. Function parameters in postconditions<span class="link">{con.arg}</span></a></h3>


<p> The model that we used for contract annotations is simple: we execute a predicate at certain specified points in time 
    (for instance, just before the function call for preconditions) and the predicate observes the state of the program at that moment.
		This model works intuitively except for one case: when function:</p>
	
<ol>
<li>has a non-reference parameter, and</li>
<li>this parameter is referenced in the postcondition, and</li>
<li>this parameter is modified inside the function.</li>
</ol>	
		
<p> This problem has been explained in detail in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html">[P2388R4]</a>
    and <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2466r0.html">[P2466R0]</a>.
		Here, we only show an example that demonstrates the issue:</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;     <em>// at this point result &lt; lo</em>
}

<em>// usage:</em>
int min = 1;
int max = 10;

int r = generate(min, max);   <em>// postcondition check fails</em>
assert(min &lt;= r &amp;&amp; r &lt;= max); <em>// even though this is satisfied</em>
</pre>

<p> How is this problem addressed in other languages?
    In D, this problem has been ignored: postconditions like the one above give false positive or false negative results.
		In ADA this problem does not occur: this is due to the way the function arguments are designed. In ADA, for each 
		function argument, the programmer has to specify if it is IN or OUT or INOUT. The OUT and INOUT parameters correspond to reference
    parameters in C++, so there is no problem here. The IN parameters, on the other hand, are immutable, so there is no question of 
    changing them inside the function: IN parameters correspond to <code>const</code> by-value parameters in C++.		
</p>	
	
	
<p> How can this issue be addressed? </p>

<ol>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0542r5.html">[P0542R5]</a> proposed to do what D does:
    it called this situation undefined behavior. </li>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html">[P2388R4]</a> and <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2461r1.pdf">[P2461R1]</a> proposes to imitate the solution from ADA: if the postcondition uses the non-reference prameters: require them to be <code>const</code> objects.</li>
</ol>

<p> Additionally, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2461r1.pdf">[P2461R1]</a> proposes for the future revisions the ability
    for the programmer to request that copies of designated function parameters be made. These copies could also be referenced when
		the postcondition is evaluated:
		</p>

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

<p> The lambda-introducer syntax should make it immediately clear, even for the uninitiated programmers, that a copy of function parameters is being made.</p>

<p> The quasi-attribute notation also allows this as a future extension, however this would require a new notation, which comes with a complexity and an aesthetical cost:</p>

<pre>
int generate(int lo, int hi)
  [[pre: lo &lt;= hi ]]
  [[post r, old_lo = lo, old_hi = hi: old_lo &lt;= r &amp;&amp; r &lt;= old_hi ]];
	
// or some alternate notation

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

<p> Thus, the decision how to address the issue of by-value arguments in postconditions is somewhat tied to the choice of syntax.
    But perhaps not as much as one might think at first.</p>

<p> We could allow postconditions to reference <code>const</code> by-value parameters in postconditions in the MVP. 
    This would address a reasonable subset of real-life use cases immediately, and at the same time not prevent the addition of 
    "copies on demnd" in the future. We could go even further and require the compiler to do implicit copies for trivially-copyable
    types. This would create a "hybrid" solution that is the least intrusive for the programmers:</p>

<pre>int generate(int lo, int hi)
  PRE(lo &lt;= hi)
  POST(r: lo &lt;= r &amp;&amp; r &lt;= hi)  <em>// ok: we can copy ints implicitly</em>
{ <em>/* ... */</em> }

BigInt generate(BigInt const lo, BigInt const hi)
  PRE(lo &lt;= hi)
  POST(r: lo &lt;= r &amp;&amp; r &lt;= hi)  <em>// ok: can safely inspect original objects </em>
{ <em>/* ... */</em> }	

BigInt generate(BigInt lo, BigInt hi)
  PRE(lo &lt;= hi)
  POST(r: lo &lt;= r &amp;&amp; r &lt;= hi)  <em>// sorry: please, wait for C++29 </em>
{ <em>/* ... */</em> }	
</pre>	

<p> Thus, the first question in this section is actually: how many cases of function arguments can we afford to handle in the MVP:</p>

<ol>
  <li>Disallow function arguments in postconditions: even the reference ones.</li>
	<li>Disallow only by-value function arguments in postconditions: references are allowed.</li>
	<li>Allow reference and const function arguments in postconditions. </li>
	<li>Allow reference and const and trivially-copyable function arguments in postconditions. </li>
</ol>

<p>Another question is a slight difference between <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html">[P2388R4]</a> or
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2461r1.pdf">[P2461R1]</a>. The former paper allows by-value parameter to omit
		<code>const</code> on the function decaration, but only requires it on function definition:<p>
		
<pre>
// P2388R4:

int generate(int lo, int hi)
  PRE(lo &lt;= hi)
  POST(r: lo &lt;= r &amp;&amp; r &lt;= hi);           <em>// ok: just a declaration</em>

int generate(int const lo, int const hi) <em>// ok: prameters are const in definition</em>
{ <em>/* ... */</em> }
</pre>

<p> The only thing we need here is that the compiler will ultimately prevent any modifications in the function body.
    In contrast, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2461r1.pdf">[P2461R1]</a> 
		requires that even the declartions have function arguments declared with <code>const</code>, even though programmers
		have been taught for years that the addition or the omission of <code>const</code> in by-value arguments in function
		declarations has no effect. 
</p>

<p> One reason for this additional restrction, is that the quasi-lambda solution may require certain mangling of function names in the presence of
    lambds, and the lambda type that captures by reference may be affected based on whether by-value function arguments are const or not:</p>

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

<p> So the trade-off here is the ability to declare lambda-like copies of arguments at the cost introducing new rules for <code>const</code>
    by-value arguments in function declarations.</p>

<p> An additional question that one might want to answer is that if we allowed in postconditions arguments 
    that are either references or const or trivially-copyable, are the remaining cases sufficient to 
		motivate the addition of quasi-lambda syntax?<p>

<p> It should be noted <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2461r1.pdf">[P2461R1]</a> offers more motivation than
    the quasi-lambda syntax than solving the problem of function arguments in postconditions. The notable exmple is the support for "oldof" values:</p>

<pre>
void vector::push_back(T const&amp; val)
  POST(r: size() == OLDOF(size()) + 1);
	
// in P2461R1, post-MVP:

void vector::push_back(T const&amp; val)
  post [old_size = size()]{ size() == oldof_size + 1 };

// in P2388R4, post-MVP:

void vector::push_back(T const&amp; val)
  [[post old_size = size(): size() == oldof_size + 1]];
</pre>	
	

<h2><a name="ack">5. References
    <span class="link">{ack}</span></a></h2>
		
<p> This paper is a summary of SG21 discussions; all SG21 members contributed to this paper. John McFarlane suggeted the idea to make implcit copies of trivilly-copyable types.</p>


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

<ul>

  <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>[P2388R4] — Andrzej Krzemieński, Gašper Ažman, "Minimum Contract Support: either No_eval or Eval_and_abort" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html</a>).
      </li>
	
  <li>[P2461R1] — Gašper Ažman, Caleb Sunstrum, Bronek Kozicki, "Closure-Based Syntax for Contracts" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2461r1.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2461r1.pdf</a>).
      </li>	
			
  <li>[P2466R0] — Andrzej Krzemieński, "The notes on contract annotations" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2466r0.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2466r0.html</a>).
      </li>	

  <li>[P2487R0] — Andrzej Krzemieński, "Attribute-like syntax for contract annotations" <br>
      (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2487r0.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2487r0.html</a>).
      </li>		
			
			
			
			
</ul>


</body></html>