diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-11-15 22:45:29 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-11-15 22:45:29 +0000 |
commit | a3e01cf822f7415337e5424af3c6f4c94a12c1b9 (patch) | |
tree | 33e9d9c041d05e24fa06fda646b16a327e3bb159 /clang/lib | |
parent | 9c13dd027bf2c3ff8d81d60af3e893a01515f1ff (diff) | |
download | bcm5719-llvm-a3e01cf822f7415337e5424af3c6f4c94a12c1b9.tar.gz bcm5719-llvm-a3e01cf822f7415337e5424af3c6f4c94a12c1b9.zip |
PR8455: Handle an attribute between a goto label and a variable declaration per
the GNU documentation: the attribute only appertains to the label if it is
followed by a semicolon. Based on a patch by Aaron Ballman!
llvm-svn: 194869
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 8f537eaa5e7..e32d61928d1 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -516,11 +516,40 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) { // identifier ':' statement SourceLocation ColonLoc = ConsumeToken(); - // Read label attributes, if present. attrs will contain both C++11 and GNU - // attributes (if present) after this point. - MaybeParseGNUAttributes(attrs); + // Read label attributes, if present. + StmtResult SubStmt; + if (Tok.is(tok::kw___attribute)) { + ParsedAttributesWithRange TempAttrs(AttrFactory); + ParseGNUAttributes(TempAttrs); - StmtResult SubStmt(ParseStatement()); + // In C++, GNU attributes only apply to the label if they are followed by a + // semicolon, to disambiguate label attributes from attributes on a labeled + // declaration. + // + // This doesn't quite match what GCC does; if the attribute list is empty + // and followed by a semicolon, GCC will reject (it appears to parse the + // attributes as part of a statement in that case). That looks like a bug. + if (!getLangOpts().CPlusPlus || Tok.is(tok::semi)) + attrs.takeAllFrom(TempAttrs); + else if (isDeclarationStatement()) { + StmtVector Stmts; + // FIXME: We should do this whether or not we have a declaration + // statement, but that doesn't work correctly (because ProhibitAttributes + // can't handle GNU attributes), so only call it in the one case where + // GNU attributes are allowed. + SubStmt = ParseStatementOrDeclarationAfterAttributes( + Stmts, /*OnlyStmts*/ true, 0, TempAttrs); + if (!TempAttrs.empty() && !SubStmt.isInvalid()) + SubStmt = Actions.ProcessStmtAttributes( + SubStmt.get(), TempAttrs.getList(), TempAttrs.Range); + } else { + Diag(Tok, diag::err_expected_semi_after) << "__attribute__"; + } + } + + // If we've not parsed a statement yet, parse one now. + if (!SubStmt.isInvalid() && !SubStmt.isUsable()) + SubStmt = ParseStatement(); // Broken substmt shouldn't prevent the label from being added to the AST. if (SubStmt.isInvalid()) @@ -557,7 +586,7 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { // out of stack space in our recursive descent parser. As a special case, // flatten this recursion into an iterative loop. This is complex and gross, // but all the grossness is constrained to ParseCaseStatement (and some - // wierdness in the actions), so this is just local grossness :). + // weirdness in the actions), so this is just local grossness :). // TopLevelCase - This is the highest level we have parsed. 'case 1' in the // example above. |