summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-10-15 01:34:54 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-10-15 01:34:54 +0000
commitc2c8bb82096bc938d776557c037cb874de695f80 (patch)
tree8a958628fb0c1a83e8718f411898b66649f52bc0 /clang/lib/Parse
parentec67c90216220daa8e99de11dd4437e8a954d153 (diff)
downloadbcm5719-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.cpp56
-rw-r--r--clang/lib/Parse/ParseStmt.cpp15
-rw-r--r--clang/lib/Parse/Parser.cpp12
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();
}
OpenPOWER on IntegriCloud