mirror of https://github.com/microsoft/clang.git
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@198270 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f1c0e48372
commit
ca70f4fa1c
|
@ -40,7 +40,6 @@ def note_also_found : Note<"also found">;
|
|||
|
||||
let CategoryName = "Lexical or Preprocessor Issue" in {
|
||||
|
||||
def err_expected_colon : Error<"expected ':'">;
|
||||
def err_expected_colon_after_setter_name : Error<
|
||||
"method name referenced in property setter attribute "
|
||||
"must end with ':'">;
|
||||
|
|
|
@ -149,10 +149,6 @@ def err_expected_expression : Error<"expected expression">;
|
|||
def err_expected_type : Error<"expected a type">;
|
||||
def err_expected_external_declaration : Error<"expected external declaration">;
|
||||
def err_extraneous_closing_brace : Error<"extraneous closing brace ('}')">;
|
||||
def err_expected_lparen : Error<"expected '('">;
|
||||
def err_expected_rparen : Error<"expected ')'">;
|
||||
def err_expected_rsquare : Error<"expected ']'">;
|
||||
def err_expected_greater : Error<"expected '>'">;
|
||||
def err_expected_semi_declaration : Error<
|
||||
"expected ';' at end of declaration">;
|
||||
def err_expected_semi_decl_list : Error<
|
||||
|
@ -182,12 +178,10 @@ def err_invalid_token_after_declarator_suggest_equal : Error<
|
|||
def err_expected_statement : Error<"expected statement">;
|
||||
def err_expected_lparen_after : Error<"expected '(' after '%0'">;
|
||||
def err_expected_less_after : Error<"expected '<' after '%0'">;
|
||||
def err_expected_comma : Error<"expected ','">;
|
||||
def err_expected_lbrace_in_compound_literal : Error<
|
||||
"expected '{' in compound literal">;
|
||||
def err_expected_while : Error<"expected 'while' in do/while loop">;
|
||||
|
||||
def err_expected_semi_after : Error<"expected ';' after %0">;
|
||||
def err_expected_semi_after_stmt : Error<"expected ';' after %0 statement">;
|
||||
def err_expected_semi_after_expr : Error<"expected ';' after expression">;
|
||||
def err_extraneous_token_before_semi : Error<"extraneous '%0' before ';'">;
|
||||
|
@ -628,8 +622,6 @@ def err_expected_qualified_after_typename : Error<
|
|||
"expected a qualified name after 'typename'">;
|
||||
def warn_expected_qualified_after_typename : ExtWarn<
|
||||
"expected a qualified name after 'typename'">;
|
||||
def err_expected_semi_after_tagdecl : Error<
|
||||
"expected ';' after %0">;
|
||||
|
||||
def err_typename_refers_to_non_type_template : Error<
|
||||
"typename specifier refers to a non-type template">;
|
||||
|
|
|
@ -681,12 +681,14 @@ private:
|
|||
/// 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
|
||||
/// If a trivial punctuator misspelling is encountered, a FixIt error
|
||||
/// diagnostic is issued and false is returned after recovery.
|
||||
///
|
||||
/// If the input is malformed, this emits the specified diagnostic and true is
|
||||
/// returned.
|
||||
bool ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned Diag,
|
||||
const char *DiagMsg = "",
|
||||
tok::TokenKind SkipToTok = tok::unknown);
|
||||
bool ExpectAndConsume(tok::TokenKind ExpectedTok,
|
||||
unsigned Diag = diag::err_expected,
|
||||
const char *DiagMsg = "");
|
||||
|
||||
/// \brief The parser expects a semicolon and, if present, will consume it.
|
||||
///
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue