<div dir="auto"><div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, 31 Jan 2020, 10:08 Saar Raz via cfe-commits, <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
Author: Saar Raz<br>
Date: 2020-01-31T20:08:13+02:00<br>
New Revision: b7ce85a130789d23c69156f4b899962458d1f05d<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/b7ce85a130789d23c69156f4b899962458d1f05d" rel="noreferrer noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/b7ce85a130789d23c69156f4b899962458d1f05d</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/b7ce85a130789d23c69156f4b899962458d1f05d.diff" rel="noreferrer noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/b7ce85a130789d23c69156f4b899962458d1f05d.diff</a><br>
<br>
LOG: [Concepts] Fix isDeclarationSpecifier to detect type-constraints correctly<br>
<br>
isDeclarationSpecifiers did not handle some cases of placeholder-type-specifiers with<br>
type-constraints, causing parsing bugs in abbreviated constructor templates.<br>
<br>
Add comprehensive handling of type-constraints to isDeclarationSpecifier.<br>
<br>
Added: <br>
<br>
<br>
Modified: <br>
    clang/lib/Parse/ParseDecl.cpp<br>
    clang/test/Parser/cxx2a-abbreviated-templates.cpp<br>
<br>
Removed: <br>
<br>
<br>
<br>
################################################################################<br>
diff  --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp<br>
index 871ca2512598..af6e105ca61f 100644<br>
--- a/clang/lib/Parse/ParseDecl.cpp<br>
+++ b/clang/lib/Parse/ParseDecl.cpp<br>
@@ -5061,6 +5061,8 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {<br>
     // recurse to handle whatever we get.<br>
     if (TryAnnotateTypeOrScopeToken())<br>
       return true;<br>
+    if (TryAnnotateTypeConstraint())<br>
+      return true;<br>
     if (Tok.is(tok::identifier))<br>
       return false;<br>
<br>
@@ -5193,11 +5195,14 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {<br>
<br>
     // placeholder-type-specifier<br>
   case tok::annot_template_id: {<br>
-    TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);<br>
-    return TemplateId->Kind == TNK_Concept_template &&<br>
+    return isTypeConstraintAnnotation() &&<br>
         (NextToken().is(tok::kw_auto) || NextToken().is(tok::kw_decltype));<br>
   }<br>
-<br>
+  case tok::annot_cxxscope:<br>
+    if (NextToken().is(tok::identifier) && TryAnnotateTypeConstraint())<br>
+      return true;<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">Our behaviour here (on invalid code) depends on whether we've already annotated the type constraint (if not, we don't require the next token to be auto/decltype). It'd be good to be consistent here.</div><div dir="auto"><br></div><div dir="auto">Incidentally, if we see any kind of (possibly-qualified) identifier or template-id followed by auto/decltype, I think we should classify it as a decl-specifier to improve error recovery when there's a typo in a concept name.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+    return isTypeConstraintAnnotation() &&<br>
+        GetLookAheadToken(2).isOneOf(tok::kw_auto, tok::kw_decltype);<br>
   case tok::kw___declspec:<br>
   case tok::kw___cdecl:<br>
   case tok::kw___stdcall:<br>
<br>
diff  --git a/clang/test/Parser/cxx2a-abbreviated-templates.cpp b/clang/test/Parser/cxx2a-abbreviated-templates.cpp<br>
index e2b3803c807e..6562389f7676 100644<br>
--- a/clang/test/Parser/cxx2a-abbreviated-templates.cpp<br>
+++ b/clang/test/Parser/cxx2a-abbreviated-templates.cpp<br>
@@ -9,11 +9,36 @@ namespace ns {<br>
   concept D = true;<br>
 }<br>
<br>
-void foo(C auto a,<br>
-         C<int> auto b,<br>
-         ns::D auto c,<br>
-         ns::D<int> auto d,<br>
-         const C auto e,<br>
-         const C<int> auto f,<br>
-         const ns::D auto g,<br>
-         const ns::D<int> auto h);<br>
\ No newline at end of file<br>
+void foo1(C auto a,<br>
+          C<int> auto b,<br>
+          ns::D auto c,<br>
+          ns::D<int> auto d,<br>
+          const C auto e,<br>
+          const C<int> auto f,<br>
+          const ns::D auto g,<br>
+          const ns::D<int> auto h);<br>
+void foo2(C auto a);<br>
+void foo3(C<int> auto b);<br>
+void foo4(ns::D auto c);<br>
+void foo5(ns::D<int> auto d);<br>
+void foo6(const C auto e);<br>
+void foo7(const C<int> auto f);<br>
+void foo8(const ns::D auto g);<br>
+void foo9(const ns::D<int> auto h);<br>
+<br>
+struct S1 { S1(C auto a,<br>
+               C<int> auto b,<br>
+               ns::D auto c,<br>
+               ns::D<int> auto d,<br>
+               const C auto e,<br>
+               const C<int> auto f,<br>
+               const ns::D auto g,<br>
+               const ns::D<int> auto h); };<br>
+struct S2 { S2(C auto a); };<br>
+struct S3 { S3(C<int> auto b); };<br>
+struct S4 { S4(ns::D auto c); };<br>
+struct S5 { S5(ns::D<int> auto d); };<br>
+struct S6 { S6(const C auto e); };<br>
+struct S7 { S7(const C<int> auto f); };<br>
+struct S8 { S8(const ns::D auto g); };<br>
+struct S9 { S9(const ns::D<int> auto h); };<br>
\ No newline at end of file<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" rel="noreferrer">cfe-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div></div></div>