<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="generator" content="pandoc">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
  <title>axiom_level_contract_statements</title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
a.sourceLine:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
  { position: relative; left: -4em; }
pre.numberSource a.sourceLine::before
  { content: attr(title);
    position: relative; left: -1em; text-align: right; vertical-align: baseline;
    border: none; pointer-events: all; display: inline-block;
    -webkit-touch-callout: none; -webkit-user-select: none;
    -khtml-user-select: none; -moz-user-select: none;
    -ms-user-select: none; user-select: none;
    padding: 0 4px; width: 4em;
    color: #aaaaaa;
  }
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
div.sourceCode
  {  }
@media screen {
a.sourceLine::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  </style>
  <link rel="stylesheet" href="github.css">
  <!-- Style for Markdown -->
  <style>
  .md2html-container {
    max-width: 800px;
    margin: 0 auto;
  }
  .md2html-container > h1:first-child {
    margin-top: 0;
  }
  body {
  font-family: Helvetica, arial, sans-serif;
  font-size: 14px;
  line-height: 1.6;
  padding-top: 10px;
  padding-bottom: 10px;
  background-color: white;
  padding: 30px; }

body > *:first-child {
  margin-top: 0 !important; }
body > *:last-child {
  margin-bottom: 0 !important; }

a {
  color: #4183C4; }
a.absent {
  color: #cc0000; }
a.anchor {
  display: block;
  padding-left: 30px;
  margin-left: -30px;
  cursor: pointer;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0; }

h1, h2, h3, h4, h5, h6 {
  margin: 20px 0 10px;
  padding: 0;
  font-weight: bold;
  -webkit-font-smoothing: antialiased;
  cursor: text;
  position: relative; }

h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
  background: url("../../images/modules/styleguide/para.png") no-repeat 10px center;
  text-decoration: none; }

h1 tt, h1 code {
  font-size: inherit; }

h2 tt, h2 code {
  font-size: inherit; }

h3 tt, h3 code {
  font-size: inherit; }

h4 tt, h4 code {
  font-size: inherit; }

h5 tt, h5 code {
  font-size: inherit; }

h6 tt, h6 code {
  font-size: inherit; }

h1 {
  font-size: 28px;
  color: black; }

h2 {
  font-size: 24px;
  border-bottom: 1px solid #cccccc;
  color: black; }

h3 {
  font-size: 18px; }

h4 {
  font-size: 16px; }

h5 {
  font-size: 14px; }

h6 {
  color: #777777;
  font-size: 14px; }

p, blockquote, ul, ol, dl, li, table, pre {
  margin: 15px 0; }

hr {
  background: transparent url("../../images/modules/pulls/dirty-shade.png") repeat-x 0 0;
  border: 0 none;
  color: #cccccc;
  height: 4px;
  padding: 0; }

body > h2:first-child {
  margin-top: 0;
  padding-top: 0; }
body > h1:first-child {
  margin-top: 0;
  padding-top: 0; }
  body > h1:first-child + h2 {
    margin-top: 0;
    padding-top: 0; }
body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child {
  margin-top: 0;
  padding-top: 0; }

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
  margin-top: 0;
  padding-top: 0; }

h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
  margin-top: 0; }

li p.first {
  display: inline-block; }

ul, ol {
  padding-left: 30px; }

ul :first-child, ol :first-child {
  margin-top: 0; }

ul :last-child, ol :last-child {
  margin-bottom: 0; }

dl {
  padding: 0; }
  dl dt {
    font-size: 14px;
    font-weight: bold;
    font-style: italic;
    padding: 0;
    margin: 15px 0 5px; }
    dl dt:first-child {
      padding: 0; }
    dl dt > :first-child {
      margin-top: 0; }
    dl dt > :last-child {
      margin-bottom: 0; }
  dl dd {
    margin: 0 0 15px;
    padding: 0 15px; }
    dl dd > :first-child {
      margin-top: 0; }
    dl dd > :last-child {
      margin-bottom: 0; }

blockquote {
  border-left: 4px solid #dddddd;
  padding: 0 15px;
  color: #777777; }
  blockquote > :first-child {
    margin-top: 0; }
  blockquote > :last-child {
    margin-bottom: 0; }

table {
  border-collapse: collapse;
  padding: 0; }
  table tr {
    border-top: 1px solid #cccccc;
    background-color: white;
    margin: 0;
    padding: 0; }
    table tr:nth-child(2n) {
      background-color: #f8f8f8; }
    table tr th {
      font-weight: bold;
      border: 1px solid #cccccc;
      text-align: left;
      margin: 0;
      padding: 6px 13px; }
    table tr td {
      border: 1px solid #cccccc;
      text-align: left;
      margin: 0;
      padding: 6px 13px; }
    table tr th :first-child, table tr td :first-child {
      margin-top: 0; }
    table tr th :last-child, table tr td :last-child {
      margin-bottom: 0; }

img {
  max-width: 100%; }

span.frame {
  display: block;
  overflow: hidden; }
  span.frame > span {
    border: 1px solid #dddddd;
    display: block;
    float: left;
    overflow: hidden;
    margin: 13px 0 0;
    padding: 7px;
    width: auto; }
  span.frame span img {
    display: block;
    float: left; }
  span.frame span span {
    clear: both;
    color: #333333;
    display: block;
    padding: 5px 0 0; }
span.align-center {
  display: block;
  overflow: hidden;
  clear: both; }
  span.align-center > span {
    display: block;
    overflow: hidden;
    margin: 13px auto 0;
    text-align: center; }
  span.align-center span img {
    margin: 0 auto;
    text-align: center; }
span.align-right {
  display: block;
  overflow: hidden;
  clear: both; }
  span.align-right > span {
    display: block;
    overflow: hidden;
    margin: 13px 0 0;
    text-align: right; }
  span.align-right span img {
    margin: 0;
    text-align: right; }
span.float-left {
  display: block;
  margin-right: 13px;
  overflow: hidden;
  float: left; }
  span.float-left span {
    margin: 13px 0 0; }
span.float-right {
  display: block;
  margin-left: 13px;
  overflow: hidden;
  float: right; }
  span.float-right > span {
    display: block;
    overflow: hidden;
    margin: 13px auto 0;
    text-align: right; }

code, tt {
  margin: 0 2px;
  padding: 0 5px;
  white-space: nowrap;
  border: 1px solid #eaeaea;
  background-color: #f8f8f8;
  border-radius: 3px; }

pre code {
  margin: 0;
  padding: 0;
  white-space: pre;
  border: none;
  background: transparent; }

.highlight pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px; }

pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px; }
  pre code, pre tt {
    background-color: transparent;
    border: none; }
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
  <div class="md2html-container">
<p>Paper number: P1704r0 <br> Date: 2019-06-16 <br> Author: Joshua Berne, Andrzej Krzemieński<br> Email: akrzemi1 (at) gmail (dot) com <br> Audience: EWG, CWG</p>
<h1 id="undefined-functions-in-axiom-level-contract-statements">Undefined functions in axiom-level contract statements</h1>
<p>Current <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4810.pdf">[WD]</a> allows axiom-level contract statements to be evaluated at runtime. This is contradictory with the design goals for axiom-level contract statements outlined in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0380r0.pdf">[P0380r0]</a>, which explicitly notes that the goal for axiom-level contract statements is to allow functions without definitions. In this paper we propose to make it clear that a program is guaranteed, in any build level, to compile and link when conditions in axiom-level contract statements contain references to objects and functions without definitions.</p>
<h3 id="non-goals">Non-goals</h3>
<p>At the same time we want to preserve the guarantee from <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4810.pdf">[WD]</a> that if the implementaiton can somehow determine the value that the predicate would return, it should be able to use this information for optimization or correctness verification purposes. Unconditionally having such optimizations are controversial and considered a defficiency in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4810.pdf">[WD]</a> by some parties, but we consider it an orthogonal issue to the one discussed in this paper.</p>
<p>In this paper we do not discuss side effects being allowed in axiom-level contact statements. That will be the subject of another paper.</p>
<h2 id="what-we-need">What we need</h2>
<p>We need to be able to declare predicates like:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb1-1" title="1"><span class="kw">template</span> &lt;InputIterator I, Sentinel&lt;I&gt; S&gt;</a>
<a class="sourceLine" id="cb1-2" title="2">  <span class="dt">bool</span> is_reachable(I b, S e); <span class="co">// never defined</span></a>
<a class="sourceLine" id="cb1-3" title="3"></a>
<a class="sourceLine" id="cb1-4" title="4"><span class="kw">template</span> &lt;<span class="kw">typename</span> T&gt;</a>
<a class="sourceLine" id="cb1-5" title="5">  <span class="dt">bool</span> points_to_heap_object(T* p); <span class="co">// never defined</span></a></code></pre></div>
<p>They are unimplementable, therefore they are only declared but never defined. They are still useful for static analysis. We want to be able to put them in axiom-level contract statements and have the guarantee that we will never get a linker error saying that an odr-used symbol is missing, regrdless of any build level.</p>
<p>At the same time, it is plausible that the implementation can understand the semantics of our condition and by some other means it can compute the result without causing any side effects and without odr-using any new entity in the condition. Such result could be used for optimization purposes, or for additional correctness validation. The current <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4810.pdf">[WD]</a> allows this and we do not want to prevent this.</p>
<p>Note that with this change contract statements with level <code>axiom</code> will become substantially different from other levels: only for them the “no linkage problems” guarantee applies. In contrast,<code>audit</code> and <code>default</code> levels require defineitions even if they are not evaluated in the current build level. For those levels we explicitly prefer retaining that ODR use to minimize the risk of writing code that links with some build levels and fails to link with others, which is a significant benefit contracts can have as a language facility over being implemented solely with macros.</p>
<p>To summarize our goal:</p>
<ol type="1">
<li>Missing definitions of entities (objects or functions) in the condition of an axiom-level contract statement never make the program ill-formed. Same as inside <code>sizeof()</code> or <code>decltype()</code>.</li>
<li>Optimizations still potentially enabled if there is a way to determine the predicate result without violating point 1.</li>
</ol>
<h2 id="proposed-wording">Proposed wording</h2>
<p>Modifications apply to section [dcl.attr.contract.cond].</p>
<h4 id="modify-paragraph-4">Modify paragraph 4:</h4>
<p>During constant expression evaluation, only predicates of checked contracts are evaluated. In other contexts, it is unspecified whether the predicate for a <ins><code>default</code> or <code>audit</code> level contract</ins> that is not checked under the current build level is evaluated; if the predicate of such a contract would evaluate to <code>false</code>, the behavior is undefined.</p>
<h4 id="add-paragraph-at-the-end">Add paragraph at the end:</h4>
<p>The predicate <code>p</code> of a contract condition with <code>axiom</code> <em>contract-level</em> is an unevaluated operand. If an implementation is able to determine what the value would be returned by evaluating <code>p</code>, and this value is <code>false</code>, the behavior is undefined.</p>
<p>[<em>Example:</em></p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb2-1" title="1"><span class="dt">bool</span> pred(<span class="dt">int</span> i);  <span class="co">// never defined</span></a>
<a class="sourceLine" id="cb2-2" title="2"></a>
<a class="sourceLine" id="cb2-3" title="3"><span class="dt">void</span> f(<span class="dt">int</span> * p)</a>
<a class="sourceLine" id="cb2-4" title="4">  [[<span class="at">expects axiom</span>:<span class="at"> p </span>&amp;&amp;<span class="at"> pred</span>(*<span class="at">p</span>)]];</a>
<a class="sourceLine" id="cb2-5" title="5"></a>
<a class="sourceLine" id="cb2-6" title="6"><span class="dt">void</span> g(<span class="dt">int</span> * p)</a>
<a class="sourceLine" id="cb2-7" title="7">{</a>
<a class="sourceLine" id="cb2-8" title="8">  f(p);</a>
<a class="sourceLine" id="cb2-9" title="9">  <span class="cf">if</span> (p != <span class="kw">nullptr</span>) <span class="co">// the check can be elided</span></a>
<a class="sourceLine" id="cb2-10" title="10">    *p = <span class="dv">0</span>;</a>
<a class="sourceLine" id="cb2-11" title="11">}</a></code></pre></div>
<p>Implementation can eliminate the check <code>p != nullptr</code> in function <code>g</code>. If <code>p</code> was null, the precondition of <code>f</code> would evaluate to <code>false</code>, which would be undefined behavior. The potential contract violation can be determined without the call to function <code>pred</code> owing to the semantics of operator <code>&amp;&amp;</code>. <em>–end example</em>]</p>
<h2 id="acknowledgements">Acknowledgements</h2>
<p>Many people in EWG reflector helped shape this proposal, in particular, Tony Van Eerd.</p>
<h2 id="references">References</h2>
<p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4810.pdf">[WD]</a> – Richard Smith, N4800, “Working Draft, Standard for Programming Language C++”.</p>
<p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0380r0.pdf">[P0380r0]</a> – G. Dos Reis, J. D. Garcia, J. Lakos, A. Meredith, N. Myers, B. Stroustrup, “A Contract Design”.</p>
<p><a href="http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2019/p1429r1.pdf">[P1429r1]</a> – Joshua Berne, John Lakos, “Contracts That Work”.</p>
  </div>
</body>
</html>

