Fix potential infinite loop with malformed attribute syntax
Double square bracket attribute arguments can be arbitrarily complex,
and the attribute argument parsing logic recovers by skipping tokens.
As a fallback recovery mechanism, parse recovery stops before reading a
semicolon. This could lead to an infinite loop in the attribute list
parsing logic.
GitOrigin-RevId: ad2d6bbb1435cef0a048c9aed3dcf9617640f222
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index bc59b41..af3d0df 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -4214,7 +4214,7 @@
llvm::SmallDenseMap<IdentifierInfo*, SourceLocation, 4> SeenAttrs;
bool AttrParsed = false;
- while (Tok.isNot(tok::r_square)) {
+ while (!Tok.isOneOf(tok::r_square, tok::semi)) {
if (AttrParsed) {
// If we parsed an attribute, a comma is required before parsing any
// additional attributes.
@@ -4279,6 +4279,13 @@
<< AttrName;
}
+ // If we hit an error and recovered by parsing up to a semicolon, eat the
+ // semicolon and don't issue further diagnostics about missing brackets.
+ if (Tok.is(tok::semi)) {
+ ConsumeToken();
+ return;
+ }
+
SourceLocation CloseLoc = Tok.getLocation();
if (ExpectAndConsume(tok::r_square))
SkipUntil(tok::r_square);
diff --git a/test/Parser/c2x-attributes.c b/test/Parser/c2x-attributes.c
index 48bb197..d75e9e2 100644
--- a/test/Parser/c2x-attributes.c
+++ b/test/Parser/c2x-attributes.c
@@ -16,6 +16,7 @@
// FIXME: this diagnostic can be improved.
enum E3 [[]] { Seven }; // expected-error {{expected identifier or '('}}
+[[deprecated([""])]] int WrongArgs; // expected-error {{expected expression}}
[[,,,,,]] int Commas1; // ok
[[,, maybe_unused]] int Commas2; // ok
[[maybe_unused,,,]] int Commas3; // ok
diff --git a/test/Parser/cxx-attributes.cpp b/test/Parser/cxx-attributes.cpp
index 2b874e4..d445e42 100644
--- a/test/Parser/cxx-attributes.cpp
+++ b/test/Parser/cxx-attributes.cpp
@@ -35,6 +35,7 @@
pi = &i[0];
}
+[[deprecated([""])]] int WrongArgs; // expected-error {{expected variable name or 'this' in lambda capture list}}
[[,,,,,]] int Commas1; // ok
[[,, maybe_unused]] int Commas2; // ok
[[maybe_unused,,,]] int Commas3; // ok