<?xml version="1.0" encoding="US-ASCII"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US"><head>
<title>Options for addressing requires-clause syntax ambiguities</title>

<style type="text/css">/*<![CDATA[*/
body { color: #000000; background-color: #FFFFFF; max-width: 40em; }
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; }

blockquote.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.std del { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC; }
blockquote.std ins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8; }
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-left: 0.5em; padding-right: 0.5em; }

table { border: 1px solid black; border-spacing: 0px;
  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }

table.table { border-spacing: 2px; border-collapse: separate; }
.table * th, .table * td { border: 1px solid black; }

table.frontmatter { border: 0; border-spacing: 0px; border-collapse: collapse; margin: 0; width: 619px; }
.frontmatter * td, .frontmatter * th { padding: 0px; }
.frontmatter * th { font-weight: inherit; text-align: left; vertical-align: top; }

ul.dash { list-style-type: none; }
ul.dash li:before { content: '\2014'; margin-left: -1em }

span.highlight { background-color: #7FDFFF }

.nowrap { white-space: nowrap; }
/*]]>*/
</style>

<script type="text/javascript" src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</head>

<body>
<h1>Options for addressing <i>requires-clause</i> syntax ambiguities</h1>
<table class="frontmatter"><tbody>
    <tr>
        <th>Document number:</th>
        <td>P0730R0</td>
    </tr>
    <tr>
        <th>Date:</th>
        <td>2017-07-11</td>
    </tr>
    <tr>
        <th>Project:</th>
        <td>ISO/IEC JTC 1/SC 22/WG 21/C++</td>
    </tr>
    <tr>
        <th>Working Group:</th>
        <td>Evolution</td>
    </tr>
    <tr>
        <th>Revises:</th>
        <td><i>None</i></td>
    </tr>
    <tr>
        <th>Reply-to:</th>
        <td><span class="nowrap">Hubert S.K. Tong</span> &lt;<a href="mailto:hubert.reinterpretcast@gmail.com">hubert.reinterpretcast@gmail.com</a>&gt;</td>
    </tr>
</tbody></table>

<h2>Description from Concepts Issue 21</h2>
<p>Given either</p>
<pre>template &lt;typename T&gt; requires (bool)&amp;T::operator short
unsigned int foo();</pre>

<p>or</p>
<pre>template &lt;typename T&gt; requires (bool)sizeof new (T::f()) short
unsigned int bar();</pre>

<p>there is more than one successful parse and it is unclear whether the return type is <code>unsigned int</code> or <code>int</code>.</p>

<p>The after-the-function-declarator form of the <i>requires-clause</i> is also ambiguous:</p>
<pre>struct X {};
template&lt;typename T&gt; void f() requires (bool)sizeof new X
{
  // might be the function body, might be a brace-or-equal-init for X
};</pre>

<p>A &#x201c;max munch&#x201d; rule would probably do the wrong thing for the above case, and likewise here:</p>

<pre>template&lt;typename T&gt; requires (bool)sizeof new unsigned
struct X { };</pre>

<p>Proposed resolutions have been to:</p>
<ul>
<li>require parens,</li>
<li>specify rules to make this unambiguous,</li>
<li>specify the operand of a requires-clause as a new grammar.</li>
</ul>

<h2>Current implementation behaviour</h2>
<p>Both GCC and Clang currently handle these cases by consuming the maximum sequence of tokens that parse as a <i>constraint-expression</i>.</p>

<p>Implementations can generate reasonably good diagnostics for experts that are aware of the issue;
however, for users encountering this issue for the first time, this is an unfriendly surprise.</p>

<p>Example (credit due to Richard Smith):</p>
<pre class="example"
>template&lt;typename U&gt;
struct A {
  template&lt;typename T = U&gt; requires (bool)(T())
  A() {}
};</pre>

<p>Diagnostic output from Clang:</p>
<pre class="extract"
>&lt;stdin&gt;:4:7: error: expected member name or ';' after declaration specifiers
  A() {}
      ^
1 error generated.</pre>

<p>The above error message indicates that the parsing reached the brace without encountering a <i>declarator-id</i>;
however, it references &#x201c;declaration specifiers&#x201d;, of which none are actually present.</p>

<p>If we standardize on the existing behaviour, then adding parentheses around the intended constraint can be harmful;
the <i>requires-clause</i> may then appear as the beginning of a C-style cast:</p>
<pre class="example"
>template &lt;typename T&gt;
requires (bool(T()))
int (*fp)();</pre>

<p>Diagnostic output from Clang:</p>
<pre class="extract"
>&lt;stdin&gt;:3:7: error: use of undeclared identifier 'fp'
int (*fp)();
      ^
1 error generated.</pre>

<p>The above error message indicates that the parsing reached the intended <i>declarator-id</i>,
but <code>fp</code> is seen as a name being referred to within an expression.</p>

<h2>Alternative: require parentheses as part of a <i>requires-clause</i></h2>
<p>This alternative is self-explanatory. The parentheses act as a natural delimiter. This would normally cost one extra character because the opening parenthesis is likely to be placed immediately after the <code>requires</code> token:</p>
<pre class="example">template &lt;typename T&gt;
requires C1&lt;T&gt;
void f(T &amp;&amp;);</pre>

<p>becomes</p>
<pre class="example">template &lt;typename T&gt;
requires(C1&lt;T&gt;)
void f(T &amp;&amp;);</pre>

<h2>Alternative: custom expression grammar for <i>requires-clause</i></h2>
<p>This alternative allows commonly written forms of <i>constraint-expression</i> to appear without parentheses. A sample grammar follows:</p>
<blockquote>
<dl><dt><i>requires-clause:</i></dt>
<dd
><code>requires</code> <i>constraint-logical-or-expression</i></dd>
</dl>

<dl><dt><i>constraint-primary-expression:</i></dt>
<dd
><i>primary-expression</i><br
/><i>qualified-concept-name</i> <code>(</code> <code>)</code></dd>
</dl>

<dl><dt><i>constraint-logical-and-expression:</i></dt>
<dd
><i>constraint-primary-expression</i><br
/><i>constraint-logical-and-expression</i> <code>&amp;&amp;</code> <i>constraint-primary-expression</i></dd>
</dl>

<dl><dt><i>constraint-logical-or-expression:</i></dt>
<dd
><i>constraint-logical-and-expression</i><br
/><i>constraint-logical-or-expression</i> <code>||</code> <i>constraint-logical-and-expression</i></dd>
</dl></blockquote>

<p>This grammar clearly allows conjunctions and disjunctions to be expressed easily,
and leaves invocation of function concepts and <i>primary-expression</i>s as &#x201c;primitives&#x201d;.</p>

<p>Restricting to the <i>primary-expression</i> grammar limits the impact of the issue.</p>
<blockquote>
<dl><dt><i>primary-expression:</i></dt>
<dd
><i>literal</i><br
/><code>this</code><br
/><code>(</code> <i>expression</i> <code>)</code><br
/><i>id-expression</i><br
/><i>lambda-expression</i><br
/><i>fold-expression</i><br
/><i>requires-expression</i></dd>
</dl></blockquote>

<p>We note that <i>id-expression</i> is still present and leaves problems with <i>conversion-type-id</i>s;
however, in such cases, the constraint expression would be broken anyway since it would not have type <code>bool</code>.</p>

<p>Constraint primitives not requiring parentheses using this custom grammar include:</p>
<ul>
<li>boolean literals, e.g., <code>true</code>;</li>
<li>references to variable concepts, e.g., <code>C0&lt;T&gt;</code>;</li>
<li>references to type traits, e.g., <code>std::is_union&lt;T&gt;::value</code> or <code>std::is_union_v&lt;T&gt;</code>;</li>
<li><i>fold-expression</i>s; and</li>
<li><i>requires-expression</i>s.</li>
</ul>

<h2><a id="Acknowledgments">Acknowledgements</a></h2>
<p>The author would like to thank Ville Voutilainen and Richard Smith for their input in discussions leading up to the production of this paper.
As usual, any mistakes are the responsibility of the author.</p>

</body>
</html>
