diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-10-15 01:34:54 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-10-15 01:34:54 +0000 |
commit | c2c8bb82096bc938d776557c037cb874de695f80 (patch) | |
tree | 8a958628fb0c1a83e8718f411898b66649f52bc0 /clang/lib/Parse | |
parent | ec67c90216220daa8e99de11dd4437e8a954d153 (diff) | |
download | bcm5719-llvm-c2c8bb82096bc938d776557c037cb874de695f80.tar.gz bcm5719-llvm-c2c8bb82096bc938d776557c037cb874de695f80.zip |
Tidy up and improve error recovery for C++11 attributes in bad places. Based on
a patch by Michael Han.
llvm-svn: 192666
Diffstat (limited to 'clang/lib/Parse')
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 56 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 12 |
3 files changed, 65 insertions, 18 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 6594749592a..21b24bfd79e 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -453,13 +453,11 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, CXXScopeSpec SS; SourceLocation TypenameLoc; bool HasTypenameKeyword = false; - ParsedAttributesWithRange Attrs(AttrFactory); - // FIXME: Simply skip the attributes and diagnose, don't bother parsing them. - MaybeParseCXX11Attributes(Attrs); - ProhibitAttributes(Attrs); - Attrs.clear(); - Attrs.Range = SourceRange(); + // Check for misplaced attributes before the identifier in an + // alias-declaration. + ParsedAttributesWithRange MisplacedAttrs(AttrFactory); + MaybeParseCXX11Attributes(MisplacedAttrs); // Ignore optional 'typename'. // FIXME: This is wrong; we should parse this as a typename-specifier. @@ -509,12 +507,24 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, return 0; } + ParsedAttributesWithRange Attrs(AttrFactory); MaybeParseCXX11Attributes(Attrs); // Maybe this is an alias-declaration. - bool IsAliasDecl = Tok.is(tok::equal); TypeResult TypeAlias; + bool IsAliasDecl = Tok.is(tok::equal); if (IsAliasDecl) { + // If we had any misplaced attributes from earlier, this is where they + // should have been written. + if (MisplacedAttrs.Range.isValid()) { + Diag(MisplacedAttrs.Range.getBegin(), diag::err_attributes_not_allowed) + << FixItHint::CreateInsertionFromRange( + Tok.getLocation(), + CharSourceRange::getTokenRange(MisplacedAttrs.Range)) + << FixItHint::CreateRemoval(MisplacedAttrs.Range); + Attrs.takeAllFrom(MisplacedAttrs); + } + // TODO: Can GNU attributes appear here? ConsumeToken(); @@ -565,6 +575,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, } else { // C++11 attributes are not allowed on a using-declaration, but GNU ones // are. + ProhibitAttributes(MisplacedAttrs); ProhibitAttributes(Attrs); // Parse (optional) attributes (most likely GNU strong-using extension). @@ -3282,6 +3293,37 @@ void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs, attrs.Range = SourceRange(StartLoc, *endLoc); } +void Parser::DiagnoseAndSkipCXX11Attributes() { + if (!isCXX11AttributeSpecifier()) + return; + + // Start and end location of an attribute or an attribute list. + SourceLocation StartLoc = Tok.getLocation(); + SourceLocation EndLoc; + + do { + if (Tok.is(tok::l_square)) { + BalancedDelimiterTracker T(*this, tok::l_square); + T.consumeOpen(); + T.skipToEnd(); + EndLoc = T.getCloseLocation(); + } else { + assert(Tok.is(tok::kw_alignas) && "not an attribute specifier"); + ConsumeToken(); + BalancedDelimiterTracker T(*this, tok::l_paren); + if (!T.consumeOpen()) + T.skipToEnd(); + EndLoc = T.getCloseLocation(); + } + } while (isCXX11AttributeSpecifier()); + + if (EndLoc.isValid()) { + SourceRange Range(StartLoc, EndLoc); + Diag(StartLoc, diag::err_attributes_not_allowed) + << Range; + } +} + /// ParseMicrosoftAttributes - Parse a Microsoft attribute [Attr] /// /// [MS] ms-attribute: diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index ef1ab89b8c9..f57ff97ceb5 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1314,14 +1314,12 @@ StmtResult Parser::ParseDoStatement() { return StmtError(); } - // Parse the parenthesized condition. + // Parse the parenthesized expression. BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); - // FIXME: Do not just parse the attribute contents and throw them away - ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX11Attributes(attrs); - ProhibitAttributes(attrs); + // A do-while expression is not a condition, so can't have attributes. + DiagnoseAndSkipCXX11Attributes(); ExprResult Cond = ParseExpression(); T.consumeClose(); @@ -2547,9 +2545,10 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { } else { StmtVector Handlers; - ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX11Attributes(attrs); - ProhibitAttributes(attrs); + + // C++11 attributes can't appear here, despite this context seeming + // statement-like. + DiagnoseAndSkipCXX11Attributes(); if (Tok.isNot(tok::kw_catch)) return StmtError(Diag(Tok, diag::err_expected_catch)); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 378a239744f..f0a3d9190c3 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1958,12 +1958,18 @@ bool BalancedDelimiterTracker::diagnoseMissingClose() { } P.Diag(P.Tok, DID); P.Diag(LOpen, diag::note_matching) << LHSName; - if (P.SkipUntil(Close, FinalToken, /*StopAtSemi*/ true, /*DontConsume*/ true) - && P.Tok.is(Close)) + + // If we're not already at some kind of closing bracket, skip to our closing + // token. + if (P.Tok.isNot(tok::r_paren) && P.Tok.isNot(tok::r_brace) && + P.Tok.isNot(tok::r_square) && + P.SkipUntil(Close, FinalToken, /*StopAtSemi*/true, /*DontConsume*/true) && + P.Tok.is(Close)) LClose = P.ConsumeAnyToken(); return true; } void BalancedDelimiterTracker::skipToEnd() { - P.SkipUntil(Close, false); + P.SkipUntil(Close, false, true); + consumeClose(); } |