Replace a fake enum class with the real thing.

llvm-svn: 208943
This commit is contained in:
Richard Smith 2014-05-16 01:56:53 +00:00
parent 218f71e148
commit ee390436b9
5 changed files with 196 additions and 213 deletions

View File

@ -1792,7 +1792,7 @@ private:
/// cast. Return false if it's no a decl-specifier, or we're not sure. /// cast. Return false if it's no a decl-specifier, or we're not sure.
bool isKnownToBeDeclarationSpecifier() { bool isKnownToBeDeclarationSpecifier() {
if (getLangOpts().CPlusPlus) if (getLangOpts().CPlusPlus)
return isCXXDeclarationSpecifier() == TPResult::True(); return isCXXDeclarationSpecifier() == TPResult::True;
return isDeclarationSpecifier(true); return isDeclarationSpecifier(true);
} }
@ -1892,25 +1892,8 @@ private:
/// TPResult - Used as the result value for functions whose purpose is to /// TPResult - Used as the result value for functions whose purpose is to
/// disambiguate C++ constructs by "tentatively parsing" them. /// disambiguate C++ constructs by "tentatively parsing" them.
/// This is a class instead of a simple enum because the implicit enum-to-bool enum class TPResult {
/// conversions may cause subtle bugs. True, False, Ambiguous, Error
class TPResult {
enum Result {
TPR_true,
TPR_false,
TPR_ambiguous,
TPR_error
};
Result Res;
TPResult(Result result) : Res(result) {}
public:
static TPResult True() { return TPR_true; }
static TPResult False() { return TPR_false; }
static TPResult Ambiguous() { return TPR_ambiguous; }
static TPResult Error() { return TPR_error; }
bool operator==(const TPResult &RHS) const { return Res == RHS.Res; }
bool operator!=(const TPResult &RHS) const { return Res != RHS.Res; }
}; };
/// \brief Based only on the given token kind, determine whether we know that /// \brief Based only on the given token kind, determine whether we know that
@ -1925,15 +1908,15 @@ private:
/// tell. /// tell.
TPResult isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind); TPResult isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind);
/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a /// isCXXDeclarationSpecifier - Returns TPResult::True if it is a
/// declaration specifier, TPResult::False() if it is not, /// declaration specifier, TPResult::False if it is not,
/// TPResult::Ambiguous() if it could be either a decl-specifier or a /// TPResult::Ambiguous if it could be either a decl-specifier or a
/// function-style cast, and TPResult::Error() if a parsing error was /// function-style cast, and TPResult::Error if a parsing error was
/// encountered. If it could be a braced C++11 function-style cast, returns /// encountered. If it could be a braced C++11 function-style cast, returns
/// BracedCastResult. /// BracedCastResult.
/// Doesn't consume tokens. /// Doesn't consume tokens.
TPResult TPResult
isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False(), isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False,
bool *HasMissingTypename = nullptr); bool *HasMissingTypename = nullptr);
/// Given that isCXXDeclarationSpecifier returns \c TPResult::True or /// Given that isCXXDeclarationSpecifier returns \c TPResult::True or
@ -1947,9 +1930,9 @@ private:
bool isTentativelyDeclared(IdentifierInfo *II); bool isTentativelyDeclared(IdentifierInfo *II);
// "Tentative parsing" functions, used for disambiguation. If a parsing error // "Tentative parsing" functions, used for disambiguation. If a parsing error
// is encountered they will return TPResult::Error(). // is encountered they will return TPResult::Error.
// Returning TPResult::True()/False() indicates that the ambiguity was // Returning TPResult::True/False indicates that the ambiguity was
// resolved and tentative parsing may stop. TPResult::Ambiguous() indicates // resolved and tentative parsing may stop. TPResult::Ambiguous indicates
// that more tentative parsing is necessary for disambiguation. // that more tentative parsing is necessary for disambiguation.
// They all consume tokens, so backtracking should be used after calling them. // They all consume tokens, so backtracking should be used after calling them.

View File

@ -923,15 +923,15 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks,
? tok::semi : tok::r_paren); ? tok::semi : tok::r_paren);
Sema::TentativeAnalysisScope Scope(Actions); Sema::TentativeAnalysisScope Scope(Actions);
TPResult Result = TPResult::Error(); TPResult Result = TPResult::Error;
ConsumeToken(); ConsumeToken();
switch (CIK) { switch (CIK) {
case CIK_DefaultInitializer: case CIK_DefaultInitializer:
Result = TryParseInitDeclaratorList(); Result = TryParseInitDeclaratorList();
// If we parsed a complete, ambiguous init-declarator-list, this // If we parsed a complete, ambiguous init-declarator-list, this
// is only syntactically-valid if it's followed by a semicolon. // is only syntactically-valid if it's followed by a semicolon.
if (Result == TPResult::Ambiguous() && Tok.isNot(tok::semi)) if (Result == TPResult::Ambiguous && Tok.isNot(tok::semi))
Result = TPResult::False(); Result = TPResult::False;
break; break;
case CIK_DefaultArgument: case CIK_DefaultArgument:
@ -940,13 +940,13 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks,
&InvalidAsDeclaration, /*VersusTemplateArgument*/true); &InvalidAsDeclaration, /*VersusTemplateArgument*/true);
// If this is an expression or a declaration with a missing // If this is an expression or a declaration with a missing
// 'typename', assume it's not a declaration. // 'typename', assume it's not a declaration.
if (Result == TPResult::Ambiguous() && InvalidAsDeclaration) if (Result == TPResult::Ambiguous && InvalidAsDeclaration)
Result = TPResult::False(); Result = TPResult::False;
break; break;
} }
// If what follows could be a declaration, it is a declaration. // If what follows could be a declaration, it is a declaration.
if (Result != TPResult::False() && Result != TPResult::Error()) { if (Result != TPResult::False && Result != TPResult::Error) {
PA.Revert(); PA.Revert();
return true; return true;
} }

View File

@ -2129,7 +2129,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
TPResult TPR = TryParseDeclarator(/*mayBeAbstract*/false); TPResult TPR = TryParseDeclarator(/*mayBeAbstract*/false);
PA.Revert(); PA.Revert();
if (TPR != TPResult::False()) { if (TPR != TPResult::False) {
// The identifier is followed by a parenthesized declarator. // The identifier is followed by a parenthesized declarator.
// It's supposed to be a type. // It's supposed to be a type.
break; break;
@ -3563,13 +3563,13 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
TPResult TPR = isExpressionOrTypeSpecifierSimple(NextToken().getKind()); TPResult TPR = isExpressionOrTypeSpecifierSimple(NextToken().getKind());
// If the next token starts an expression, we know we're parsing a // If the next token starts an expression, we know we're parsing a
// bit-field. This is the common case. // bit-field. This is the common case.
if (TPR == TPResult::True()) if (TPR == TPResult::True)
PossibleBitfield = true; PossibleBitfield = true;
// If the next token starts a type-specifier-seq, it may be either a // If the next token starts a type-specifier-seq, it may be either a
// a fixed underlying type or the start of a function-style cast in C++; // a fixed underlying type or the start of a function-style cast in C++;
// lookahead one more token to see if it's obvious that we have a // lookahead one more token to see if it's obvious that we have a
// fixed underlying type. // fixed underlying type.
else if (TPR == TPResult::False() && else if (TPR == TPResult::False &&
GetLookAheadToken(2).getKind() == tok::semi) { GetLookAheadToken(2).getKind() == tok::semi) {
// Consume the ':'. // Consume the ':'.
ConsumeToken(); ConsumeToken();
@ -3589,7 +3589,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// FIXME: The standard is not entirely clear on how to disambiguate in // FIXME: The standard is not entirely clear on how to disambiguate in
// this case. // this case.
if ((getLangOpts().CPlusPlus && if ((getLangOpts().CPlusPlus &&
isCXXDeclarationSpecifier(TPResult::True()) != TPResult::True()) || isCXXDeclarationSpecifier(TPResult::True) != TPResult::True) ||
(!getLangOpts().CPlusPlus && !isDeclarationSpecifier(true))) { (!getLangOpts().CPlusPlus && !isDeclarationSpecifier(true))) {
// We'll parse this as a bitfield later. // We'll parse this as a bitfield later.
PossibleBitfield = true; PossibleBitfield = true;

View File

@ -1144,7 +1144,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) {
return true; return true;
// See whether we have declaration specifiers, which indicate a type. // See whether we have declaration specifiers, which indicate a type.
while (isCXXDeclarationSpecifier() == TPResult::True()) while (isCXXDeclarationSpecifier() == TPResult::True)
ConsumeToken(); ConsumeToken();
// If we have a '>' or a ',' then this is a template argument list. // If we have a '>' or a ',' then this is a template argument list.

View File

@ -101,15 +101,15 @@ bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
// an ambiguity if the first decl-specifier is // an ambiguity if the first decl-specifier is
// simple-type-specifier/typename-specifier followed by a '(', which may // simple-type-specifier/typename-specifier followed by a '(', which may
// indicate a function-style cast expression. // indicate a function-style cast expression.
// isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such // isCXXDeclarationSpecifier will return TPResult::Ambiguous only in such
// a case. // a case.
bool InvalidAsDeclaration = false; bool InvalidAsDeclaration = false;
TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(), TPResult TPR = isCXXDeclarationSpecifier(TPResult::False,
&InvalidAsDeclaration); &InvalidAsDeclaration);
if (TPR != TPResult::Ambiguous()) if (TPR != TPResult::Ambiguous)
return TPR != TPResult::False(); // Returns true for TPResult::True() or return TPR != TPResult::False; // Returns true for TPResult::True or
// TPResult::Error(). // TPResult::Error.
// FIXME: TryParseSimpleDeclaration doesn't look past the first initializer, // FIXME: TryParseSimpleDeclaration doesn't look past the first initializer,
// and so gets some cases wrong. We can't carry on if we've already seen // and so gets some cases wrong. We can't carry on if we've already seen
@ -131,15 +131,15 @@ bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
PA.Revert(); PA.Revert();
// In case of an error, let the declaration parsing code handle it. // In case of an error, let the declaration parsing code handle it.
if (TPR == TPResult::Error()) if (TPR == TPResult::Error)
return true; return true;
// Declarations take precedence over expressions. // Declarations take precedence over expressions.
if (TPR == TPResult::Ambiguous()) if (TPR == TPResult::Ambiguous)
TPR = TPResult::True(); TPR = TPResult::True;
assert(TPR == TPResult::True() || TPR == TPResult::False()); assert(TPR == TPResult::True || TPR == TPResult::False);
return TPR == TPResult::True(); return TPR == TPResult::True;
} }
/// Try to consume a token sequence that we've already identified as /// Try to consume a token sequence that we've already identified as
@ -157,10 +157,10 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
case tok::kw___underlying_type: { case tok::kw___underlying_type: {
ConsumeToken(); ConsumeToken();
if (Tok.isNot(tok::l_paren)) if (Tok.isNot(tok::l_paren))
return TPResult::Error(); return TPResult::Error;
ConsumeParen(); ConsumeParen();
if (!SkipUntil(tok::r_paren)) if (!SkipUntil(tok::r_paren))
return TPResult::Error(); return TPResult::Error;
break; break;
} }
@ -184,23 +184,23 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
if (Tok.is(tok::l_square)) { if (Tok.is(tok::l_square)) {
ConsumeBracket(); ConsumeBracket();
if (!SkipUntil(tok::r_square)) if (!SkipUntil(tok::r_square))
return TPResult::Error(); return TPResult::Error;
} else { } else {
ConsumeToken(); ConsumeToken();
if (Tok.isNot(tok::l_paren)) if (Tok.isNot(tok::l_paren))
return TPResult::Error(); return TPResult::Error;
ConsumeParen(); ConsumeParen();
if (!SkipUntil(tok::r_paren)) if (!SkipUntil(tok::r_paren))
return TPResult::Error(); return TPResult::Error;
} }
} }
if (TryAnnotateCXXScopeToken()) if (TryAnnotateCXXScopeToken())
return TPResult::Error(); return TPResult::Error;
if (Tok.is(tok::annot_cxxscope)) if (Tok.is(tok::annot_cxxscope))
ConsumeToken(); ConsumeToken();
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
return TPResult::Error(); return TPResult::Error;
ConsumeToken(); ConsumeToken();
break; break;
@ -215,7 +215,7 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
break; break;
} }
return TPResult::Ambiguous(); return TPResult::Ambiguous;
} }
/// simple-declaration: /// simple-declaration:
@ -227,29 +227,29 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
/// attribute-specifier-seqopt type-specifier-seq declarator /// attribute-specifier-seqopt type-specifier-seq declarator
/// ///
Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) { Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
if (TryConsumeDeclarationSpecifier() == TPResult::Error()) if (TryConsumeDeclarationSpecifier() == TPResult::Error)
return TPResult::Error(); return TPResult::Error;
// Two decl-specifiers in a row conclusively disambiguate this as being a // Two decl-specifiers in a row conclusively disambiguate this as being a
// simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the // simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the
// overwhelmingly common case that the next token is a '('. // overwhelmingly common case that the next token is a '('.
if (Tok.isNot(tok::l_paren)) { if (Tok.isNot(tok::l_paren)) {
TPResult TPR = isCXXDeclarationSpecifier(); TPResult TPR = isCXXDeclarationSpecifier();
if (TPR == TPResult::Ambiguous()) if (TPR == TPResult::Ambiguous)
return TPResult::True(); return TPResult::True;
if (TPR == TPResult::True() || TPR == TPResult::Error()) if (TPR == TPResult::True || TPR == TPResult::Error)
return TPR; return TPR;
assert(TPR == TPResult::False()); assert(TPR == TPResult::False);
} }
TPResult TPR = TryParseInitDeclaratorList(); TPResult TPR = TryParseInitDeclaratorList();
if (TPR != TPResult::Ambiguous()) if (TPR != TPResult::Ambiguous)
return TPR; return TPR;
if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon))) if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon)))
return TPResult::False(); return TPResult::False;
return TPResult::Ambiguous(); return TPResult::Ambiguous;
} }
/// Tentatively parse an init-declarator-list in order to disambiguate it from /// Tentatively parse an init-declarator-list in order to disambiguate it from
@ -283,23 +283,23 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() {
while (1) { while (1) {
// declarator // declarator
TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/); TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
if (TPR != TPResult::Ambiguous()) if (TPR != TPResult::Ambiguous)
return TPR; return TPR;
// [GNU] simple-asm-expr[opt] attributes[opt] // [GNU] simple-asm-expr[opt] attributes[opt]
if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
return TPResult::True(); return TPResult::True;
// initializer[opt] // initializer[opt]
if (Tok.is(tok::l_paren)) { if (Tok.is(tok::l_paren)) {
// Parse through the parens. // Parse through the parens.
ConsumeParen(); ConsumeParen();
if (!SkipUntil(tok::r_paren, StopAtSemi)) if (!SkipUntil(tok::r_paren, StopAtSemi))
return TPResult::Error(); return TPResult::Error;
} else if (Tok.is(tok::l_brace)) { } else if (Tok.is(tok::l_brace)) {
// A left-brace here is sufficient to disambiguate the parse; an // A left-brace here is sufficient to disambiguate the parse; an
// expression can never be followed directly by a braced-init-list. // expression can never be followed directly by a braced-init-list.
return TPResult::True(); return TPResult::True;
} else if (Tok.is(tok::equal) || isTokIdentifier_in()) { } else if (Tok.is(tok::equal) || isTokIdentifier_in()) {
// MSVC and g++ won't examine the rest of declarators if '=' is // MSVC and g++ won't examine the rest of declarators if '=' is
// encountered; they just conclude that we have a declaration. // encountered; they just conclude that we have a declaration.
@ -317,14 +317,14 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() {
// in any other context 'in' is invalid after a declaration and parser // in any other context 'in' is invalid after a declaration and parser
// issues the error regardless of outcome of this decision. // issues the error regardless of outcome of this decision.
// FIXME: Change if above assumption does not hold. // FIXME: Change if above assumption does not hold.
return TPResult::True(); return TPResult::True;
} }
if (!TryConsumeToken(tok::comma)) if (!TryConsumeToken(tok::comma))
break; break;
} }
return TPResult::Ambiguous(); return TPResult::Ambiguous;
} }
/// isCXXConditionDeclaration - Disambiguates between a declaration or an /// isCXXConditionDeclaration - Disambiguates between a declaration or an
@ -342,9 +342,9 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() {
/// ///
bool Parser::isCXXConditionDeclaration() { bool Parser::isCXXConditionDeclaration() {
TPResult TPR = isCXXDeclarationSpecifier(); TPResult TPR = isCXXDeclarationSpecifier();
if (TPR != TPResult::Ambiguous()) if (TPR != TPResult::Ambiguous)
return TPR != TPResult::False(); // Returns true for TPResult::True() or return TPR != TPResult::False; // Returns true for TPResult::True or
// TPResult::Error(). // TPResult::Error.
// FIXME: Add statistics about the number of ambiguous statements encountered // FIXME: Add statistics about the number of ambiguous statements encountered
// and how they were resolved (number of declarations+number of expressions). // and how they were resolved (number of declarations+number of expressions).
@ -362,25 +362,25 @@ bool Parser::isCXXConditionDeclaration() {
TPR = TryParseDeclarator(false/*mayBeAbstract*/); TPR = TryParseDeclarator(false/*mayBeAbstract*/);
// In case of an error, let the declaration parsing code handle it. // In case of an error, let the declaration parsing code handle it.
if (TPR == TPResult::Error()) if (TPR == TPResult::Error)
TPR = TPResult::True(); TPR = TPResult::True;
if (TPR == TPResult::Ambiguous()) { if (TPR == TPResult::Ambiguous) {
// '=' // '='
// [GNU] simple-asm-expr[opt] attributes[opt] // [GNU] simple-asm-expr[opt] attributes[opt]
if (Tok.is(tok::equal) || if (Tok.is(tok::equal) ||
Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
TPR = TPResult::True(); TPR = TPResult::True;
else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))
TPR = TPResult::True(); TPR = TPResult::True;
else else
TPR = TPResult::False(); TPR = TPResult::False;
} }
PA.Revert(); PA.Revert();
assert(TPR == TPResult::True() || TPR == TPResult::False()); assert(TPR == TPResult::True || TPR == TPResult::False);
return TPR == TPResult::True(); return TPR == TPResult::True;
} }
/// \brief Determine whether the next set of tokens contains a type-id. /// \brief Determine whether the next set of tokens contains a type-id.
@ -412,9 +412,9 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
// in its syntactic context shall be considered a type-id. // in its syntactic context shall be considered a type-id.
TPResult TPR = isCXXDeclarationSpecifier(); TPResult TPR = isCXXDeclarationSpecifier();
if (TPR != TPResult::Ambiguous()) if (TPR != TPResult::Ambiguous)
return TPR != TPResult::False(); // Returns true for TPResult::True() or return TPR != TPResult::False; // Returns true for TPResult::True or
// TPResult::Error(). // TPResult::Error.
// FIXME: Add statistics about the number of ambiguous statements encountered // FIXME: Add statistics about the number of ambiguous statements encountered
// and how they were resolved (number of declarations+number of expressions). // and how they were resolved (number of declarations+number of expressions).
@ -432,14 +432,14 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/); TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
// In case of an error, let the declaration parsing code handle it. // In case of an error, let the declaration parsing code handle it.
if (TPR == TPResult::Error()) if (TPR == TPResult::Error)
TPR = TPResult::True(); TPR = TPResult::True;
if (TPR == TPResult::Ambiguous()) { if (TPR == TPResult::Ambiguous) {
// We are supposed to be inside parens, so if after the abstract declarator // We are supposed to be inside parens, so if after the abstract declarator
// we encounter a ')' this is a type-id, otherwise it's an expression. // we encounter a ')' this is a type-id, otherwise it's an expression.
if (Context == TypeIdInParens && Tok.is(tok::r_paren)) { if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {
TPR = TPResult::True(); TPR = TPResult::True;
isAmbiguous = true; isAmbiguous = true;
// We are supposed to be inside a template argument, so if after // We are supposed to be inside a template argument, so if after
@ -448,17 +448,17 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
} else if (Context == TypeIdAsTemplateArgument && } else if (Context == TypeIdAsTemplateArgument &&
(Tok.is(tok::greater) || Tok.is(tok::comma) || (Tok.is(tok::greater) || Tok.is(tok::comma) ||
(getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)))) { (getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)))) {
TPR = TPResult::True(); TPR = TPResult::True;
isAmbiguous = true; isAmbiguous = true;
} else } else
TPR = TPResult::False(); TPR = TPResult::False;
} }
PA.Revert(); PA.Revert();
assert(TPR == TPResult::True() || TPR == TPResult::False()); assert(TPR == TPResult::True || TPR == TPResult::False);
return TPR == TPResult::True(); return TPR == TPResult::True;
} }
/// \brief Returns true if this is a C++11 attribute-specifier. Per /// \brief Returns true if this is a C++11 attribute-specifier. Per
@ -624,7 +624,7 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() {
while (true) { while (true) {
if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier)) if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
if (TryAnnotateCXXScopeToken(true)) if (TryAnnotateCXXScopeToken(true))
return TPResult::Error(); return TPResult::Error;
if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) || if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
Tok.is(tok::ampamp) || Tok.is(tok::ampamp) ||
@ -636,7 +636,7 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() {
Tok.is(tok::kw_restrict)) Tok.is(tok::kw_restrict))
ConsumeToken(); ConsumeToken();
} else { } else {
return TPResult::True(); return TPResult::True;
} }
} }
} }
@ -671,20 +671,20 @@ Parser::TPResult Parser::TryParseOperatorId() {
ConsumeBracket(); ConsumeBracket();
ConsumeBracket(); ConsumeBracket();
} }
return TPResult::True(); return TPResult::True;
#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemOnly) \ #define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemOnly) \
case tok::Token: case tok::Token:
#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemOnly) #define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemOnly)
#include "clang/Basic/OperatorKinds.def" #include "clang/Basic/OperatorKinds.def"
ConsumeToken(); ConsumeToken();
return TPResult::True(); return TPResult::True;
case tok::l_square: case tok::l_square:
if (NextToken().is(tok::r_square)) { if (NextToken().is(tok::r_square)) {
ConsumeBracket(); ConsumeBracket();
ConsumeBracket(); ConsumeBracket();
return TPResult::True(); return TPResult::True;
} }
break; break;
@ -692,7 +692,7 @@ Parser::TPResult Parser::TryParseOperatorId() {
if (NextToken().is(tok::r_paren)) { if (NextToken().is(tok::r_paren)) {
ConsumeParen(); ConsumeParen();
ConsumeParen(); ConsumeParen();
return TPResult::True(); return TPResult::True;
} }
break; break;
@ -712,24 +712,24 @@ Parser::TPResult Parser::TryParseOperatorId() {
if (Tok.is(tok::identifier)) if (Tok.is(tok::identifier))
ConsumeToken(); ConsumeToken();
else else
return TPResult::Error(); return TPResult::Error;
} }
return TPResult::True(); return TPResult::True;
} }
// Maybe this is a conversion-function-id. // Maybe this is a conversion-function-id.
bool AnyDeclSpecifiers = false; bool AnyDeclSpecifiers = false;
while (true) { while (true) {
TPResult TPR = isCXXDeclarationSpecifier(); TPResult TPR = isCXXDeclarationSpecifier();
if (TPR == TPResult::Error()) if (TPR == TPResult::Error)
return TPR; return TPR;
if (TPR == TPResult::False()) { if (TPR == TPResult::False) {
if (!AnyDeclSpecifiers) if (!AnyDeclSpecifiers)
return TPResult::Error(); return TPResult::Error;
break; break;
} }
if (TryConsumeDeclarationSpecifier() == TPResult::Error()) if (TryConsumeDeclarationSpecifier() == TPResult::Error)
return TPResult::Error(); return TPResult::Error;
AnyDeclSpecifiers = true; AnyDeclSpecifiers = true;
} }
return TryParsePtrOperatorSeq(); return TryParsePtrOperatorSeq();
@ -793,8 +793,8 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
// declarator: // declarator:
// direct-declarator // direct-declarator
// ptr-operator declarator // ptr-operator declarator
if (TryParsePtrOperatorSeq() == TPResult::Error()) if (TryParsePtrOperatorSeq() == TPResult::Error)
return TPResult::Error(); return TPResult::Error;
// direct-declarator: // direct-declarator:
// direct-abstract-declarator: // direct-abstract-declarator:
@ -811,8 +811,8 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
else if (Tok.is(tok::identifier)) else if (Tok.is(tok::identifier))
TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo()); TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo());
if (Tok.is(tok::kw_operator)) { if (Tok.is(tok::kw_operator)) {
if (TryParseOperatorId() == TPResult::Error()) if (TryParseOperatorId() == TPResult::Error)
return TPResult::Error(); return TPResult::Error;
} else } else
ConsumeToken(); ConsumeToken();
} else if (Tok.is(tok::l_paren)) { } else if (Tok.is(tok::l_paren)) {
@ -825,7 +825,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
// exception-specification[opt] // exception-specification[opt]
TPResult TPR = TryParseFunctionDeclarator(); TPResult TPR = TryParseFunctionDeclarator();
if (TPR != TPResult::Ambiguous()) if (TPR != TPResult::Ambiguous)
return TPR; return TPR;
} else { } else {
// '(' declarator ')' // '(' declarator ')'
@ -838,20 +838,20 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___fastcall) ||
Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___thiscall) ||
Tok.is(tok::kw___unaligned)) Tok.is(tok::kw___unaligned))
return TPResult::True(); // attributes indicate declaration return TPResult::True; // attributes indicate declaration
TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier); TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
if (TPR != TPResult::Ambiguous()) if (TPR != TPResult::Ambiguous)
return TPR; return TPR;
if (Tok.isNot(tok::r_paren)) if (Tok.isNot(tok::r_paren))
return TPResult::False(); return TPResult::False;
ConsumeParen(); ConsumeParen();
} }
} else if (!mayBeAbstract) { } else if (!mayBeAbstract) {
return TPResult::False(); return TPResult::False;
} }
while (1) { while (1) {
TPResult TPR(TPResult::Ambiguous()); TPResult TPR(TPResult::Ambiguous);
// abstract-declarator: ... // abstract-declarator: ...
if (Tok.is(tok::ellipsis)) if (Tok.is(tok::ellipsis))
@ -877,11 +877,11 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
break; break;
} }
if (TPR != TPResult::Ambiguous()) if (TPR != TPResult::Ambiguous)
return TPR; return TPR;
} }
return TPResult::Ambiguous(); return TPResult::Ambiguous;
} }
Parser::TPResult Parser::TPResult
@ -943,7 +943,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
#define TYPE_TRAIT(N,Spelling,K) \ #define TYPE_TRAIT(N,Spelling,K) \
case tok::kw_##Spelling: case tok::kw_##Spelling:
#include "clang/Basic/TokenKinds.def" #include "clang/Basic/TokenKinds.def"
return TPResult::True(); return TPResult::True;
// Obviously starts a type-specifier-seq: // Obviously starts a type-specifier-seq:
case tok::kw_char: case tok::kw_char:
@ -989,13 +989,13 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
case tok::kw___pixel: case tok::kw___pixel:
case tok::kw__Atomic: case tok::kw__Atomic:
case tok::kw___unknown_anytype: case tok::kw___unknown_anytype:
return TPResult::False(); return TPResult::False;
default: default:
break; break;
} }
return TPResult::Ambiguous(); return TPResult::Ambiguous;
} }
bool Parser::isTentativelyDeclared(IdentifierInfo *II) { bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
@ -1004,16 +1004,16 @@ bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
!= TentativelyDeclaredIdentifiers.end(); != TentativelyDeclaredIdentifiers.end();
} }
/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration /// isCXXDeclarationSpecifier - Returns TPResult::True if it is a declaration
/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could /// specifier, TPResult::False if it is not, TPResult::Ambiguous if it could
/// be either a decl-specifier or a function-style cast, and TPResult::Error() /// be either a decl-specifier or a function-style cast, and TPResult::Error
/// if a parsing error was found and reported. /// if a parsing error was found and reported.
/// ///
/// If HasMissingTypename is provided, a name with a dependent scope specifier /// If HasMissingTypename is provided, a name with a dependent scope specifier
/// will be treated as ambiguous if the 'typename' keyword is missing. If this /// will be treated as ambiguous if the 'typename' keyword is missing. If this
/// happens, *HasMissingTypename will be set to 'true'. This will also be used /// happens, *HasMissingTypename will be set to 'true'. This will also be used
/// as an indicator that undeclared identifiers (which will trigger a later /// as an indicator that undeclared identifiers (which will trigger a later
/// parse error) should be treated as types. Returns TPResult::Ambiguous() in /// parse error) should be treated as types. Returns TPResult::Ambiguous in
/// such cases. /// such cases.
/// ///
/// decl-specifier: /// decl-specifier:
@ -1117,12 +1117,12 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// Check for need to substitute AltiVec __vector keyword // Check for need to substitute AltiVec __vector keyword
// for "vector" identifier. // for "vector" identifier.
if (TryAltiVecVectorToken()) if (TryAltiVecVectorToken())
return TPResult::True(); return TPResult::True;
const Token &Next = NextToken(); const Token &Next = NextToken();
// In 'foo bar', 'foo' is always a type name outside of Objective-C. // In 'foo bar', 'foo' is always a type name outside of Objective-C.
if (!getLangOpts().ObjC1 && Next.is(tok::identifier)) if (!getLangOpts().ObjC1 && Next.is(tok::identifier))
return TPResult::True(); return TPResult::True;
if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) { if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) {
// Determine whether this is a valid expression. If not, we will hit // Determine whether this is a valid expression. If not, we will hit
@ -1135,15 +1135,15 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
switch (TryAnnotateName(false /* no nested name specifier */, switch (TryAnnotateName(false /* no nested name specifier */,
&TypoCorrection)) { &TypoCorrection)) {
case ANK_Error: case ANK_Error:
return TPResult::Error(); return TPResult::Error;
case ANK_TentativeDecl: case ANK_TentativeDecl:
return TPResult::False(); return TPResult::False;
case ANK_TemplateName: case ANK_TemplateName:
// A bare type template-name which can't be a template template // A bare type template-name which can't be a template template
// argument is an error, and was probably intended to be a type. // argument is an error, and was probably intended to be a type.
return GreaterThanIsOperator ? TPResult::True() : TPResult::False(); return GreaterThanIsOperator ? TPResult::True : TPResult::False;
case ANK_Unresolved: case ANK_Unresolved:
return HasMissingTypename ? TPResult::Ambiguous() : TPResult::False(); return HasMissingTypename ? TPResult::Ambiguous : TPResult::False;
case ANK_Success: case ANK_Success:
break; break;
} }
@ -1155,12 +1155,12 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// since it will annotate as a primary expression, and we want to use the // since it will annotate as a primary expression, and we want to use the
// "missing 'typename'" logic. // "missing 'typename'" logic.
if (TryAnnotateTypeOrScopeToken()) if (TryAnnotateTypeOrScopeToken())
return TPResult::Error(); return TPResult::Error;
// If annotation failed, assume it's a non-type. // If annotation failed, assume it's a non-type.
// FIXME: If this happens due to an undeclared identifier, treat it as // FIXME: If this happens due to an undeclared identifier, treat it as
// ambiguous. // ambiguous.
if (Tok.is(tok::identifier)) if (Tok.is(tok::identifier))
return TPResult::False(); return TPResult::False;
} }
// We annotated this token as something. Recurse to handle whatever we got. // We annotated this token as something. Recurse to handle whatever we got.
@ -1171,21 +1171,21 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// Annotate typenames and C++ scope specifiers. If we get one, just // Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get. // recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken()) if (TryAnnotateTypeOrScopeToken())
return TPResult::Error(); return TPResult::Error;
return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename); return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
case tok::coloncolon: { // ::foo::bar case tok::coloncolon: { // ::foo::bar
const Token &Next = NextToken(); const Token &Next = NextToken();
if (Next.is(tok::kw_new) || // ::new if (Next.is(tok::kw_new) || // ::new
Next.is(tok::kw_delete)) // ::delete Next.is(tok::kw_delete)) // ::delete
return TPResult::False(); return TPResult::False;
} }
// Fall through. // Fall through.
case tok::kw_decltype: case tok::kw_decltype:
// Annotate typenames and C++ scope specifiers. If we get one, just // Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get. // recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken()) if (TryAnnotateTypeOrScopeToken())
return TPResult::Error(); return TPResult::Error;
return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename); return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);
// decl-specifier: // decl-specifier:
@ -1242,7 +1242,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw_restrict: case tok::kw_restrict:
case tok::kw__Complex: case tok::kw__Complex:
case tok::kw___attribute: case tok::kw___attribute:
return TPResult::True(); return TPResult::True;
// Microsoft // Microsoft
case tok::kw___declspec: case tok::kw___declspec:
@ -1257,20 +1257,20 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw___ptr32: case tok::kw___ptr32:
case tok::kw___forceinline: case tok::kw___forceinline:
case tok::kw___unaligned: case tok::kw___unaligned:
return TPResult::True(); return TPResult::True;
// Borland // Borland
case tok::kw___pascal: case tok::kw___pascal:
return TPResult::True(); return TPResult::True;
// AltiVec // AltiVec
case tok::kw___vector: case tok::kw___vector:
return TPResult::True(); return TPResult::True;
case tok::annot_template_id: { case tok::annot_template_id: {
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
if (TemplateId->Kind != TNK_Type_template) if (TemplateId->Kind != TNK_Type_template)
return TPResult::False(); return TPResult::False;
CXXScopeSpec SS; CXXScopeSpec SS;
AnnotateTemplateIdTokenAsType(); AnnotateTemplateIdTokenAsType();
assert(Tok.is(tok::annot_typename)); assert(Tok.is(tok::annot_typename));
@ -1280,7 +1280,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
// We've already annotated a scope; try to annotate a type. // We've already annotated a scope; try to annotate a type.
if (TryAnnotateTypeOrScopeToken()) if (TryAnnotateTypeOrScopeToken())
return TPResult::Error(); return TPResult::Error;
if (!Tok.is(tok::annot_typename)) { if (!Tok.is(tok::annot_typename)) {
// If the next token is an identifier or a type qualifier, then this // If the next token is an identifier or a type qualifier, then this
// can't possibly be a valid expression either. // can't possibly be a valid expression either.
@ -1294,37 +1294,37 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
ConsumeToken(); ConsumeToken();
ConsumeToken(); ConsumeToken();
bool isIdentifier = Tok.is(tok::identifier); bool isIdentifier = Tok.is(tok::identifier);
TPResult TPR = TPResult::False(); TPResult TPR = TPResult::False;
if (!isIdentifier) if (!isIdentifier)
TPR = isCXXDeclarationSpecifier(BracedCastResult, TPR = isCXXDeclarationSpecifier(BracedCastResult,
HasMissingTypename); HasMissingTypename);
PA.Revert(); PA.Revert();
if (isIdentifier || if (isIdentifier ||
TPR == TPResult::True() || TPR == TPResult::Error()) TPR == TPResult::True || TPR == TPResult::Error)
return TPResult::Error(); return TPResult::Error;
if (HasMissingTypename) { if (HasMissingTypename) {
// We can't tell whether this is a missing 'typename' or a valid // We can't tell whether this is a missing 'typename' or a valid
// expression. // expression.
*HasMissingTypename = true; *HasMissingTypename = true;
return TPResult::Ambiguous(); return TPResult::Ambiguous;
} }
} else { } else {
// Try to resolve the name. If it doesn't exist, assume it was // Try to resolve the name. If it doesn't exist, assume it was
// intended to name a type and keep disambiguating. // intended to name a type and keep disambiguating.
switch (TryAnnotateName(false /* SS is not dependent */)) { switch (TryAnnotateName(false /* SS is not dependent */)) {
case ANK_Error: case ANK_Error:
return TPResult::Error(); return TPResult::Error;
case ANK_TentativeDecl: case ANK_TentativeDecl:
return TPResult::False(); return TPResult::False;
case ANK_TemplateName: case ANK_TemplateName:
// A bare type template-name which can't be a template template // A bare type template-name which can't be a template template
// argument is an error, and was probably intended to be a type. // argument is an error, and was probably intended to be a type.
return GreaterThanIsOperator ? TPResult::True() : TPResult::False(); return GreaterThanIsOperator ? TPResult::True : TPResult::False;
case ANK_Unresolved: case ANK_Unresolved:
return HasMissingTypename ? TPResult::Ambiguous() return HasMissingTypename ? TPResult::Ambiguous
: TPResult::False(); : TPResult::False;
case ANK_Success: case ANK_Success:
// Annotated it, check again. // Annotated it, check again.
assert(Tok.isNot(tok::annot_cxxscope) || assert(Tok.isNot(tok::annot_cxxscope) ||
@ -1334,7 +1334,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
} }
} }
} }
return TPResult::False(); return TPResult::False;
} }
// If that succeeded, fallthrough into the generic simple-type-id case. // If that succeeded, fallthrough into the generic simple-type-id case.
@ -1370,16 +1370,16 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
PA.Revert(); PA.Revert();
if (TPR == TPResult::Error()) if (TPR == TPResult::Error)
return TPResult::Error(); return TPResult::Error;
if (isFollowedByParen) if (isFollowedByParen)
return TPResult::Ambiguous(); return TPResult::Ambiguous;
if (getLangOpts().CPlusPlus11 && isFollowedByBrace) if (getLangOpts().CPlusPlus11 && isFollowedByBrace)
return BracedCastResult; return BracedCastResult;
return TPResult::True(); return TPResult::True;
} }
case tok::kw_char: case tok::kw_char:
@ -1400,7 +1400,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw_void: case tok::kw_void:
case tok::annot_decltype: case tok::annot_decltype:
if (NextToken().is(tok::l_paren)) if (NextToken().is(tok::l_paren))
return TPResult::Ambiguous(); return TPResult::Ambiguous;
// This is a function-style cast in all cases we disambiguate other than // This is a function-style cast in all cases we disambiguate other than
// one: // one:
@ -1412,14 +1412,14 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
return BracedCastResult; return BracedCastResult;
if (isStartOfObjCClassMessageMissingOpenBracket()) if (isStartOfObjCClassMessageMissingOpenBracket())
return TPResult::False(); return TPResult::False;
return TPResult::True(); return TPResult::True;
// GNU typeof support. // GNU typeof support.
case tok::kw_typeof: { case tok::kw_typeof: {
if (NextToken().isNot(tok::l_paren)) if (NextToken().isNot(tok::l_paren))
return TPResult::True(); return TPResult::True;
TentativeParsingAction PA(*this); TentativeParsingAction PA(*this);
@ -1429,28 +1429,28 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
PA.Revert(); PA.Revert();
if (TPR == TPResult::Error()) if (TPR == TPResult::Error)
return TPResult::Error(); return TPResult::Error;
if (isFollowedByParen) if (isFollowedByParen)
return TPResult::Ambiguous(); return TPResult::Ambiguous;
if (getLangOpts().CPlusPlus11 && isFollowedByBrace) if (getLangOpts().CPlusPlus11 && isFollowedByBrace)
return BracedCastResult; return BracedCastResult;
return TPResult::True(); return TPResult::True;
} }
// C++0x type traits support // C++0x type traits support
case tok::kw___underlying_type: case tok::kw___underlying_type:
return TPResult::True(); return TPResult::True;
// C11 _Atomic // C11 _Atomic
case tok::kw__Atomic: case tok::kw__Atomic:
return TPResult::True(); return TPResult::True;
default: default:
return TPResult::False(); return TPResult::False;
} }
} }
@ -1516,9 +1516,9 @@ Parser::TPResult Parser::TryParseTypeofSpecifier() {
// Parse through the parens after 'typeof'. // Parse through the parens after 'typeof'.
ConsumeParen(); ConsumeParen();
if (!SkipUntil(tok::r_paren, StopAtSemi)) if (!SkipUntil(tok::r_paren, StopAtSemi))
return TPResult::Error(); return TPResult::Error;
return TPResult::Ambiguous(); return TPResult::Ambiguous;
} }
/// [ObjC] protocol-qualifiers: /// [ObjC] protocol-qualifiers:
@ -1528,7 +1528,7 @@ Parser::TPResult Parser::TryParseProtocolQualifiers() {
ConsumeToken(); ConsumeToken();
do { do {
if (Tok.isNot(tok::identifier)) if (Tok.isNot(tok::identifier))
return TPResult::Error(); return TPResult::Error;
ConsumeToken(); ConsumeToken();
if (Tok.is(tok::comma)) { if (Tok.is(tok::comma)) {
@ -1538,11 +1538,11 @@ Parser::TPResult Parser::TryParseProtocolQualifiers() {
if (Tok.is(tok::greater)) { if (Tok.is(tok::greater)) {
ConsumeToken(); ConsumeToken();
return TPResult::Ambiguous(); return TPResult::Ambiguous;
} }
} while (false); } while (false);
return TPResult::Error(); return TPResult::Error;
} }
/// isCXXFunctionDeclarator - Disambiguates between a function declarator or /// isCXXFunctionDeclarator - Disambiguates between a function declarator or
@ -1571,9 +1571,9 @@ bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) {
ConsumeParen(); ConsumeParen();
bool InvalidAsDeclaration = false; bool InvalidAsDeclaration = false;
TPResult TPR = TryParseParameterDeclarationClause(&InvalidAsDeclaration); TPResult TPR = TryParseParameterDeclarationClause(&InvalidAsDeclaration);
if (TPR == TPResult::Ambiguous()) { if (TPR == TPResult::Ambiguous) {
if (Tok.isNot(tok::r_paren)) if (Tok.isNot(tok::r_paren))
TPR = TPResult::False(); TPR = TPResult::False;
else { else {
const Token &Next = NextToken(); const Token &Next = NextToken();
if (Next.is(tok::amp) || Next.is(tok::ampamp) || if (Next.is(tok::amp) || Next.is(tok::ampamp) ||
@ -1585,20 +1585,20 @@ bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) {
// The next token cannot appear after a constructor-style initializer, // The next token cannot appear after a constructor-style initializer,
// and can appear next in a function definition. This must be a function // and can appear next in a function definition. This must be a function
// declarator. // declarator.
TPR = TPResult::True(); TPR = TPResult::True;
else if (InvalidAsDeclaration) else if (InvalidAsDeclaration)
// Use the absence of 'typename' as a tie-breaker. // Use the absence of 'typename' as a tie-breaker.
TPR = TPResult::False(); TPR = TPResult::False;
} }
} }
PA.Revert(); PA.Revert();
if (IsAmbiguous && TPR == TPResult::Ambiguous()) if (IsAmbiguous && TPR == TPResult::Ambiguous)
*IsAmbiguous = true; *IsAmbiguous = true;
// In case of an error, let the declaration parsing code handle it. // In case of an error, let the declaration parsing code handle it.
return TPR != TPResult::False(); return TPR != TPResult::False;
} }
/// parameter-declaration-clause: /// parameter-declaration-clause:
@ -1623,7 +1623,7 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration,
bool VersusTemplateArgument) { bool VersusTemplateArgument) {
if (Tok.is(tok::r_paren)) if (Tok.is(tok::r_paren))
return TPResult::Ambiguous(); return TPResult::Ambiguous;
// parameter-declaration-list[opt] '...'[opt] // parameter-declaration-list[opt] '...'[opt]
// parameter-declaration-list ',' '...' // parameter-declaration-list ',' '...'
@ -1637,15 +1637,15 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration,
if (Tok.is(tok::ellipsis)) { if (Tok.is(tok::ellipsis)) {
ConsumeToken(); ConsumeToken();
if (Tok.is(tok::r_paren)) if (Tok.is(tok::r_paren))
return TPResult::True(); // '...)' is a sign of a function declarator. return TPResult::True; // '...)' is a sign of a function declarator.
else else
return TPResult::False(); return TPResult::False;
} }
// An attribute-specifier-seq here is a sign of a function declarator. // An attribute-specifier-seq here is a sign of a function declarator.
if (isCXX11AttributeSpecifier(/*Disambiguate*/false, if (isCXX11AttributeSpecifier(/*Disambiguate*/false,
/*OuterMightBeMessageSend*/true)) /*OuterMightBeMessageSend*/true))
return TPResult::True(); return TPResult::True;
ParsedAttributes attrs(AttrFactory); ParsedAttributes attrs(AttrFactory);
MaybeParseMicrosoftAttributes(attrs); MaybeParseMicrosoftAttributes(attrs);
@ -1653,43 +1653,43 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration,
// decl-specifier-seq // decl-specifier-seq
// A parameter-declaration's initializer must be preceded by an '=', so // A parameter-declaration's initializer must be preceded by an '=', so
// decl-specifier-seq '{' is not a parameter in C++11. // decl-specifier-seq '{' is not a parameter in C++11.
TPResult TPR = isCXXDeclarationSpecifier(TPResult::False(), TPResult TPR = isCXXDeclarationSpecifier(TPResult::False,
InvalidAsDeclaration); InvalidAsDeclaration);
if (VersusTemplateArgument && TPR == TPResult::True()) { if (VersusTemplateArgument && TPR == TPResult::True) {
// Consume the decl-specifier-seq. We have to look past it, since a // Consume the decl-specifier-seq. We have to look past it, since a
// type-id might appear here in a template argument. // type-id might appear here in a template argument.
bool SeenType = false; bool SeenType = false;
do { do {
SeenType |= isCXXDeclarationSpecifierAType(); SeenType |= isCXXDeclarationSpecifierAType();
if (TryConsumeDeclarationSpecifier() == TPResult::Error()) if (TryConsumeDeclarationSpecifier() == TPResult::Error)
return TPResult::Error(); return TPResult::Error;
// If we see a parameter name, this can't be a template argument. // If we see a parameter name, this can't be a template argument.
if (SeenType && Tok.is(tok::identifier)) if (SeenType && Tok.is(tok::identifier))
return TPResult::True(); return TPResult::True;
TPR = isCXXDeclarationSpecifier(TPResult::False(), TPR = isCXXDeclarationSpecifier(TPResult::False,
InvalidAsDeclaration); InvalidAsDeclaration);
if (TPR == TPResult::Error()) if (TPR == TPResult::Error)
return TPR; return TPR;
} while (TPR != TPResult::False()); } while (TPR != TPResult::False);
} else if (TPR == TPResult::Ambiguous()) { } else if (TPR == TPResult::Ambiguous) {
// Disambiguate what follows the decl-specifier. // Disambiguate what follows the decl-specifier.
if (TryConsumeDeclarationSpecifier() == TPResult::Error()) if (TryConsumeDeclarationSpecifier() == TPResult::Error)
return TPResult::Error(); return TPResult::Error;
} else } else
return TPR; return TPR;
// declarator // declarator
// abstract-declarator[opt] // abstract-declarator[opt]
TPR = TryParseDeclarator(true/*mayBeAbstract*/); TPR = TryParseDeclarator(true/*mayBeAbstract*/);
if (TPR != TPResult::Ambiguous()) if (TPR != TPResult::Ambiguous)
return TPR; return TPR;
// [GNU] attributes[opt] // [GNU] attributes[opt]
if (Tok.is(tok::kw___attribute)) if (Tok.is(tok::kw___attribute))
return TPResult::True(); return TPResult::True;
// If we're disambiguating a template argument in a default argument in // If we're disambiguating a template argument in a default argument in
// a class definition versus a parameter declaration, an '=' here // a class definition versus a parameter declaration, an '=' here
@ -1702,36 +1702,36 @@ Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration,
// parameter-declaration-clause, and the last param is missing its default // parameter-declaration-clause, and the last param is missing its default
// argument. // argument.
if (VersusTemplateArgument) if (VersusTemplateArgument)
return (Tok.is(tok::equal) || Tok.is(tok::r_paren)) ? TPResult::True() return (Tok.is(tok::equal) || Tok.is(tok::r_paren)) ? TPResult::True
: TPResult::False(); : TPResult::False;
if (Tok.is(tok::equal)) { if (Tok.is(tok::equal)) {
// '=' assignment-expression // '=' assignment-expression
// Parse through assignment-expression. // Parse through assignment-expression.
// FIXME: assignment-expression may contain an unparenthesized comma. // FIXME: assignment-expression may contain an unparenthesized comma.
if (!SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch)) if (!SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch))
return TPResult::Error(); return TPResult::Error;
} }
if (Tok.is(tok::ellipsis)) { if (Tok.is(tok::ellipsis)) {
ConsumeToken(); ConsumeToken();
if (Tok.is(tok::r_paren)) if (Tok.is(tok::r_paren))
return TPResult::True(); // '...)' is a sign of a function declarator. return TPResult::True; // '...)' is a sign of a function declarator.
else else
return TPResult::False(); return TPResult::False;
} }
if (!TryConsumeToken(tok::comma)) if (!TryConsumeToken(tok::comma))
break; break;
} }
return TPResult::Ambiguous(); return TPResult::Ambiguous;
} }
/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue /// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
/// parsing as a function declarator. /// parsing as a function declarator.
/// If TryParseFunctionDeclarator fully parsed the function declarator, it will /// If TryParseFunctionDeclarator fully parsed the function declarator, it will
/// return TPResult::Ambiguous(), otherwise it will return either False() or /// return TPResult::Ambiguous, otherwise it will return either False() or
/// Error(). /// Error().
/// ///
/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] /// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
@ -1745,15 +1745,15 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() {
// The '(' is already parsed. // The '(' is already parsed.
TPResult TPR = TryParseParameterDeclarationClause(); TPResult TPR = TryParseParameterDeclarationClause();
if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) if (TPR == TPResult::Ambiguous && Tok.isNot(tok::r_paren))
TPR = TPResult::False(); TPR = TPResult::False;
if (TPR == TPResult::False() || TPR == TPResult::Error()) if (TPR == TPResult::False || TPR == TPResult::Error)
return TPR; return TPR;
// Parse through the parens. // Parse through the parens.
if (!SkipUntil(tok::r_paren, StopAtSemi)) if (!SkipUntil(tok::r_paren, StopAtSemi))
return TPResult::Error(); return TPResult::Error;
// cv-qualifier-seq // cv-qualifier-seq
while (Tok.is(tok::kw_const) || while (Tok.is(tok::kw_const) ||
@ -1769,12 +1769,12 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() {
if (Tok.is(tok::kw_throw)) { if (Tok.is(tok::kw_throw)) {
ConsumeToken(); ConsumeToken();
if (Tok.isNot(tok::l_paren)) if (Tok.isNot(tok::l_paren))
return TPResult::Error(); return TPResult::Error;
// Parse through the parens after 'throw'. // Parse through the parens after 'throw'.
ConsumeParen(); ConsumeParen();
if (!SkipUntil(tok::r_paren, StopAtSemi)) if (!SkipUntil(tok::r_paren, StopAtSemi))
return TPResult::Error(); return TPResult::Error;
} }
if (Tok.is(tok::kw_noexcept)) { if (Tok.is(tok::kw_noexcept)) {
ConsumeToken(); ConsumeToken();
@ -1783,11 +1783,11 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() {
// Find the matching rparen. // Find the matching rparen.
ConsumeParen(); ConsumeParen();
if (!SkipUntil(tok::r_paren, StopAtSemi)) if (!SkipUntil(tok::r_paren, StopAtSemi))
return TPResult::Error(); return TPResult::Error;
} }
} }
return TPResult::Ambiguous(); return TPResult::Ambiguous;
} }
/// '[' constant-expression[opt] ']' /// '[' constant-expression[opt] ']'
@ -1795,7 +1795,7 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() {
Parser::TPResult Parser::TryParseBracketDeclarator() { Parser::TPResult Parser::TryParseBracketDeclarator() {
ConsumeBracket(); ConsumeBracket();
if (!SkipUntil(tok::r_square, StopAtSemi)) if (!SkipUntil(tok::r_square, StopAtSemi))
return TPResult::Error(); return TPResult::Error;
return TPResult::Ambiguous(); return TPResult::Ambiguous;
} }