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

<style>
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; }
dl > dt { font-style:italic; }
body { font-family: "Calibri" }

@media (prefers-color-scheme: dark) {
	body { background: #111; color:  #ccc; }
	a { color:  #38f; }
	a:visited { color:  #a4d; }
	.sect { color:  #ccc; }
    del { text-decoration: line-through; color: #EE9999; }
    ins { text-decoration: underline; color: #99EE99; }
    blockquote.std    { color: #ccc; background-color: #2A2A2A;  border: 1px solid #3A3A3A;  padding-left: 0.5em; padding-right: 0.5em; }
    blockquote.stddel { text-decoration: line-through;  color: #ccc; background-color: #221820;  border: 1px solid #332228;  padding-left: 0.5em; padding-right: 0.5em; ; }
    blockquote.stdins { text-decoration: underline;  color: #ccc; background-color: #182220;  border: 1px solid #223328; padding: 0.5em; }
    table { border: 1px solid #ccc; border-spacing: 0px;  margin-left: auto; margin-right: auto; }
}

@media (prefers-color-scheme: light) {
	body { background:  white; color: black; }
    del { text-decoration: line-through; color: #8B0040; }
    ins { text-decoration: underline; color: #005100; }
    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 { border: 1px solid black; border-spacing: 1px;  margin-left: auto; margin-right: auto; }
}


.comment em { font-family: "Calibri"; font-style:italic; }
p.example   { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }
div.poll { 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; font-family: "Consolas", "Lucida Console", monospace; font-size:80% }


table.header { border: none; border-spacing: 0;  margin-left: 0px; font-style: normal; }
td.header { border: none; border-spacing: 0;  margin-left: 0px; font-style: normal; }
.header { border: none; border-spacing: 0;  margin-left: 0px; font-style: normal; }
table.poll { border: 1px solid black; border-spacing: 0px;  margin-left: 0px; font-style: normal; }

th { text-align: left; vertical-align: top;  padding-left: 0.4em;  /*padding-right: 0.4em; border-bottom:1px dashed;*/ }
td { text-align: left;  padding-left: 0.4em; padding-right: 0.4em; /*border-right:1px dashed; */}
tr { border: solid; border-width: 1px 0; border-bottom:1px solid blue }


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

</style>

<title>Violation handlers vs `noexcept`</title>

</head>
<body>  

<table class="header"><tbody>
  <tr>
    <th>Document number:&nbsp;&nbsp;</th><th> </th><td class="header">P3541R0</td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;</th><th> </th><td class="header">2024-12-16</td>
  </tr>
  <tr>
    <th>Audience:&nbsp;&nbsp;</th><th> </th><td class="header">SG21, SG23, EWG</td>
  </tr>
  <tr>
    <th>Reply-to:&nbsp;&nbsp;</th><th> </th><td class="header">
        <address>Andrzej Krzemie&#324;ski &lt;akrzemi1 at gmail dot com&gt;</address>
    </td>
  </tr>
</tbody></table>



<h1>Violation handlers vs <code>noexcept</code></h1>


<p> In this paper we point out that a number of correctness-checking features
    currently considered for addition to C++ that allow responding 
    to runtime-detected violations via exceptions, should
    define the interaction with the <code>noexcept</code>-specifier and the
    <code>noexcept</code>-operator.
    </p>


<h2><a class="sect" id="1">1.</a> Background</h2>


<p> There is a number of proposals currently on the flight aiming at detecting at run-time
    the incorrect usages of the language or libraries, and responding to them in a number of ways,
    including by throwing an exception. These proposals include:</p>

<ol>
  <li><a href="https://isocpp.org/files/papers/P2900R11.pdf"
       title="Joshua Berne, Timur Doumler, Andrzej Krzemieński et al., &ldquo;Contracts for C++&rdquo;">[P2900R11]</a>
      &mdash; Contracts for C++,
      </li>
  <li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3471r0.html"
       title="Konstantin Varlamov, Louis Dionne, &ldquo;Standard library hardening&rdquo;">[P3471R0]</a>
      &mdash; Standard library hardening,
      </li>
  <li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3081r0.pdf"
       title="Herb Sutter, &ldquo;Core safety Profiles: Specification, adoptability, and impact&rdquo;">[P3081R0]</a>
      &mdash; Core safety profiles,
      </li>    
  <li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3100r1.pdf"
       title="Timur Doumler, Gašper Ažman, Joshua Berne, &ldquo;Undefined and erroneous behaviour is a contract violation&rdquo;">[P3100R1]</a>
       &mdash; Undefined and erroneous behaviour is a contract violation.
       </li>
</ol>

<p> In all these proposals we have the notion of a <em>violation handler:</em>
    a user-customisable function that 
    is invoked in response to a bug detected at run-time at the point in program where the bug has 
    been detected. One of the intended use cases for these handlers is for the programmer
    to be able to throw an exception that would on the one hand prevent the execution of the 
    following expression, and on the other resume the program execution from another location.
    </p>




<h2><a class="sect" id="2">2.</a> The problem</h2>


<p> The effect of these added runtime-checks is that expressions and constructs
    that used to be visibly non-throwing now can throw exceptions, possibly only under some
    compiler configurations. Consider the following function.
    </p>

<pre>Tool::~Tool() <em>// noexcept by default</em>
{ 
  for (int i = 0; i &lt;= size(); ++i) {
    static_assert(noexcept(_vector[i]));
    _vector[i].retire(i);
  }
}
</pre>

<p> In C++23 this definition of a destructor compiles fine: the static assertion does not fire. But if a 
    <code>bounds</code> profile is enforced, as per 
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3081r0.pdf"
       title="Herb Sutter, &ldquo;Core safety Profiles: Specification, adoptability, and impact&rdquo;">[P3081R0]</a>,
    and the programmer installs a throwing violation handler, the element-accessing
    expression can now throw an exception. So the question is, what should the
    <code>noexcept</code>-operator return in this case, and if the answer should depend on
    whether the <code>bounds</code> profile is enforced in the given context. Note also
    that even if the runtime check and the throw are performed outside of the expression,
    as suggested in 
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3081r0.pdf"
       title="Herb Sutter, &ldquo;Core safety Profiles: Specification, adoptability, and impact&rdquo;">[P3081R0]</a>,
    they are still performed inside the enclosing destructor, which is implicitly declared 
    <code>noexcept</code>, so an exception that is thrown doesn't achieve the goal of not 
    terminating the program and still ends up calling <code>std::terminate()</code>.

<p> In short, the idea of throwing an exception everywhere where we would previously have 
    undefined behavior is clearly at odds with the semantics of <code>noexcept</code>,
    and also at odds with the notion of exception safety guarantees (<a href="https://www.boost.org/community/exception_safety.html"
        title="David Abrahams, &ldquo;Exception-Safety in Generic Components&rdquo;">[ABRAHAMS]</a>).
    </p>
    
<p> While it is true that upon undefined behavior the language imposes nothing on the programs,
    and they are free to lie about <code>noexcept</code>, this is not helpful
    when the goal is to guarantee a predictable, non-surprising, non-UB, non-terminating behavior
    of an incorrect program.
    </p>
    
    
    
<h2><a class="sect" id="3">3.</a> The interaction with contracts</h2>


<p> Contracts (<a href="https://isocpp.org/files/papers/P2900R11.pdf"
       title="Joshua Berne, Timur Doumler, Andrzej Krzemieński et al., &ldquo;Contracts for C++&rdquo;">[P2900R11]</a>)
    are special in this regard, as the runtime-checks are never added implicitly
    but require an explicit usage of either <code>pre</code> or 
    <code>post</code> on function declarations or <code>contract_assert</code> as a
    statement.
    </p>
    
<p> <a href="https://isocpp.org/files/papers/P2900R11.pdf"
       title="Joshua Berne, Timur Doumler, Andrzej Krzemieński et al., &ldquo;Contracts for C++&rdquo;">[P2900R11]</a>
       
    clearly defines the interaction with <code>noexcept</code>. 
    Preconditions and postconditions, even if physically checked in the caller, 
    interact with <code>noexcept</code> as if they were evaluated inside the function body.     
    </p>

<p> <code>contract_assert</code> is a statement rather than an expression, so that its
    non-throwing property cannot be tested in any way. 
    </p>

<p> However, while this works for now, we know of two features that propose to be able
    to test the non-throwing property of arbitrary statements:</p>
    
<ol>
    <li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3166r0.html"
       title="Lewis Baker, &ldquo;Static Exception Specifications&rdquo;">[P3166R0]</a>
       &mdash; <em>Static Exception Specifications,</em> where you can annotate your function
       with <code>throw(auto)</code> which will deduce the exception specification from all 
       statements in the function body,
       </li>
    <li><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2806r2.html"
       title="Bruno Cardoso Lopes, Zach Laine, Michael Park, Barry Revzin, &ldquo;do expressions&rdquo;">[P2806R2]</a>
     &mdash; <em><code>do</code> expressions,</em> which turn a sequence of statements into an 
      expression which you can inspect with the <code>noexcept</code>-operator.
      </li>
</ol>

<p> If either of these features is added, the question will need to be answered:
    is <code>contract_assert</code> potentially throwing?
    </p>
 



<h2><a class="sect" id="4">4.</a> Conclusion</h2>



<p> Given that the same idea — potentially throwing in a controlled way from every place 
    that is undefined-behavior-like — surfaces in a number of proposals, the C++ community
    would benefit from a clear design direction in this respect.
    </p>
    
<p> The following are the possible directions that we can think of.
    </p>
 
<ol> 
    <li>Any undefined behavior or contract assertion evaluating to <code>false</code>
        is potentially throwing and the throwing behavior can be controlled by programmers.
    </li>
    <li>All these constructs are non-throwing, 
        and we accept that "turn UB into a controlled throw" is not a thing.
    </li>
    <li>The said features are either observably no-throwing or observably potentially
        throwing based on some configuration, maybe a compiler switch.
        </li>
    <li>The said features are <code>noexcept(true)</code> but can throw nonetheless.
        </li>
</ol>

<p> Any of the choices comes with a cost. #1 goes against the intuition of exception safety,
    where you need some operations to be never-throwing in order to provide a strong (transactional)
    exception safety guarantees. It also goes against the direction outlined in 
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0709r4.pdf"
       title="Herb Sutter, &ldquo;Zero-overhead deterministic exceptions: Throwing values&rdquo;">[P0709R4]</a>.
    Note that a goal of turning UB into a throw requires exception safety to still be provided. #2 closes the door for the direction, where any bug could be turned into an exception
    and recovered from at some higher levels. #3 has a consequence of a correct program
    (even if it has no bugs and does no recovery) taking different paths of execution depending 
    on the (conformant) compiler switches. #4, while allows throwing, makes the environment —
    the compiler and the libraries that depend on <code>noexcept</code> — unprepared for 
    handling the exception in a reliable way, so the goal of reliably recovering from a detected bug.
    Options #1 and #2, while they close doors for certain use cases, have a clear, simple, teachable model
    to offer.
    </p>         
      
       
<h2><a class="sect" id="5">5.</a> References</h2>


<ul>



    <li>
        [ABRAHAMS] — David Abrahams,
        "Exception-Safety in Generic Components"<br>
        (<a href="https://www.boost.org/community/exception_safety.html">https://www.boost.org/community/exception_safety.html</a>).
    </li>
    <!--
    <a href="https://www.boost.org/community/exception_safety.html"
        title="David Abrahams, &ldquo;Exception-Safety in Generic Components&rdquo;">[ABRAHAMS]</a>
    -->

    <li>
        [N2855] — Douglas Gregor, David Abrahams,
        "Rvalue References and Exception Safety"<br>
        (<a href="https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2855.html">https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2855.html</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2855.html"
        title="Douglas Gregor, David Abrahams, &ldquo;Rvalue References and Exception Safety&rdquo;">[N2855]</a>
    -->

    <li>
        [N2983] — David Abrahams, Rani Sharoni, Doug Gregor,
        "Allowing Move Constructors to Throw"<br>
        (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2983.html"
            >https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2983.html</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2983.html"
        title="David Abrahams, Rani Sharoni, Doug Gregor, &ldquo;Allowing Move Constructors to Throw&rdquo;">[N2983]</a>
    -->
    
        <li>
        [N3248] — Alisdair Meredith, John Lakos,
        "noexcept Prevents Library Validation"<br>
        (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3248.pdf">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3248.pdf</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3248.pdf"
        title="Alisdair Meredith, John Lakos, &ldquo;noexcept Prevents Library Validation&rdquo;">[N3248]</a>
    -->
    
    
<li>[P0709R4] — Herb Sutter, "Zero-overhead deterministic exceptions: Throwing values" <br>
    (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0709r4.pdf">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0709r4.pdf</a>).
    </li>
    <!-- 
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0709r4.pdf"
       title="Herb Sutter, &ldquo;Zero-overhead deterministic exceptions: Throwing values&rdquo;">[P0709R4]</a>
    -->
    
    
    
    <li>
        [P2698R0] — Bjarne Stroustrup, "Unconditional termination is a serious problem" <br>
        (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2698r0.pdf">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2698r0.pdf</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2698r0.pdf"
       title="Bjarne Stroustrup, &ldquo;Unconditional termination is a serious problem&rdquo;">[P2698R0]</a>
    -->
    
     <li>
        [P2780R0] — Ville Voutilainen,
        "Caller-side precondition checking, and Eval_and_throw"<br>
        (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2780r0.html">
            https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2780r0.html
        </a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2780r0.html"
        title="Ville Voutilainen, &ldquo;Caller-side precondition checking, and Eval_and_throw&rdquo;">[P2780R0]</a>
    -->



<li>[P2806R2] — Bruno Cardoso Lopes, Zach Laine, Michael Park, Barry Revzin, "<code>do</code> expressions" <br>
    (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2806r2.html">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2806r2.html</a>).
    </li>
    <!-- 
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2806r2.html"
       title="Bruno Cardoso Lopes, Zach Laine, Michael Park, Barry Revzin, &ldquo;do expressions&rdquo;">[P2806R2]</a>
    -->
    
    
<li>[P2858R0] — Andrzej Krzemieński,
    "Noexcept vs contract violations", <br>
    (<a href="https://isocpp.org/files/papers/P2858R0.html">"https://isocpp.org/files/papers/P2858R0.html"</a>).
    </li>
    <!--
    <a href="https://isocpp.org/files/papers/P2858R0.html"
       title="Andrzej Krzemieński, &ldquo;Noexcept vs contract violations&rdquo;">[P2858R0]</a>
    -->
          
<li>[P2900R11] — Joshua Berne, Timur Doumler, Andrzej Krzemieński et al.,
    "Contracts for C++", <br>
    (<a href="https://isocpp.org/files/papers/P2900R11.pdf">"https://isocpp.org/files/papers/P2900R11.pdf"</a>).
    </li>
    <!--
    <a href="https://isocpp.org/files/papers/P2900R11.pdf"
       title="Joshua Berne, Timur Doumler, Andrzej Krzemieński et al., &ldquo;Contracts for C++&rdquo;">[P2900R11]</a>
    -->
 
    
<li>[P3081R0] — Herb Sutter, "Core safety Profiles: Specification, adoptability, and impact" <br>
    (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3081r0.pdf">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3081r0.pdf</a>).
    </li>
    <!-- 
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3081r0.pdf"
       title="Herb Sutter, &ldquo;Core safety Profiles: Specification, adoptability, and impact&rdquo;">[P3081R0]</a>
    -->


<li>[P3100R1] — Timur Doumler, Gašper Ažman, Joshua Berne, "Undefined and erroneous behaviour is a contract violation" <br>
    (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3100r1.pdf">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3100r1.pdf</a>).
    </li>
    <!-- 
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3100r1.pdf"
       title="Timur Doumler, Gašper Ažman, Joshua Berne, &ldquo;Undefined and erroneous behaviour is a contract violation&rdquo;">[P3100R1]</a>
    -->


<li>[P3166R0] — Lewis Baker, "Static Exception Specifications" <br>
    (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3166r0.html">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3166r0.html</a>).
    </li>
    <!-- 
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3166r0.html"
       title="Lewis Baker, &ldquo;Static Exception Specifications&rdquo;">[P3166R0]</a>
    -->
    

<li>[P3471R0] — Konstantin Varlamov, Louis Dionne, "Standard library hardening" <br>
    (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3471r0.html">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3471r0.html</a>).
    </li>
    <!-- 
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3471r0.html"
       title="Konstantin Varlamov, Louis Dionne, &ldquo;Standard library hardening&rdquo;">[P3471R0]</a>
    -->





</ul>



</body></html>
