summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorAlp Toker <alp@nuanti.com>2014-01-01 03:08:43 +0000
committerAlp Toker <alp@nuanti.com>2014-01-01 03:08:43 +0000
commit383d2c478cdd1f688a2e0d71a8867eef33316c0a (patch)
treef07c878376122ba66e754480a75c96c47672b693 /clang/lib
parent3fec8c612e62d1bd458031ba309251e01b2a8b7c (diff)
downloadbcm5719-llvm-383d2c478cdd1f688a2e0d71a8867eef33316c0a.tar.gz
bcm5719-llvm-383d2c478cdd1f688a2e0d71a8867eef33316c0a.zip
ExpectAndConsume: Diagnose errors automatically
1) Teach ExpectAndConsume() to emit expected and expected-after diagnostics using the generic diagnostic descriptions added in r197972, eliminating another set of trivial err_expected_* variations while maintaining existing behaviour. 2) Lift SkipUntil() recovery out of ExpectAndConsume(). The Expect/Consume family of functions are primitive parser operations that now have the well-defined property of operating on single tokens. Factoring out recovery exposes opportunities for more consistent and tailored error recover at the call sites instead of just relying on a bottled SkipUntil formula. llvm-svn: 198270
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Parse/ParseCXXInlineMethods.cpp6
-rw-r--r--clang/lib/Parse/ParseDecl.cpp33
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp47
-rw-r--r--clang/lib/Parse/ParseExpr.cpp46
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp10
-rw-r--r--clang/lib/Parse/ParseObjc.cpp72
-rw-r--r--clang/lib/Parse/ParseStmt.cpp8
-rw-r--r--clang/lib/Parse/ParseTemplate.cpp8
-rw-r--r--clang/lib/Parse/Parser.cpp89
-rw-r--r--clang/lib/Parse/RAIIObjectsForParser.h4
10 files changed, 157 insertions, 166 deletions
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 95502143b0f..feff7fb724a 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -96,9 +96,9 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)
<< Delete;
SkipUntil(tok::semi);
- } else {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- Delete ? "delete" : "default", tok::semi);
+ } else if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ Delete ? "delete" : "default")) {
+ SkipUntil(tok::semi);
}
return FnD;
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f664cf20409..60cb48f6760 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -171,10 +171,10 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
AttributeList::AS_GNU);
}
}
- if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+ if (ExpectAndConsume(tok::r_paren))
SkipUntil(tok::r_paren, StopAtSemi);
SourceLocation Loc = Tok.getLocation();
- if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
+ if (ExpectAndConsume(tok::r_paren))
SkipUntil(tok::r_paren, StopAtSemi);
if (endLoc)
*endLoc = Loc;
@@ -322,7 +322,7 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
}
SourceLocation RParen = Tok.getLocation();
- if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
+ if (!ExpectAndConsume(tok::r_paren)) {
SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc;
Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc,
ArgExprs.data(), ArgExprs.size(), Syntax);
@@ -826,8 +826,10 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
IdentifierLoc *Platform = ParseIdentifierLoc();
// Parse the ',' following the platform name.
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
+ }
// If we haven't grabbed the pointers for the identifiers
// "introduced", "deprecated", and "obsoleted", do so now.
@@ -857,11 +859,9 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
}
UnavailableLoc = KeywordLoc;
- if (Tok.isNot(tok::comma))
- break;
-
- ConsumeToken();
- continue;
+ if (TryConsumeToken(tok::comma))
+ continue;
+ break;
}
if (Tok.isNot(tok::equal)) {
@@ -2385,7 +2385,7 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
SourceLocation KWLoc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return;
SourceLocation EllipsisLoc;
@@ -2496,8 +2496,8 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
return false;
Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getLocEnd()),
- diag::err_expected_semi_after_tagdecl)
- << DeclSpec::getSpecifierName(DS.getTypeSpecType());
+ diag::err_expected_after)
+ << DeclSpec::getSpecifierName(DS.getTypeSpecType()) << tok::semi;
// Try to recover from the typo, by dropping the tag definition and parsing
// the problematic tokens as a type.
@@ -3468,7 +3468,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
continue;
}
ConsumeToken();
- ExpectAndConsume(tok::l_paren, diag::err_expected_lparen);
+ ExpectAndConsume(tok::l_paren);
if (!Tok.is(tok::identifier)) {
Diag(Tok, diag::err_expected) << tok::identifier;
SkipUntil(tok::semi);
@@ -3479,7 +3479,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
Tok.getIdentifierInfo(), Fields);
FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end());
ConsumeToken();
- ExpectAndConsume(tok::r_paren, diag::err_expected_rparen);
+ ExpectAndConsume(tok::r_paren);
}
if (TryConsumeToken(tok::semi))
@@ -3757,8 +3757,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
if (Tok.isNot(tok::semi)) {
// A semicolon was missing after this declaration. Diagnose and recover.
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
- "enum");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");
PP.EnterToken(Tok);
Tok.setKind(tok::semi);
}
@@ -3987,7 +3986,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
// was probably forgotten.
bool CanBeBitfield = getCurScope()->getFlags() & Scope::ClassScope;
if (!isValidAfterTypeSpecifier(CanBeBitfield)) {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, "enum");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");
// Push this token back into the preprocessor and change our current token
// to ';' so that the rest of the code recovers as though there were an
// ';' after the definition.
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 6098c0c8970..d3283eb21bd 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -263,8 +263,8 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
// Eat the ';'.
DeclEnd = Tok.getLocation();
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name,
- "", tok::semi);
+ if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name))
+ SkipUntil(tok::semi);
return Actions.ActOnNamespaceAliasDef(getCurScope(), NamespaceLoc, AliasLoc, Alias,
SS, IdentLoc, Ident);
@@ -428,10 +428,10 @@ Decl *Parser::ParseUsingDirective(unsigned Context,
// Eat ';'.
DeclEnd = Tok.getLocation();
- ExpectAndConsume(tok::semi,
- GNUAttr ? diag::err_expected_semi_after_attribute_list
- : diag::err_expected_semi_after_namespace_name,
- "", tok::semi);
+ if (ExpectAndConsume(tok::semi,
+ GNUAttr ? diag::err_expected_semi_after_attribute_list
+ : diag::err_expected_semi_after_namespace_name))
+ SkipUntil(tok::semi);
return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS,
IdentLoc, NamespcName, attrs.getList());
@@ -588,10 +588,11 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
// Eat ';'.
DeclEnd = Tok.getLocation();
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- !Attrs.empty() ? "attributes list" :
- IsAliasDecl ? "alias declaration" : "using declaration",
- tok::semi);
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ !Attrs.empty() ? "attributes list"
+ : IsAliasDecl ? "alias declaration"
+ : "using declaration"))
+ SkipUntil(tok::semi);
// Diagnose an attempt to declare a templated using-declaration.
// In C++11, alias-declarations can be templates:
@@ -664,8 +665,10 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
return 0;
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::semi))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::semi);
return 0;
+ }
if (!isTokenStringLiteral()) {
Diag(Tok, diag::err_expected_string_literal)
@@ -1373,8 +1376,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
if (Tok.isNot(tok::semi)) {
// A semicolon was missing after this declaration. Diagnose and recover.
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
- DeclSpec::getSpecifierName(TagType));
+ ExpectAndConsume(tok::semi, diag::err_expected_after,
+ DeclSpec::getSpecifierName(TagType));
PP.EnterToken(Tok);
Tok.setKind(tok::semi);
}
@@ -1637,8 +1640,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (TUK == Sema::TUK_Definition &&
(TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {
if (Tok.isNot(tok::semi)) {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
- DeclSpec::getSpecifierName(TagType));
+ ExpectAndConsume(tok::semi, diag::err_expected_after,
+ DeclSpec::getSpecifierName(TagType));
// Push this token back into the preprocessor and change our current token
// to ';' so that the rest of the code recovers as though there were an
// ';' after the definition.
@@ -1985,11 +1988,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
}
// TODO: recover from mistakenly-qualified operator declarations.
- if (ExpectAndConsume(tok::semi,
- diag::err_expected_semi_after,
- "access declaration",
- tok::semi))
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ "access declaration")) {
+ SkipUntil(tok::semi);
return;
+ }
Actions.ActOnUsingDeclaration(getCurScope(), AS,
/* HasUsingKeyword */ false,
@@ -3306,11 +3309,11 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
}
}
- if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+ if (ExpectAndConsume(tok::r_square))
SkipUntil(tok::r_square);
if (endLoc)
*endLoc = Tok.getLocation();
- if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
+ if (ExpectAndConsume(tok::r_square))
SkipUntil(tok::r_square);
}
@@ -3381,7 +3384,7 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs,
ConsumeBracket();
SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch);
if (endLoc) *endLoc = Tok.getLocation();
- ExpectAndConsume(tok::r_square, diag::err_expected_rsquare);
+ ExpectAndConsume(tok::r_square);
}
}
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 96f8f55a738..e7bc682211c 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1296,7 +1296,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}
if (!LHS.isInvalid()) {
- if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen, ""))
+ if (ExpectAndConsume(tok::l_paren))
LHS = ExprError();
else
Loc = PrevTokLocation;
@@ -1698,8 +1698,10 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
case tok::kw___builtin_va_arg: {
ExprResult Expr(ParseAssignmentExpression());
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
Expr = ExprError();
+ }
TypeResult Ty = ParseTypeName();
@@ -1722,8 +1724,10 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
return ExprError();
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
+ }
// We must have at least one identifier here.
if (Tok.isNot(tok::identifier)) {
@@ -1798,16 +1802,20 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
SkipUntil(tok::r_paren, StopAtSemi);
return Cond;
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
+ }
ExprResult Expr1(ParseAssignmentExpression());
if (Expr1.isInvalid()) {
SkipUntil(tok::r_paren, StopAtSemi);
return Expr1;
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
+ }
ExprResult Expr2(ParseAssignmentExpression());
if (Expr2.isInvalid()) {
@@ -1829,11 +1837,12 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
-
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",
- tok::r_paren))
+
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
-
+ }
+
// Second argument is the type to bitcast to.
TypeResult DestTy = ParseTypeName();
if (DestTy.isInvalid())
@@ -1857,11 +1866,12 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
-
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",
- tok::r_paren))
+
+ if (ExpectAndConsume(tok::comma)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
-
+ }
+
// Second argument is the type to bitcast to.
TypeResult DestTy = ParseTypeName();
if (DestTy.isInvalid())
@@ -1938,7 +1948,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
Tok.is(tok::kw___bridge_retained) ||
Tok.is(tok::kw___bridge_retain)));
if (BridgeCast && !getLangOpts().ObjCAutoRefCount) {
- if (Tok.isNot(tok::kw___bridge)) {
+ if (!TryConsumeToken(tok::kw___bridge)) {
StringRef BridgeCastName = Tok.getName();
SourceLocation BridgeKeywordLoc = ConsumeToken();
if (!PP.getSourceManager().isInSystemHeader(BridgeKeywordLoc))
@@ -1946,8 +1956,6 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
<< BridgeCastName
<< FixItHint::CreateReplacement(BridgeKeywordLoc, "");
}
- else
- ConsumeToken(); // consume __bridge
BridgeCast = false;
}
@@ -2195,7 +2203,7 @@ ExprResult Parser::ParseGenericSelectionExpression() {
Diag(KeyLoc, diag::ext_c11_generic_selection);
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return ExprError();
ExprResult ControllingExpr;
@@ -2210,7 +2218,7 @@ ExprResult Parser::ParseGenericSelectionExpression() {
}
}
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "")) {
+ if (ExpectAndConsume(tok::comma)) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -2242,7 +2250,7 @@ ExprResult Parser::ParseGenericSelectionExpression() {
}
Types.push_back(Ty);
- if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "")) {
+ if (ExpectAndConsume(tok::colon)) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 61dfbc6d58c..cef5b270e7b 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1186,7 +1186,7 @@ ExprResult Parser::ParseCXXCasts() {
SourceLocation RAngleBracketLoc = Tok.getLocation();
- if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
+ if (ExpectAndConsume(tok::greater))
return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << tok::less);
SourceLocation LParenLoc, RParenLoc;
@@ -2747,7 +2747,7 @@ ExprResult Parser::ParseTypeTrait() {
SourceLocation Loc = ConsumeToken();
BalancedDelimiterTracker Parens(*this, tok::l_paren);
- if (Parens.expectAndConsume(diag::err_expected_lparen))
+ if (Parens.expectAndConsume())
return ExprError();
SmallVector<ParsedType, 2> Args;
@@ -2808,7 +2808,7 @@ ExprResult Parser::ParseArrayTypeTrait() {
SourceLocation Loc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return ExprError();
TypeResult Ty = ParseTypeName();
@@ -2825,7 +2825,7 @@ ExprResult Parser::ParseArrayTypeTrait() {
T.getCloseLocation());
}
case ATT_ArrayExtent: {
- if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) {
+ if (ExpectAndConsume(tok::comma)) {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
@@ -2851,7 +2851,7 @@ ExprResult Parser::ParseExpressionTrait() {
SourceLocation Loc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return ExprError();
ExprResult Expr = ParseExpression();
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index a36d2ea1b41..c8460c0e808 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -115,14 +115,12 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
ClassLocs.push_back(Tok.getLocation());
ConsumeToken();
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
-
- ConsumeToken();
}
// Consume the ';'.
- if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@class"))
return Actions.ConvertDeclToDeclGroup(0);
return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
@@ -613,8 +611,10 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter :
diag::err_objc_expected_equal_for_getter;
- if (ExpectAndConsume(tok::equal, DiagID, "", tok::r_paren))
+ if (ExpectAndConsume(tok::equal, DiagID)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
+ }
if (Tok.is(tok::code_completion)) {
if (IsSetter)
@@ -639,10 +639,11 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
DS.setSetterName(SelIdent);
- if (ExpectAndConsume(tok::colon,
- diag::err_expected_colon_after_setter_name, "",
- tok::r_paren))
+ if (ExpectAndConsume(tok::colon,
+ diag::err_expected_colon_after_setter_name)) {
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
+ }
} else {
DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
DS.setGetterName(SelIdent);
@@ -1057,11 +1058,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
Sema::ObjCArgInfo ArgInfo;
// Each iteration parses a single keyword argument.
- if (Tok.isNot(tok::colon)) {
- Diag(Tok, diag::err_expected) << tok::colon;
+ if (ExpectAndConsume(tok::colon))
break;
- }
- ConsumeToken(); // Eat the ':'.
ArgInfo.Type = ParsedType();
if (Tok.is(tok::l_paren)) // Parse the argument type if present.
@@ -1211,9 +1209,8 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
ProtocolLocs.push_back(Tok.getLocation());
ConsumeToken();
- if (Tok.isNot(tok::comma))
+ if (!TryConsumeToken(tok::comma))
break;
- ConsumeToken();
}
// Consume the '>'.
@@ -1303,9 +1300,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
}
// Set the default visibility to private.
- if (Tok.is(tok::at)) { // parse objc-visibility-spec
- ConsumeToken(); // eat the @ sign
-
+ if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtVisibility(getCurScope());
return cutOffParsing();
@@ -1423,9 +1418,8 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
IdentifierInfo *protocolName = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken();
- if (Tok.is(tok::semi)) { // forward declaration of one protocol.
+ if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol.
IdentifierLocPair ProtoInfo(protocolName, nameLoc);
- ConsumeToken();
return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
attrs.getList());
}
@@ -1452,7 +1446,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
break;
}
// Consume the ';'.
- if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
+ if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol"))
return DeclGroupPtrTy();
return Actions.ActOnForwardProtocolDeclaration(AtLoc,
@@ -1558,9 +1552,8 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) {
// We have a class implementation
SourceLocation superClassLoc;
IdentifierInfo *superClassId = 0;
- if (Tok.is(tok::colon)) {
+ if (TryConsumeToken(tok::colon)) {
// We have a super class
- ConsumeToken();
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected)
<< tok::identifier; // missing super class name.
@@ -1673,8 +1666,7 @@ Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
}
IdentifierInfo *classId = Tok.getIdentifierInfo();
SourceLocation classLoc = ConsumeToken(); // consume class-name;
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- "@compatibility_alias");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias");
return Actions.ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc,
classId, classLoc);
}
@@ -1712,10 +1704,8 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
IdentifierInfo *propertyId = Tok.getIdentifierInfo();
SourceLocation propertyLoc = ConsumeToken(); // consume property name
SourceLocation propertyIvarLoc;
- if (Tok.is(tok::equal)) {
+ if (TryConsumeToken(tok::equal)) {
// property '=' ivar-name
- ConsumeToken(); // consume '='
-
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId);
cutOffParsing();
@@ -1735,7 +1725,7 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
break;
ConsumeToken(); // consume ','
}
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@synthesize");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "@synthesize");
return 0;
}
@@ -1772,7 +1762,7 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
break;
ConsumeToken(); // consume ','
}
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@dynamic");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "@dynamic");
return 0;
}
@@ -1790,7 +1780,7 @@ StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
}
}
// consume ';'
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@throw");
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "@throw");
return Actions.ActOnObjCAtThrowStmt(atLoc, Res.take(), getCurScope());
}
@@ -2485,8 +2475,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
KeyIdents.push_back(selIdent);
KeyLocs.push_back(Loc);
- if (Tok.isNot(tok::colon)) {
- Diag(Tok, diag::err_expected) << tok::colon;
+ if (ExpectAndConsume(tok::colon)) {
// We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
// the enclosing expression.
@@ -2494,7 +2483,6 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
return ExprError();
}
- ConsumeToken(); // Eat the ':'.
/// Parse the expression after ':'
if (Tok.is(tok::code_completion)) {
@@ -2761,8 +2749,7 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
}
}
- if (!TryConsumeToken(tok::colon)) {
- Diag(Tok, diag::err_expected) << tok::colon;
+ if (ExpectAndConsume(tok::colon)) {
SkipUntil(tok::r_brace, StopAtSemi);
return ExprError();
}
@@ -2787,10 +2774,8 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None
};
Elements.push_back(Element);
-
- if (Tok.is(tok::comma))
- ConsumeToken(); // Eat the ','.
- else if (Tok.isNot(tok::r_brace))
+
+ if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace))
return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_brace
<< tok::comma);
}
@@ -2880,14 +2865,13 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
unsigned nColons = 0;
if (Tok.isNot(tok::r_paren)) {
while (1) {
- if (Tok.is(tok::coloncolon)) { // Handle :: in C++.
+ if (TryConsumeToken(tok::coloncolon)) { // Handle :: in C++.
++nColons;
KeyIdents.push_back(0);
- } else if (Tok.isNot(tok::colon))
- return ExprError(Diag(Tok, diag::err_expected) << tok::colon);
-
+ } else if (ExpectAndConsume(tok::colon)) // Otherwise expect ':'.
+ return ExprError();
++nColons;
- ConsumeToken(); // Eat the ':' or '::'.
+
if (Tok.is(tok::r_paren))
break;
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 7f3be42fe6c..88d86056af1 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -449,7 +449,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
raii2(Ident___exception_code, false),
raii3(Ident_GetExceptionCode, false);
- if(ExpectAndConsume(tok::l_paren,diag::err_expected_lparen))
+ if (ExpectAndConsume(tok::l_paren))
return StmtError();
ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope);
@@ -470,7 +470,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
if(FilterExpr.isInvalid())
return StmtError();
- if(ExpectAndConsume(tok::r_paren,diag::err_expected_rparen))
+ if (ExpectAndConsume(tok::r_paren))
return StmtError();
StmtResult Block(ParseCompoundStatement());
@@ -543,7 +543,7 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) {
SubStmt = Actions.ProcessStmtAttributes(
SubStmt.get(), TempAttrs.getList(), TempAttrs.Range);
} else {
- Diag(Tok, diag::err_expected_semi_after) << "__attribute__";
+ Diag(Tok, diag::err_expected_after) << "__attribute__" << tok::semi;
}
}
@@ -2627,7 +2627,7 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
SourceLocation CatchLoc = ConsumeToken();
BalancedDelimiterTracker T(*this, tok::l_paren);
- if (T.expectAndConsume(diag::err_expected_lparen))
+ if (T.expectAndConsume())
return StmtError();
// C++ 3.3.2p3:
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 03325db8860..a5471f1294e 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -316,10 +316,8 @@ bool Parser::ParseTemplateParameters(unsigned Depth,
Tok.setKind(tok::greater);
RAngleLoc = Tok.getLocation();
Tok.setLocation(Tok.getLocation().getLocWithOffset(1));
- } else if (Tok.is(tok::greater))
- RAngleLoc = ConsumeToken();
- else if (Failed) {
- Diag(Tok.getLocation(), diag::err_expected_greater);
+ } else if (!TryConsumeToken(tok::greater, RAngleLoc) && Failed) {
+ Diag(Tok.getLocation(), diag::err_expected) << tok::greater;
return true;
}
return false;
@@ -675,7 +673,7 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
switch (Tok.getKind()) {
default:
- Diag(Tok.getLocation(), diag::err_expected_greater);
+ Diag(Tok.getLocation(), diag::err_expected) << tok::greater;
return true;
case tok::greater:
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index d1424899aec..a62d4c3d16a 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -152,14 +152,8 @@ static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) {
}
}
-/// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
-/// input. If so, it is consumed and false is returned.
-///
-/// If the input is malformed, this emits the specified diagnostic. Next, if
-/// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is
-/// returned.
bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
- const char *Msg, tok::TokenKind SkipToTok) {
+ const char *Msg) {
if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) {
ConsumeAnyToken();
return false;
@@ -168,29 +162,37 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
// Detect common single-character typos and resume.
if (IsCommonTypo(ExpectedTok, Tok)) {
SourceLocation Loc = Tok.getLocation();
- Diag(Loc, DiagID)
- << Msg
- << FixItHint::CreateReplacement(SourceRange(Loc),
- getTokenSimpleSpelling(ExpectedTok));
+ DiagnosticBuilder DB = Diag(Loc, DiagID);
+ DB << FixItHint::CreateReplacement(SourceRange(Loc),
+ getTokenSimpleSpelling(ExpectedTok));
+ if (DiagID == diag::err_expected)
+ DB << ExpectedTok;
+ else if (DiagID == diag::err_expected_after)
+ DB << Msg << ExpectedTok;
+ else
+ DB << Msg;
ConsumeAnyToken();
// Pretend there wasn't a problem.
return false;
}
- const char *Spelling = 0;
SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
- if (EndLoc.isValid() &&
- (Spelling = tok::getTokenSimpleSpelling(ExpectedTok))) {
- // Show what code to insert to fix this problem.
- Diag(EndLoc, DiagID)
- << Msg
- << FixItHint::CreateInsertion(EndLoc, Spelling);
- } else
- Diag(Tok, DiagID) << Msg;
+ const char *Spelling = 0;
+ if (EndLoc.isValid())
+ Spelling = tok::getTokenSimpleSpelling(ExpectedTok);
+
+ DiagnosticBuilder DB =
+ Spelling
+ ? Diag(EndLoc, DiagID) << FixItHint::CreateInsertion(EndLoc, Spelling)
+ : Diag(Tok, DiagID);
+ if (DiagID == diag::err_expected)
+ DB << ExpectedTok;
+ else if (DiagID == diag::err_expected_after)
+ DB << Msg << ExpectedTok;
+ else
+ DB << Msg;
- if (SkipToTok != tok::unknown)
- SkipUntil(SkipToTok, StopAtSemi);
return true;
}
@@ -725,7 +727,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
SourceLocation EndLoc;
ExprResult Result(ParseSimpleAsm(&EndLoc));
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
+ ExpectAndConsume(tok::semi, diag::err_expected_after,
"top-level asm block");
if (Result.isInvalid())
@@ -1127,28 +1129,22 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// safe because we're always the sole owner.
D.getMutableDeclSpec().abort();
- if (Tok.is(tok::equal)) {
+ if (TryConsumeToken(tok::equal)) {
assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='");
- ConsumeToken();
-
Actions.ActOnFinishFunctionBody(Res, 0, false);
bool Delete = false;
SourceLocation KWLoc;
- if (Tok.is(tok::kw_delete)) {
- Diag(Tok, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_deleted_function :
- diag::ext_deleted_function);
-
- KWLoc = ConsumeToken();
+ if (TryConsumeToken(tok::kw_delete, KWLoc)) {
+ Diag(KWLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_deleted_function
+ : diag::ext_deleted_function);
Actions.SetDeclDeleted(Res, KWLoc);
Delete = true;
- } else if (Tok.is(tok::kw_default)) {
- Diag(Tok, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_defaulted_function :
- diag::ext_defaulted_function);
-
- KWLoc = ConsumeToken();
+ } else if (TryConsumeToken(tok::kw_default, KWLoc)) {
+ Diag(KWLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_defaulted_function
+ : diag::ext_defaulted_function);
Actions.SetDeclDefaulted(Res, KWLoc);
} else {
llvm_unreachable("function definition after = not 'delete' or 'default'");
@@ -1158,9 +1154,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
Diag(KWLoc, diag::err_default_delete_in_multiple_declaration)
<< Delete;
SkipUntil(tok::semi);
- } else {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
- Delete ? "delete" : "default", tok::semi);
+ } else if (ExpectAndConsume(tok::semi, diag::err_expected_after,
+ Delete ? "delete" : "default")) {
+ SkipUntil(tok::semi);
}
return Res;
@@ -2033,12 +2029,15 @@ bool BalancedDelimiterTracker::diagnoseOverflow() {
}
bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID,
- const char *Msg,
- tok::TokenKind SkipToToc ) {
+ const char *Msg,
+ tok::TokenKind SkipToTok) {
LOpen = P.Tok.getLocation();
- if (P.ExpectAndConsume(Kind, DiagID, Msg, SkipToToc))
+ if (P.ExpectAndConsume(Kind, DiagID, Msg)) {
+ if (SkipToTok != tok::unknown)
+ P.SkipUntil(SkipToTok, Parser::StopAtSemi);
return true;
-
+ }
+
if (getDepth() < MaxDepth)
return false;
diff --git a/clang/lib/Parse/RAIIObjectsForParser.h b/clang/lib/Parse/RAIIObjectsForParser.h
index f68a2e09fe9..711dc2a7c4d 100644
--- a/clang/lib/Parse/RAIIObjectsForParser.h
+++ b/clang/lib/Parse/RAIIObjectsForParser.h
@@ -415,8 +415,8 @@ namespace clang {
return diagnoseOverflow();
}
-
- bool expectAndConsume(unsigned DiagID,
+
+ bool expectAndConsume(unsigned DiagID = diag::err_expected,
const char *Msg = "",
tok::TokenKind SkipToTok = tok::unknown);
bool consumeClose() {
OpenPOWER on IntegriCloud