/// This does not work with all kinds of tokens: strings and specific other
/// tokens must be consumed with custom methods below. This returns the
/// location of the consumed token.
- SourceLocation ConsumeToken(bool ConsumeCodeCompletionTok = false) {
- assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() &&
- !isTokenBrace() &&
+ SourceLocation ConsumeToken() {
+ assert(!isTokenSpecial() &&
"Should consume special tokens with Consume*Token");
- if (!ConsumeCodeCompletionTok && Tok.is(tok::code_completion))
+ if (LLVM_UNLIKELY(Tok.is(tok::code_completion)))
return handleUnexpectedCodeCompletionToken();
PrevTokLocation = Tok.getLocation();
return PrevTokLocation;
}
+ bool TryConsumeToken(tok::TokenKind Expected) {
+ if (Tok.isNot(Expected))
+ return false;
+ assert(!isTokenSpecial() &&
+ "Should consume special tokens with Consume*Token");
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return true;
+ }
+
+ bool TryConsumeToken(tok::TokenKind Expected, SourceLocation &Loc) {
+ if (!TryConsumeToken(Expected))
+ return false;
+ Loc = PrevTokLocation;
+ return true;
+ }
+
private:
//===--------------------------------------------------------------------===//
// Low-Level token peeking and consumption methods.
bool isTokenBrace() const {
return Tok.getKind() == tok::l_brace || Tok.getKind() == tok::r_brace;
}
-
/// isTokenStringLiteral - True if this token is a string-literal.
- ///
bool isTokenStringLiteral() const {
return tok::isStringLiteral(Tok.getKind());
}
+ /// isTokenSpecial - True if this token requires special consumption methods.
+ bool isTokenSpecial() const {
+ return isTokenStringLiteral() || isTokenParen() || isTokenBracket() ||
+ isTokenBrace();
+ }
/// \brief Returns true if the current token is '=' or is a type of '='.
/// For typos, give a fixit to '='
return ConsumeBrace();
else if (isTokenStringLiteral())
return ConsumeStringToken();
+ else if (ConsumeCodeCompletionTok && Tok.is(tok::code_completion))
+ return ConsumeCodeCompletionToken();
else
- return ConsumeToken(ConsumeCodeCompletionTok);
+ return ConsumeToken();
}
/// ConsumeParen - This consume method keeps the paren count up-to-date.
D.complete(FnD);
- if (Tok.is(tok::equal)) {
- ConsumeToken();
-
+ if (TryConsumeToken(tok::equal)) {
if (!FnD) {
SkipUntil(tok::semi);
return 0;
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(FnD, 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(FnD, KWLoc);
} else {
llvm_unreachable("function definition after = not 'delete' or 'default'");
if (DefArgResult.isInvalid())
Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
else {
- if (Tok.is(tok::cxx_defaultarg_end))
- ConsumeToken();
- else {
+ if (!TryConsumeToken(tok::cxx_defaultarg_end)) {
// The last two tokens are the terminator and the saved value of
// Tok; the last token in the default argument is the one before
// those.
ExpectAndConsume(tok::r_paren, diag::err_expected_rparen);
}
- if (Tok.is(tok::semi)) {
- ConsumeToken();
- } else if (Tok.is(tok::r_brace)) {
+ if (TryConsumeToken(tok::semi))
+ continue;
+
+ if (Tok.is(tok::r_brace)) {
ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list);
break;
- } else {
- ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
- // Skip to end of block or statement to avoid ext-warning on extra ';'.
- SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
- // If we stopped at a ';', eat it.
- if (Tok.is(tok::semi)) ConsumeToken();
}
+
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
+ // Skip to end of block or statement to avoid ext-warning on extra ';'.
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
+ // If we stopped at a ';', eat it.
+ TryConsumeToken(tok::semi);
}
T.consumeClose();
ExprResult AssignedVal;
ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
+ if (TryConsumeToken(tok::equal, EqualLoc)) {
AssignedVal = ParseConstantExpression();
if (AssignedVal.isInvalid())
SkipUntil(tok::comma, tok::r_brace, StopAtSemi | StopBeforeMatch);
continue;
}
- if (Tok.isNot(tok::comma))
+ SourceLocation CommaLoc;
+ if (!TryConsumeToken(tok::comma, CommaLoc))
break;
- SourceLocation CommaLoc = ConsumeToken();
if (Tok.isNot(tok::identifier)) {
if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11)
// Maintain an efficient lookup of params we have seen so far.
llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
- while (1) {
+ do {
// If this isn't an identifier, report the error and skip until ')'.
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
// Eat the identifier.
ConsumeToken();
-
// The list continues if we see a comma.
- if (Tok.isNot(tok::comma))
- break;
- ConsumeToken();
- }
+ } while (TryConsumeToken(tok::comma));
}
/// ParseParameterDeclarationClause - Parse a (possibly empty) parameter-list
ParsedAttributes &FirstArgAttrs,
SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
SourceLocation &EllipsisLoc) {
- while (1) {
- if (Tok.is(tok::ellipsis)) {
- // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
- // before deciding this was a parameter-declaration-clause.
- EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
+ do {
+ // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
+ // before deciding this was a parameter-declaration-clause.
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
break;
- }
// Parse the declaration-specifiers.
// Just use the ParsingDeclaration "scope" of the declarator.
Param, DefArgToks));
}
- // If the next token is a comma, consume it and keep reading arguments.
- if (Tok.isNot(tok::comma)) {
- if (Tok.is(tok::ellipsis)) {
- EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
-
- if (!getLangOpts().CPlusPlus) {
- // We have ellipsis without a preceding ',', which is ill-formed
- // in C. Complain and provide the fix.
- Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
- << FixItHint::CreateInsertion(EllipsisLoc, ", ");
- }
- }
-
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc) &&
+ !getLangOpts().CPlusPlus) {
+ // We have ellipsis without a preceding ',', which is ill-formed
+ // in C. Complain and provide the fix.
+ Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
+ << FixItHint::CreateInsertion(EllipsisLoc, ", ");
break;
}
- // Consume the comma.
- ConsumeToken();
- }
-
+ // If the next token is a comma, consume it and keep reading arguments.
+ } while (TryConsumeToken(tok::comma));
}
/// [C90] direct-declarator '[' constant-expression[opt] ']'
// If valid, this location is the position where we read the 'static' keyword.
SourceLocation StaticLoc;
- if (Tok.is(tok::kw_static))
- StaticLoc = ConsumeToken();
+ TryConsumeToken(tok::kw_static, StaticLoc);
// If there is a type-qualifier-list, read it now.
// Type qualifiers in an array subscript are a C99 feature.
// If we haven't already read 'static', check to see if there is one after the
// type-qualifier-list.
- if (!StaticLoc.isValid() && Tok.is(tok::kw_static))
- StaticLoc = ConsumeToken();
+ if (!StaticLoc.isValid())
+ TryConsumeToken(tok::kw_static, StaticLoc);
// Handle "direct-declarator [ type-qual-list[opt] * ]".
bool isStar = false;
Diag(Tok, diag::ext_gnu_conditional_expr);
}
- if (Tok.is(tok::colon)) {
- // Eat the colon.
- ColonLoc = ConsumeToken();
- } else {
+ if (!TryConsumeToken(tok::colon, ColonLoc)) {
// Otherwise, we're missing a ':'. Assume that this was a typo that
// the user forgot. If we're not in a macro expansion, we can suggest
// a fixit hint. If there were two spaces before the current token,
LHS = ExprError();
}
- SourceLocation CloseLoc = Tok.getLocation();
- if (Tok.is(tok::greatergreatergreater)) {
- ConsumeToken();
+ SourceLocation CloseLoc;
+ if (TryConsumeToken(tok::greatergreatergreater, CloseLoc)) {
} else if (LHS.isInvalid()) {
SkipUntil(tok::greatergreatergreater, StopAtSemi);
} else {
SourceLocation DefaultLoc;
TypeVector Types;
ExprVector Exprs;
- while (1) {
+ do {
ParsedType Ty;
if (Tok.is(tok::kw_default)) {
// C11 6.5.1.1p2 "A generic selection shall have no more than one default
return ExprError();
}
Exprs.push_back(ER.release());
-
- if (Tok.isNot(tok::comma))
- break;
- ConsumeToken();
- }
+ } while (TryConsumeToken(tok::comma));
T.consumeClose();
if (T.getCloseLocation().isInvalid())
DeclSpec DS(AttrFactory);
SourceLocation DeclLoc = Tok.getLocation();
SourceLocation EndLoc = ParseDecltypeSpecifier(DS);
- if (Tok.isNot(tok::coloncolon)) {
+
+ SourceLocation CCLoc;
+ if (!TryConsumeToken(tok::coloncolon, CCLoc)) {
AnnotateExistingDecltypeSpecifier(DS, DeclLoc, EndLoc);
return false;
}
-
- SourceLocation CCLoc = ConsumeToken();
+
if (Actions.ActOnCXXNestedNameSpecifierDecltype(SS, DS, CCLoc))
SS.SetInvalid(SourceRange(DeclLoc, CCLoc));
// to save the necessary state, and restore it later.
EnterExpressionEvaluationContext EC(Actions,
Sema::PotentiallyEvaluated);
- if (Tok.is(tok::equal))
- ConsumeToken();
+ TryConsumeToken(tok::equal);
if (!SkippedInits)
Init = ParseInitializer();
ConsumeToken();
}
}
- } else if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
+ } else
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
}
// If this is an init capture, process the initialization expression
// right away. For lambda init-captures such as the following:
// Add this type to the list of arguments.
Args.push_back(Ty.get());
-
- if (Tok.is(tok::comma)) {
- ConsumeToken();
- continue;
- }
-
- break;
- } while (true);
-
+ } while (TryConsumeToken(tok::comma));
+
if (Parens.consumeClose())
return ExprError();
do {
// Consume the 'export', if any.
SourceLocation ExportLoc;
- if (Tok.is(tok::kw_export)) {
- ExportLoc = ConsumeToken();
- }
+ TryConsumeToken(tok::kw_export, ExportLoc);
// Consume the 'template', which should be here.
SourceLocation TemplateLoc;
- if (Tok.is(tok::kw_template)) {
- TemplateLoc = ConsumeToken();
- } else {
+ if (!TryConsumeToken(tok::kw_template, TemplateLoc)) {
Diag(Tok.getLocation(), diag::err_expected_template);
return 0;
}
TemplateParams, LAngleLoc, RAngleLoc)) {
// Skip until the semi-colon or a }.
SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
- if (Tok.is(tok::semi))
- ConsumeToken();
+ TryConsumeToken(tok::semi);
return 0;
}
SourceLocation &LAngleLoc,
SourceLocation &RAngleLoc) {
// Get the template parameter list.
- if (!Tok.is(tok::less)) {
+ if (!TryConsumeToken(tok::less, LAngleLoc)) {
Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
return true;
}
- LAngleLoc = ConsumeToken();
// Try to parse the template parameter list.
bool Failed = false;
// Grab the ellipsis (if given).
bool Ellipsis = false;
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis)) {
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {
Ellipsis = true;
- EllipsisLoc = ConsumeToken();
-
Diag(EllipsisLoc,
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
// we introduce the type parameter into the local scope.
SourceLocation EqualLoc;
ParsedType DefaultArg;
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
+ if (TryConsumeToken(tok::equal, EqualLoc))
DefaultArg = ParseTypeName(/*Range=*/0,
Declarator::TemplateTypeArgContext).get();
- }
return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, Ellipsis,
EllipsisLoc, KeyLoc, ParamName, NameLoc,
// identifier, comma, or greater. Provide a fixit if the identifier, comma,
// or greater appear immediately or after 'typename' or 'struct'. In the
// latter case, replace the keyword with 'class'.
- if (!Tok.is(tok::kw_class)) {
+ if (!TryConsumeToken(tok::kw_class)) {
bool Replace = Tok.is(tok::kw_typename) || Tok.is(tok::kw_struct);
const Token& Next = Replace ? NextToken() : Tok;
if (Next.is(tok::identifier) || Next.is(tok::comma) ||
if (Replace)
ConsumeToken();
- } else
- ConsumeToken();
+ }
// Parse the ellipsis, if given.
SourceLocation EllipsisLoc;
- if (Tok.is(tok::ellipsis)) {
- EllipsisLoc = ConsumeToken();
-
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
Diag(EllipsisLoc,
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
: diag::ext_variadic_templates);
- }
// Get the identifier, if given.
SourceLocation NameLoc;
// we introduce the template parameter into the local scope.
SourceLocation EqualLoc;
ParsedTemplateArgument DefaultArg;
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
+ if (TryConsumeToken(tok::equal, EqualLoc)) {
DefaultArg = ParseTemplateTemplateArgument();
if (DefaultArg.isInvalid()) {
Diag(Tok.getLocation(),
// we introduce the template parameter into the local scope.
SourceLocation EqualLoc;
ExprResult DefaultArg;
- if (Tok.is(tok::equal)) {
- EqualLoc = ConsumeToken();
-
+ if (TryConsumeToken(tok::equal, EqualLoc)) {
// C++ [temp.param]p15:
// When parsing a default template-argument for a non-type
// template-parameter, the first non-nested > is taken as the
if (Invalid) {
// If we failed to parse the template ID but skipped ahead to a >, we're not
// going to be able to form a token annotation. Eat the '>' if present.
- if (Tok.is(tok::greater))
- ConsumeToken();
+ TryConsumeToken(tok::greater);
return true;
}
if (Type.isInvalid()) {
// If we failed to parse the template ID but skipped ahead to a >, we're not
// going to be able to form a token annotation. Eat the '>' if present.
- if (Tok.is(tok::greater))
- ConsumeToken();
+ TryConsumeToken(tok::greater);
return true;
}
UnqualifiedId Name;
Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken(); // the identifier
-
- // Parse the ellipsis.
- if (Tok.is(tok::ellipsis))
- EllipsisLoc = ConsumeToken();
+
+ TryConsumeToken(tok::ellipsis, EllipsisLoc);
if (isEndOfTemplateArgument(Tok)) {
bool MemberOfUnknownSpecialization;
}
// '<'
- if (!Tok.is(tok::less))
+ if (!TryConsumeToken(tok::less))
return false;
- ConsumeToken();
// An empty template argument list.
if (Tok.is(tok::greater))
// Template argument lists are constant-evaluation contexts.
EnterExpressionEvaluationContext EvalContext(Actions,Sema::ConstantEvaluated);
- while (true) {
+ do {
ParsedTemplateArgument Arg = ParseTemplateArgument();
- if (Tok.is(tok::ellipsis)) {
- SourceLocation EllipsisLoc = ConsumeToken();
+ SourceLocation EllipsisLoc;
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc);
- }
if (Arg.isInvalid()) {
SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);
// If the next token is a comma, consume it and keep reading
// arguments.
- if (Tok.isNot(tok::comma)) break;
-
- // Consume the comma.
- ConsumeToken();
- }
+ } while (TryConsumeToken(tok::comma));
return false;
}