summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2014-12-29 06:56:50 +0000
committerNico Weber <nicolasweber@gmx.de>2014-12-29 06:56:50 +0000
commit4b4be84a2f747bc65ccfe53281ae0aa19259744c (patch)
treea9a3572b66ef241adff7aa31bc333022d40a4c6e /clang
parent939111ac518530f79ffd430bbba4b846e8759518 (diff)
downloadbcm5719-llvm-4b4be84a2f747bc65ccfe53281ae0aa19259744c.tar.gz
bcm5719-llvm-4b4be84a2f747bc65ccfe53281ae0aa19259744c.zip
Don't crash on malformed attributes in an incorrect location.
r168626 added nicer diagnostics for attributes in the wrong places, such as after the `final` on a class. To do this, it added code that did high-level pattern matching for e.g. 'final' 'alignas' '(' and then skipped until the closing ')'. If it saw that, it then went down the regular class parsing path and then called MaybeParseCXX11Attributes() to parse the attribute after the 'final' using real attribute parsing code. On invalid attributes, the real attribute parsing code could eat more tokens than the pattern matching code and for example skip past the '{' starting the class, which would then lead to an assert. To prevent this, check for a good state after calling MaybeParseCXX11Attributes() (which morphed into CheckMisplacedCXX11Attribute() in r175575) and bail out if things look bleak. Found by SLi's afl bot. llvm-svn: 224915
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp10
-rw-r--r--clang/test/Parser/cxx0x-attributes.cpp4
2 files changed, 14 insertions, 0 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 14fe9f7cf37..4377a782864 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -2706,6 +2706,16 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
// and the only possible place for them to appertain
// to the class would be between class-key and class-name.
CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc);
+
+ // ParseClassSpecifier() does only a superficial check for attributes before
+ // deciding to call this method. For example, for
+ // `class C final alignas ([l) {` it will decide that this looks like a
+ // misplaced attribute since it sees `alignas '(' ')'`. But the actual
+ // attribute parsing code will try to parse the '[' as a constexpr lambda
+ // and consume enough tokens that the alignas parsing code will eat the
+ // opening '{'. So bail out if the next token isn't one we expect.
+ if (!Tok.is(tok::colon) && !Tok.is(tok::l_brace))
+ return;
}
if (Tok.is(tok::colon)) {
diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp
index e366d8582e8..02791f4f54c 100644
--- a/clang/test/Parser/cxx0x-attributes.cpp
+++ b/clang/test/Parser/cxx0x-attributes.cpp
@@ -330,3 +330,7 @@ namespace {
[[deprecated()]] void foo(); // expected-error {{parentheses must be omitted if 'deprecated' attribute's argument list is empty}}
[[gnu::deprecated()]] void quux();
}
+
+// The diagnostics here don't matter much, this just shouldn't crash:
+class C final [[deprecated(l]] {}; // expected-error {{use of undeclared identifier}} expected-error {{expected ']'}} expected-error {{an attribute list cannot appear here}}
+class C final alignas ([l) {}; // expected-error {{expected ';' after class}}
OpenPOWER on IntegriCloud