Skip to content

Commit b7ce85a

Browse files
committed
[Concepts] Fix isDeclarationSpecifier to detect type-constraints correctly
isDeclarationSpecifiers did not handle some cases of placeholder-type-specifiers with type-constraints, causing parsing bugs in abbreviated constructor templates. Add comprehensive handling of type-constraints to isDeclarationSpecifier.
1 parent 5702dad commit b7ce85a

File tree

2 files changed

+41
-11
lines changed

2 files changed

+41
-11
lines changed

clang/lib/Parse/ParseDecl.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5061,6 +5061,8 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
50615061
// recurse to handle whatever we get.
50625062
if (TryAnnotateTypeOrScopeToken())
50635063
return true;
5064+
if (TryAnnotateTypeConstraint())
5065+
return true;
50645066
if (Tok.is(tok::identifier))
50655067
return false;
50665068

@@ -5193,11 +5195,14 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
51935195

51945196
// placeholder-type-specifier
51955197
case tok::annot_template_id: {
5196-
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
5197-
return TemplateId->Kind == TNK_Concept_template &&
5198+
return isTypeConstraintAnnotation() &&
51985199
(NextToken().is(tok::kw_auto) || NextToken().is(tok::kw_decltype));
51995200
}
5200-
5201+
case tok::annot_cxxscope:
5202+
if (NextToken().is(tok::identifier) && TryAnnotateTypeConstraint())
5203+
return true;
5204+
return isTypeConstraintAnnotation() &&
5205+
GetLookAheadToken(2).isOneOf(tok::kw_auto, tok::kw_decltype);
52015206
case tok::kw___declspec:
52025207
case tok::kw___cdecl:
52035208
case tok::kw___stdcall:

clang/test/Parser/cxx2a-abbreviated-templates.cpp

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,36 @@ namespace ns {
99
concept D = true;
1010
}
1111

12-
void foo(C auto a,
13-
C<int> auto b,
14-
ns::D auto c,
15-
ns::D<int> auto d,
16-
const C auto e,
17-
const C<int> auto f,
18-
const ns::D auto g,
19-
const ns::D<int> auto h);
12+
void foo1(C auto a,
13+
C<int> auto b,
14+
ns::D auto c,
15+
ns::D<int> auto d,
16+
const C auto e,
17+
const C<int> auto f,
18+
const ns::D auto g,
19+
const ns::D<int> auto h);
20+
void foo2(C auto a);
21+
void foo3(C<int> auto b);
22+
void foo4(ns::D auto c);
23+
void foo5(ns::D<int> auto d);
24+
void foo6(const C auto e);
25+
void foo7(const C<int> auto f);
26+
void foo8(const ns::D auto g);
27+
void foo9(const ns::D<int> auto h);
28+
29+
struct S1 { S1(C auto a,
30+
C<int> auto b,
31+
ns::D auto c,
32+
ns::D<int> auto d,
33+
const C auto e,
34+
const C<int> auto f,
35+
const ns::D auto g,
36+
const ns::D<int> auto h); };
37+
struct S2 { S2(C auto a); };
38+
struct S3 { S3(C<int> auto b); };
39+
struct S4 { S4(ns::D auto c); };
40+
struct S5 { S5(ns::D<int> auto d); };
41+
struct S6 { S6(const C auto e); };
42+
struct S7 { S7(const C<int> auto f); };
43+
struct S8 { S8(const ns::D auto g); };
44+
struct S9 { S9(const ns::D<int> auto h); };

0 commit comments

Comments
 (0)