ParseTentative.cpp revision 224145
1193326Sed//===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file implements the tentative parsing portions of the Parser 11193326Sed// interfaces, for ambiguity resolution. 12193326Sed// 13193326Sed//===----------------------------------------------------------------------===// 14193326Sed 15193326Sed#include "clang/Parse/Parser.h" 16193326Sed#include "clang/Parse/ParseDiagnostic.h" 17212904Sdim#include "clang/Sema/ParsedTemplate.h" 18193326Sedusing namespace clang; 19193326Sed 20193326Sed/// isCXXDeclarationStatement - C++-specialized function that disambiguates 21193326Sed/// between a declaration or an expression statement, when parsing function 22193326Sed/// bodies. Returns true for declaration, false for expression. 23193326Sed/// 24193326Sed/// declaration-statement: 25193326Sed/// block-declaration 26193326Sed/// 27193326Sed/// block-declaration: 28193326Sed/// simple-declaration 29193326Sed/// asm-definition 30193326Sed/// namespace-alias-definition 31193326Sed/// using-declaration 32193326Sed/// using-directive 33193326Sed/// [C++0x] static_assert-declaration 34193326Sed/// 35193326Sed/// asm-definition: 36193326Sed/// 'asm' '(' string-literal ')' ';' 37193326Sed/// 38193326Sed/// namespace-alias-definition: 39193326Sed/// 'namespace' identifier = qualified-namespace-specifier ';' 40193326Sed/// 41193326Sed/// using-declaration: 42193326Sed/// 'using' typename[opt] '::'[opt] nested-name-specifier 43193326Sed/// unqualified-id ';' 44193326Sed/// 'using' '::' unqualified-id ; 45193326Sed/// 46193326Sed/// using-directive: 47193326Sed/// 'using' 'namespace' '::'[opt] nested-name-specifier[opt] 48193326Sed/// namespace-name ';' 49193326Sed/// 50193326Sedbool Parser::isCXXDeclarationStatement() { 51193326Sed switch (Tok.getKind()) { 52193326Sed // asm-definition 53193326Sed case tok::kw_asm: 54193326Sed // namespace-alias-definition 55193326Sed case tok::kw_namespace: 56193326Sed // using-declaration 57193326Sed // using-directive 58193326Sed case tok::kw_using: 59199990Srdivacky // static_assert-declaration 60193326Sed case tok::kw_static_assert: 61221345Sdim case tok::kw__Static_assert: 62193326Sed return true; 63199990Srdivacky // simple-declaration 64193326Sed default: 65193326Sed return isCXXSimpleDeclaration(); 66193326Sed } 67193326Sed} 68193326Sed 69193326Sed/// isCXXSimpleDeclaration - C++-specialized function that disambiguates 70193326Sed/// between a simple-declaration or an expression-statement. 71193326Sed/// If during the disambiguation process a parsing error is encountered, 72193326Sed/// the function returns true to let the declaration parsing code handle it. 73193326Sed/// Returns false if the statement is disambiguated as expression. 74193326Sed/// 75193326Sed/// simple-declaration: 76193326Sed/// decl-specifier-seq init-declarator-list[opt] ';' 77193326Sed/// 78193326Sedbool Parser::isCXXSimpleDeclaration() { 79193326Sed // C++ 6.8p1: 80193326Sed // There is an ambiguity in the grammar involving expression-statements and 81193326Sed // declarations: An expression-statement with a function-style explicit type 82193326Sed // conversion (5.2.3) as its leftmost subexpression can be indistinguishable 83193326Sed // from a declaration where the first declarator starts with a '('. In those 84193326Sed // cases the statement is a declaration. [Note: To disambiguate, the whole 85193326Sed // statement might have to be examined to determine if it is an 86193326Sed // expression-statement or a declaration]. 87193326Sed 88193326Sed // C++ 6.8p3: 89193326Sed // The disambiguation is purely syntactic; that is, the meaning of the names 90193326Sed // occurring in such a statement, beyond whether they are type-names or not, 91193326Sed // is not generally used in or changed by the disambiguation. Class 92193326Sed // templates are instantiated as necessary to determine if a qualified name 93193326Sed // is a type-name. Disambiguation precedes parsing, and a statement 94193326Sed // disambiguated as a declaration may be an ill-formed declaration. 95193326Sed 96193326Sed // We don't have to parse all of the decl-specifier-seq part. There's only 97193326Sed // an ambiguity if the first decl-specifier is 98193326Sed // simple-type-specifier/typename-specifier followed by a '(', which may 99193326Sed // indicate a function-style cast expression. 100193326Sed // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such 101193326Sed // a case. 102193326Sed 103193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 104193326Sed if (TPR != TPResult::Ambiguous()) 105193326Sed return TPR != TPResult::False(); // Returns true for TPResult::True() or 106193326Sed // TPResult::Error(). 107193326Sed 108193326Sed // FIXME: Add statistics about the number of ambiguous statements encountered 109193326Sed // and how they were resolved (number of declarations+number of expressions). 110193326Sed 111193326Sed // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 112193326Sed // We need tentative parsing... 113193326Sed 114193326Sed TentativeParsingAction PA(*this); 115193326Sed TPR = TryParseSimpleDeclaration(); 116193326Sed PA.Revert(); 117193326Sed 118193326Sed // In case of an error, let the declaration parsing code handle it. 119193326Sed if (TPR == TPResult::Error()) 120193326Sed return true; 121193326Sed 122193326Sed // Declarations take precedence over expressions. 123193326Sed if (TPR == TPResult::Ambiguous()) 124193326Sed TPR = TPResult::True(); 125193326Sed 126193326Sed assert(TPR == TPResult::True() || TPR == TPResult::False()); 127193326Sed return TPR == TPResult::True(); 128193326Sed} 129193326Sed 130193326Sed/// simple-declaration: 131193326Sed/// decl-specifier-seq init-declarator-list[opt] ';' 132193326Sed/// 133193326SedParser::TPResult Parser::TryParseSimpleDeclaration() { 134193326Sed // We know that we have a simple-type-specifier/typename-specifier followed 135193326Sed // by a '('. 136193326Sed assert(isCXXDeclarationSpecifier() == TPResult::Ambiguous()); 137193326Sed 138193326Sed if (Tok.is(tok::kw_typeof)) 139193326Sed TryParseTypeofSpecifier(); 140218893Sdim else { 141193326Sed ConsumeToken(); 142218893Sdim 143218893Sdim if (getLang().ObjC1 && Tok.is(tok::less)) 144218893Sdim TryParseProtocolQualifiers(); 145218893Sdim } 146218893Sdim 147193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 148193326Sed 149193326Sed TPResult TPR = TryParseInitDeclaratorList(); 150193326Sed if (TPR != TPResult::Ambiguous()) 151193326Sed return TPR; 152193326Sed 153193326Sed if (Tok.isNot(tok::semi)) 154193326Sed return TPResult::False(); 155193326Sed 156193326Sed return TPResult::Ambiguous(); 157193326Sed} 158193326Sed 159193326Sed/// init-declarator-list: 160193326Sed/// init-declarator 161193326Sed/// init-declarator-list ',' init-declarator 162193326Sed/// 163193326Sed/// init-declarator: 164193326Sed/// declarator initializer[opt] 165193326Sed/// [GNU] declarator simple-asm-expr[opt] attributes[opt] initializer[opt] 166193326Sed/// 167193326Sed/// initializer: 168193326Sed/// '=' initializer-clause 169193326Sed/// '(' expression-list ')' 170193326Sed/// 171193326Sed/// initializer-clause: 172193326Sed/// assignment-expression 173193326Sed/// '{' initializer-list ','[opt] '}' 174193326Sed/// '{' '}' 175193326Sed/// 176193326SedParser::TPResult Parser::TryParseInitDeclaratorList() { 177193326Sed while (1) { 178193326Sed // declarator 179193326Sed TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/); 180193326Sed if (TPR != TPResult::Ambiguous()) 181193326Sed return TPR; 182193326Sed 183193326Sed // [GNU] simple-asm-expr[opt] attributes[opt] 184193326Sed if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) 185193326Sed return TPResult::True(); 186193326Sed 187193326Sed // initializer[opt] 188193326Sed if (Tok.is(tok::l_paren)) { 189193326Sed // Parse through the parens. 190193326Sed ConsumeParen(); 191193326Sed if (!SkipUntil(tok::r_paren)) 192193326Sed return TPResult::Error(); 193212904Sdim } else if (Tok.is(tok::equal) || isTokIdentifier_in()) { 194212904Sdim // MSVC and g++ won't examine the rest of declarators if '=' is 195212904Sdim // encountered; they just conclude that we have a declaration. 196212904Sdim // EDG parses the initializer completely, which is the proper behavior 197212904Sdim // for this case. 198193326Sed // 199212904Sdim // At present, Clang follows MSVC and g++, since the parser does not have 200212904Sdim // the ability to parse an expression fully without recording the 201212904Sdim // results of that parse. 202212904Sdim // Also allow 'in' after on objective-c declaration as in: 203212904Sdim // for (int (^b)(void) in array). Ideally this should be done in the 204212904Sdim // context of parsing for-init-statement of a foreach statement only. But, 205212904Sdim // in any other context 'in' is invalid after a declaration and parser 206212904Sdim // issues the error regardless of outcome of this decision. 207212904Sdim // FIXME. Change if above assumption does not hold. 208212904Sdim return TPResult::True(); 209193326Sed } 210193326Sed 211193326Sed if (Tok.isNot(tok::comma)) 212193326Sed break; 213193326Sed ConsumeToken(); // the comma. 214193326Sed } 215193326Sed 216193326Sed return TPResult::Ambiguous(); 217193326Sed} 218193326Sed 219193326Sed/// isCXXConditionDeclaration - Disambiguates between a declaration or an 220193326Sed/// expression for a condition of a if/switch/while/for statement. 221193326Sed/// If during the disambiguation process a parsing error is encountered, 222193326Sed/// the function returns true to let the declaration parsing code handle it. 223193326Sed/// 224193326Sed/// condition: 225193326Sed/// expression 226193326Sed/// type-specifier-seq declarator '=' assignment-expression 227193326Sed/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] 228193326Sed/// '=' assignment-expression 229193326Sed/// 230193326Sedbool Parser::isCXXConditionDeclaration() { 231193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 232193326Sed if (TPR != TPResult::Ambiguous()) 233193326Sed return TPR != TPResult::False(); // Returns true for TPResult::True() or 234193326Sed // TPResult::Error(). 235193326Sed 236193326Sed // FIXME: Add statistics about the number of ambiguous statements encountered 237193326Sed // and how they were resolved (number of declarations+number of expressions). 238193326Sed 239193326Sed // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 240193326Sed // We need tentative parsing... 241193326Sed 242193326Sed TentativeParsingAction PA(*this); 243193326Sed 244193326Sed // type-specifier-seq 245193326Sed if (Tok.is(tok::kw_typeof)) 246193326Sed TryParseTypeofSpecifier(); 247218893Sdim else { 248193326Sed ConsumeToken(); 249218893Sdim 250218893Sdim if (getLang().ObjC1 && Tok.is(tok::less)) 251218893Sdim TryParseProtocolQualifiers(); 252218893Sdim } 253193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 254193326Sed 255193326Sed // declarator 256193326Sed TPR = TryParseDeclarator(false/*mayBeAbstract*/); 257193326Sed 258193326Sed // In case of an error, let the declaration parsing code handle it. 259193326Sed if (TPR == TPResult::Error()) 260193326Sed TPR = TPResult::True(); 261193326Sed 262193326Sed if (TPR == TPResult::Ambiguous()) { 263193326Sed // '=' 264193326Sed // [GNU] simple-asm-expr[opt] attributes[opt] 265193326Sed if (Tok.is(tok::equal) || 266193326Sed Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) 267193326Sed TPR = TPResult::True(); 268193326Sed else 269193326Sed TPR = TPResult::False(); 270193326Sed } 271193326Sed 272193326Sed PA.Revert(); 273193326Sed 274193326Sed assert(TPR == TPResult::True() || TPR == TPResult::False()); 275193326Sed return TPR == TPResult::True(); 276193326Sed} 277193326Sed 278198092Srdivacky /// \brief Determine whether the next set of tokens contains a type-id. 279193326Sed /// 280193326Sed /// The context parameter states what context we're parsing right 281193326Sed /// now, which affects how this routine copes with the token 282193326Sed /// following the type-id. If the context is TypeIdInParens, we have 283193326Sed /// already parsed the '(' and we will cease lookahead when we hit 284193326Sed /// the corresponding ')'. If the context is 285193326Sed /// TypeIdAsTemplateArgument, we've already parsed the '<' or ',' 286193326Sed /// before this template argument, and will cease lookahead when we 287193326Sed /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id 288193326Sed /// and false for an expression. If during the disambiguation 289193326Sed /// process a parsing error is encountered, the function returns 290193326Sed /// true to let the declaration parsing code handle it. 291193326Sed /// 292193326Sed /// type-id: 293193326Sed /// type-specifier-seq abstract-declarator[opt] 294193326Sed /// 295193326Sedbool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { 296198092Srdivacky 297193326Sed isAmbiguous = false; 298193326Sed 299193326Sed // C++ 8.2p2: 300193326Sed // The ambiguity arising from the similarity between a function-style cast and 301193326Sed // a type-id can occur in different contexts. The ambiguity appears as a 302193326Sed // choice between a function-style cast expression and a declaration of a 303193326Sed // type. The resolution is that any construct that could possibly be a type-id 304193326Sed // in its syntactic context shall be considered a type-id. 305193326Sed 306193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 307193326Sed if (TPR != TPResult::Ambiguous()) 308193326Sed return TPR != TPResult::False(); // Returns true for TPResult::True() or 309193326Sed // TPResult::Error(). 310193326Sed 311193326Sed // FIXME: Add statistics about the number of ambiguous statements encountered 312193326Sed // and how they were resolved (number of declarations+number of expressions). 313193326Sed 314193326Sed // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 315193326Sed // We need tentative parsing... 316193326Sed 317193326Sed TentativeParsingAction PA(*this); 318193326Sed 319193326Sed // type-specifier-seq 320193326Sed if (Tok.is(tok::kw_typeof)) 321193326Sed TryParseTypeofSpecifier(); 322218893Sdim else { 323193326Sed ConsumeToken(); 324218893Sdim 325218893Sdim if (getLang().ObjC1 && Tok.is(tok::less)) 326218893Sdim TryParseProtocolQualifiers(); 327218893Sdim } 328218893Sdim 329193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 330193326Sed 331193326Sed // declarator 332193326Sed TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/); 333193326Sed 334193326Sed // In case of an error, let the declaration parsing code handle it. 335193326Sed if (TPR == TPResult::Error()) 336193326Sed TPR = TPResult::True(); 337193326Sed 338193326Sed if (TPR == TPResult::Ambiguous()) { 339193326Sed // We are supposed to be inside parens, so if after the abstract declarator 340193326Sed // we encounter a ')' this is a type-id, otherwise it's an expression. 341193326Sed if (Context == TypeIdInParens && Tok.is(tok::r_paren)) { 342193326Sed TPR = TPResult::True(); 343193326Sed isAmbiguous = true; 344193326Sed 345193326Sed // We are supposed to be inside a template argument, so if after 346193326Sed // the abstract declarator we encounter a '>', '>>' (in C++0x), or 347193326Sed // ',', this is a type-id. Otherwise, it's an expression. 348193326Sed } else if (Context == TypeIdAsTemplateArgument && 349193326Sed (Tok.is(tok::greater) || Tok.is(tok::comma) || 350193326Sed (getLang().CPlusPlus0x && Tok.is(tok::greatergreater)))) { 351193326Sed TPR = TPResult::True(); 352193326Sed isAmbiguous = true; 353193326Sed 354193326Sed } else 355193326Sed TPR = TPResult::False(); 356193326Sed } 357193326Sed 358193326Sed PA.Revert(); 359193326Sed 360193326Sed assert(TPR == TPResult::True() || TPR == TPResult::False()); 361193326Sed return TPR == TPResult::True(); 362193326Sed} 363193326Sed 364199990Srdivacky/// isCXX0XAttributeSpecifier - returns true if this is a C++0x 365199990Srdivacky/// attribute-specifier. By default, unless in Obj-C++, only a cursory check is 366199990Srdivacky/// performed that will simply return true if a [[ is seen. Currently C++ has no 367199990Srdivacky/// syntactical ambiguities from this check, but it may inhibit error recovery. 368199990Srdivacky/// If CheckClosing is true, a check is made for closing ]] brackets. 369199990Srdivacky/// 370199990Srdivacky/// If given, After is set to the token after the attribute-specifier so that 371199990Srdivacky/// appropriate parsing decisions can be made; it is left untouched if false is 372199990Srdivacky/// returned. 373199990Srdivacky/// 374199990Srdivacky/// FIXME: If an error is in the closing ]] brackets, the program assumes 375199990Srdivacky/// the absence of an attribute-specifier, which can cause very yucky errors 376199990Srdivacky/// to occur. 377199990Srdivacky/// 378199990Srdivacky/// [C++0x] attribute-specifier: 379199990Srdivacky/// '[' '[' attribute-list ']' ']' 380199990Srdivacky/// 381199990Srdivacky/// [C++0x] attribute-list: 382199990Srdivacky/// attribute[opt] 383199990Srdivacky/// attribute-list ',' attribute[opt] 384199990Srdivacky/// 385199990Srdivacky/// [C++0x] attribute: 386199990Srdivacky/// attribute-token attribute-argument-clause[opt] 387199990Srdivacky/// 388199990Srdivacky/// [C++0x] attribute-token: 389199990Srdivacky/// identifier 390199990Srdivacky/// attribute-scoped-token 391199990Srdivacky/// 392199990Srdivacky/// [C++0x] attribute-scoped-token: 393199990Srdivacky/// attribute-namespace '::' identifier 394199990Srdivacky/// 395199990Srdivacky/// [C++0x] attribute-namespace: 396199990Srdivacky/// identifier 397199990Srdivacky/// 398199990Srdivacky/// [C++0x] attribute-argument-clause: 399199990Srdivacky/// '(' balanced-token-seq ')' 400199990Srdivacky/// 401199990Srdivacky/// [C++0x] balanced-token-seq: 402199990Srdivacky/// balanced-token 403199990Srdivacky/// balanced-token-seq balanced-token 404199990Srdivacky/// 405199990Srdivacky/// [C++0x] balanced-token: 406199990Srdivacky/// '(' balanced-token-seq ')' 407199990Srdivacky/// '[' balanced-token-seq ']' 408199990Srdivacky/// '{' balanced-token-seq '}' 409199990Srdivacky/// any token but '(', ')', '[', ']', '{', or '}' 410199990Srdivackybool Parser::isCXX0XAttributeSpecifier (bool CheckClosing, 411199990Srdivacky tok::TokenKind *After) { 412199990Srdivacky if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) 413199990Srdivacky return false; 414199990Srdivacky 415199990Srdivacky // No tentative parsing if we don't need to look for ]] 416199990Srdivacky if (!CheckClosing && !getLang().ObjC1) 417199990Srdivacky return true; 418199990Srdivacky 419199990Srdivacky struct TentativeReverter { 420199990Srdivacky TentativeParsingAction PA; 421199990Srdivacky 422199990Srdivacky TentativeReverter (Parser& P) 423199990Srdivacky : PA(P) 424199990Srdivacky {} 425199990Srdivacky ~TentativeReverter () { 426199990Srdivacky PA.Revert(); 427199990Srdivacky } 428199990Srdivacky } R(*this); 429199990Srdivacky 430199990Srdivacky // Opening brackets were checked for above. 431199990Srdivacky ConsumeBracket(); 432199990Srdivacky ConsumeBracket(); 433199990Srdivacky 434199990Srdivacky // SkipUntil will handle balanced tokens, which are guaranteed in attributes. 435199990Srdivacky SkipUntil(tok::r_square, false); 436199990Srdivacky 437199990Srdivacky if (Tok.isNot(tok::r_square)) 438199990Srdivacky return false; 439199990Srdivacky ConsumeBracket(); 440199990Srdivacky 441199990Srdivacky if (After) 442199990Srdivacky *After = Tok.getKind(); 443199990Srdivacky 444199990Srdivacky return true; 445199990Srdivacky} 446199990Srdivacky 447193326Sed/// declarator: 448193326Sed/// direct-declarator 449193326Sed/// ptr-operator declarator 450193326Sed/// 451193326Sed/// direct-declarator: 452193326Sed/// declarator-id 453193326Sed/// direct-declarator '(' parameter-declaration-clause ')' 454193326Sed/// cv-qualifier-seq[opt] exception-specification[opt] 455193326Sed/// direct-declarator '[' constant-expression[opt] ']' 456193326Sed/// '(' declarator ')' 457193326Sed/// [GNU] '(' attributes declarator ')' 458193326Sed/// 459193326Sed/// abstract-declarator: 460193326Sed/// ptr-operator abstract-declarator[opt] 461193326Sed/// direct-abstract-declarator 462218893Sdim/// ... 463193326Sed/// 464193326Sed/// direct-abstract-declarator: 465193326Sed/// direct-abstract-declarator[opt] 466193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 467193326Sed/// exception-specification[opt] 468193326Sed/// direct-abstract-declarator[opt] '[' constant-expression[opt] ']' 469193326Sed/// '(' abstract-declarator ')' 470193326Sed/// 471193326Sed/// ptr-operator: 472193326Sed/// '*' cv-qualifier-seq[opt] 473193326Sed/// '&' 474193326Sed/// [C++0x] '&&' [TODO] 475193326Sed/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt] 476193326Sed/// 477193326Sed/// cv-qualifier-seq: 478193326Sed/// cv-qualifier cv-qualifier-seq[opt] 479193326Sed/// 480193326Sed/// cv-qualifier: 481193326Sed/// 'const' 482193326Sed/// 'volatile' 483193326Sed/// 484193326Sed/// declarator-id: 485218893Sdim/// '...'[opt] id-expression 486193326Sed/// 487193326Sed/// id-expression: 488193326Sed/// unqualified-id 489193326Sed/// qualified-id [TODO] 490193326Sed/// 491193326Sed/// unqualified-id: 492193326Sed/// identifier 493193326Sed/// operator-function-id [TODO] 494193326Sed/// conversion-function-id [TODO] 495193326Sed/// '~' class-name [TODO] 496193326Sed/// template-id [TODO] 497193326Sed/// 498193326SedParser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, 499193326Sed bool mayHaveIdentifier) { 500193326Sed // declarator: 501193326Sed // direct-declarator 502193326Sed // ptr-operator declarator 503193326Sed 504193326Sed while (1) { 505193326Sed if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier)) 506204643Srdivacky if (TryAnnotateCXXScopeToken(true)) 507204643Srdivacky return TPResult::Error(); 508193326Sed 509193326Sed if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) || 510218893Sdim Tok.is(tok::ampamp) || 511193326Sed (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) { 512193326Sed // ptr-operator 513193326Sed ConsumeToken(); 514193326Sed while (Tok.is(tok::kw_const) || 515193326Sed Tok.is(tok::kw_volatile) || 516193326Sed Tok.is(tok::kw_restrict)) 517193326Sed ConsumeToken(); 518193326Sed } else { 519193326Sed break; 520193326Sed } 521193326Sed } 522193326Sed 523193326Sed // direct-declarator: 524193326Sed // direct-abstract-declarator: 525218893Sdim if (Tok.is(tok::ellipsis)) 526218893Sdim ConsumeToken(); 527218893Sdim 528198092Srdivacky if ((Tok.is(tok::identifier) || 529198092Srdivacky (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) && 530198092Srdivacky mayHaveIdentifier) { 531193326Sed // declarator-id 532198092Srdivacky if (Tok.is(tok::annot_cxxscope)) 533198092Srdivacky ConsumeToken(); 534193326Sed ConsumeToken(); 535193326Sed } else if (Tok.is(tok::l_paren)) { 536193326Sed ConsumeParen(); 537193326Sed if (mayBeAbstract && 538193326Sed (Tok.is(tok::r_paren) || // 'int()' is a function. 539193326Sed Tok.is(tok::ellipsis) || // 'int(...)' is a function. 540193326Sed isDeclarationSpecifier())) { // 'int(int)' is a function. 541193326Sed // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 542193326Sed // exception-specification[opt] 543193326Sed TPResult TPR = TryParseFunctionDeclarator(); 544193326Sed if (TPR != TPResult::Ambiguous()) 545193326Sed return TPR; 546193326Sed } else { 547193326Sed // '(' declarator ')' 548193326Sed // '(' attributes declarator ')' 549193326Sed // '(' abstract-declarator ')' 550218893Sdim if (Tok.is(tok::kw___attribute) || 551218893Sdim Tok.is(tok::kw___declspec) || 552218893Sdim Tok.is(tok::kw___cdecl) || 553218893Sdim Tok.is(tok::kw___stdcall) || 554218893Sdim Tok.is(tok::kw___fastcall) || 555218893Sdim Tok.is(tok::kw___thiscall)) 556193326Sed return TPResult::True(); // attributes indicate declaration 557193326Sed TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier); 558193326Sed if (TPR != TPResult::Ambiguous()) 559193326Sed return TPR; 560193326Sed if (Tok.isNot(tok::r_paren)) 561193326Sed return TPResult::False(); 562193326Sed ConsumeParen(); 563193326Sed } 564193326Sed } else if (!mayBeAbstract) { 565193326Sed return TPResult::False(); 566193326Sed } 567193326Sed 568193326Sed while (1) { 569193326Sed TPResult TPR(TPResult::Ambiguous()); 570193326Sed 571218893Sdim // abstract-declarator: ... 572218893Sdim if (Tok.is(tok::ellipsis)) 573218893Sdim ConsumeToken(); 574218893Sdim 575193326Sed if (Tok.is(tok::l_paren)) { 576193326Sed // Check whether we have a function declarator or a possible ctor-style 577193326Sed // initializer that follows the declarator. Note that ctor-style 578193326Sed // initializers are not possible in contexts where abstract declarators 579193326Sed // are allowed. 580193326Sed if (!mayBeAbstract && !isCXXFunctionDeclarator(false/*warnIfAmbiguous*/)) 581193326Sed break; 582193326Sed 583193326Sed // direct-declarator '(' parameter-declaration-clause ')' 584193326Sed // cv-qualifier-seq[opt] exception-specification[opt] 585193326Sed ConsumeParen(); 586193326Sed TPR = TryParseFunctionDeclarator(); 587193326Sed } else if (Tok.is(tok::l_square)) { 588193326Sed // direct-declarator '[' constant-expression[opt] ']' 589193326Sed // direct-abstract-declarator[opt] '[' constant-expression[opt] ']' 590193326Sed TPR = TryParseBracketDeclarator(); 591193326Sed } else { 592193326Sed break; 593193326Sed } 594193326Sed 595193326Sed if (TPR != TPResult::Ambiguous()) 596193326Sed return TPR; 597193326Sed } 598193326Sed 599193326Sed return TPResult::Ambiguous(); 600193326Sed} 601193326Sed 602218893SdimParser::TPResult 603218893SdimParser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { 604218893Sdim switch (Kind) { 605218893Sdim // Obviously starts an expression. 606218893Sdim case tok::numeric_constant: 607218893Sdim case tok::char_constant: 608218893Sdim case tok::string_literal: 609218893Sdim case tok::wide_string_literal: 610218893Sdim case tok::l_square: 611218893Sdim case tok::l_paren: 612218893Sdim case tok::amp: 613218893Sdim case tok::ampamp: 614218893Sdim case tok::star: 615218893Sdim case tok::plus: 616218893Sdim case tok::plusplus: 617218893Sdim case tok::minus: 618218893Sdim case tok::minusminus: 619218893Sdim case tok::tilde: 620218893Sdim case tok::exclaim: 621218893Sdim case tok::kw_sizeof: 622218893Sdim case tok::kw___func__: 623218893Sdim case tok::kw_const_cast: 624218893Sdim case tok::kw_delete: 625218893Sdim case tok::kw_dynamic_cast: 626218893Sdim case tok::kw_false: 627218893Sdim case tok::kw_new: 628218893Sdim case tok::kw_operator: 629218893Sdim case tok::kw_reinterpret_cast: 630218893Sdim case tok::kw_static_cast: 631218893Sdim case tok::kw_this: 632218893Sdim case tok::kw_throw: 633218893Sdim case tok::kw_true: 634218893Sdim case tok::kw_typeid: 635218893Sdim case tok::kw_alignof: 636218893Sdim case tok::kw_noexcept: 637218893Sdim case tok::kw_nullptr: 638218893Sdim case tok::kw___null: 639218893Sdim case tok::kw___alignof: 640218893Sdim case tok::kw___builtin_choose_expr: 641218893Sdim case tok::kw___builtin_offsetof: 642218893Sdim case tok::kw___builtin_types_compatible_p: 643218893Sdim case tok::kw___builtin_va_arg: 644218893Sdim case tok::kw___imag: 645218893Sdim case tok::kw___real: 646218893Sdim case tok::kw___FUNCTION__: 647218893Sdim case tok::kw___PRETTY_FUNCTION__: 648218893Sdim case tok::kw___has_nothrow_assign: 649218893Sdim case tok::kw___has_nothrow_copy: 650218893Sdim case tok::kw___has_nothrow_constructor: 651218893Sdim case tok::kw___has_trivial_assign: 652218893Sdim case tok::kw___has_trivial_copy: 653218893Sdim case tok::kw___has_trivial_constructor: 654218893Sdim case tok::kw___has_trivial_destructor: 655218893Sdim case tok::kw___has_virtual_destructor: 656218893Sdim case tok::kw___is_abstract: 657218893Sdim case tok::kw___is_base_of: 658218893Sdim case tok::kw___is_class: 659218893Sdim case tok::kw___is_convertible_to: 660218893Sdim case tok::kw___is_empty: 661218893Sdim case tok::kw___is_enum: 662221345Sdim case tok::kw___is_literal: 663221345Sdim case tok::kw___is_literal_type: 664218893Sdim case tok::kw___is_pod: 665218893Sdim case tok::kw___is_polymorphic: 666221345Sdim case tok::kw___is_trivial: 667223017Sdim case tok::kw___is_trivially_copyable: 668218893Sdim case tok::kw___is_union: 669218893Sdim case tok::kw___uuidof: 670218893Sdim return TPResult::True(); 671218893Sdim 672218893Sdim // Obviously starts a type-specifier-seq: 673218893Sdim case tok::kw_char: 674218893Sdim case tok::kw_const: 675218893Sdim case tok::kw_double: 676218893Sdim case tok::kw_enum: 677218893Sdim case tok::kw_float: 678218893Sdim case tok::kw_int: 679218893Sdim case tok::kw_long: 680221345Sdim case tok::kw___int64: 681218893Sdim case tok::kw_restrict: 682218893Sdim case tok::kw_short: 683218893Sdim case tok::kw_signed: 684218893Sdim case tok::kw_struct: 685218893Sdim case tok::kw_union: 686218893Sdim case tok::kw_unsigned: 687218893Sdim case tok::kw_void: 688218893Sdim case tok::kw_volatile: 689218893Sdim case tok::kw__Bool: 690218893Sdim case tok::kw__Complex: 691218893Sdim case tok::kw_class: 692218893Sdim case tok::kw_typename: 693218893Sdim case tok::kw_wchar_t: 694218893Sdim case tok::kw_char16_t: 695218893Sdim case tok::kw_char32_t: 696218893Sdim case tok::kw_decltype: 697223017Sdim case tok::kw___underlying_type: 698218893Sdim case tok::kw_thread_local: 699218893Sdim case tok::kw__Decimal32: 700218893Sdim case tok::kw__Decimal64: 701218893Sdim case tok::kw__Decimal128: 702218893Sdim case tok::kw___thread: 703218893Sdim case tok::kw_typeof: 704218893Sdim case tok::kw___cdecl: 705218893Sdim case tok::kw___stdcall: 706218893Sdim case tok::kw___fastcall: 707218893Sdim case tok::kw___thiscall: 708218893Sdim case tok::kw___vector: 709218893Sdim case tok::kw___pixel: 710218893Sdim return TPResult::False(); 711218893Sdim 712218893Sdim default: 713218893Sdim break; 714218893Sdim } 715218893Sdim 716218893Sdim return TPResult::Ambiguous(); 717218893Sdim} 718218893Sdim 719193326Sed/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration 720193326Sed/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could 721193326Sed/// be either a decl-specifier or a function-style cast, and TPResult::Error() 722193326Sed/// if a parsing error was found and reported. 723193326Sed/// 724193326Sed/// decl-specifier: 725193326Sed/// storage-class-specifier 726193326Sed/// type-specifier 727193326Sed/// function-specifier 728193326Sed/// 'friend' 729193326Sed/// 'typedef' 730198954Srdivacky/// [C++0x] 'constexpr' 731193326Sed/// [GNU] attributes declaration-specifiers[opt] 732193326Sed/// 733193326Sed/// storage-class-specifier: 734193326Sed/// 'register' 735193326Sed/// 'static' 736193326Sed/// 'extern' 737193326Sed/// 'mutable' 738193326Sed/// 'auto' 739193326Sed/// [GNU] '__thread' 740193326Sed/// 741193326Sed/// function-specifier: 742193326Sed/// 'inline' 743193326Sed/// 'virtual' 744193326Sed/// 'explicit' 745193326Sed/// 746193326Sed/// typedef-name: 747193326Sed/// identifier 748193326Sed/// 749193326Sed/// type-specifier: 750193326Sed/// simple-type-specifier 751193326Sed/// class-specifier 752193326Sed/// enum-specifier 753193326Sed/// elaborated-type-specifier 754193326Sed/// typename-specifier 755193326Sed/// cv-qualifier 756193326Sed/// 757193326Sed/// simple-type-specifier: 758193326Sed/// '::'[opt] nested-name-specifier[opt] type-name 759193326Sed/// '::'[opt] nested-name-specifier 'template' 760193326Sed/// simple-template-id [TODO] 761193326Sed/// 'char' 762193326Sed/// 'wchar_t' 763193326Sed/// 'bool' 764193326Sed/// 'short' 765193326Sed/// 'int' 766193326Sed/// 'long' 767193326Sed/// 'signed' 768193326Sed/// 'unsigned' 769193326Sed/// 'float' 770193326Sed/// 'double' 771193326Sed/// 'void' 772193326Sed/// [GNU] typeof-specifier 773193326Sed/// [GNU] '_Complex' 774193326Sed/// [C++0x] 'auto' [TODO] 775195099Sed/// [C++0x] 'decltype' ( expression ) 776193326Sed/// 777193326Sed/// type-name: 778193326Sed/// class-name 779193326Sed/// enum-name 780193326Sed/// typedef-name 781193326Sed/// 782193326Sed/// elaborated-type-specifier: 783193326Sed/// class-key '::'[opt] nested-name-specifier[opt] identifier 784193326Sed/// class-key '::'[opt] nested-name-specifier[opt] 'template'[opt] 785193326Sed/// simple-template-id 786193326Sed/// 'enum' '::'[opt] nested-name-specifier[opt] identifier 787193326Sed/// 788193326Sed/// enum-name: 789193326Sed/// identifier 790193326Sed/// 791193326Sed/// enum-specifier: 792193326Sed/// 'enum' identifier[opt] '{' enumerator-list[opt] '}' 793193326Sed/// 'enum' identifier[opt] '{' enumerator-list ',' '}' 794193326Sed/// 795193326Sed/// class-specifier: 796193326Sed/// class-head '{' member-specification[opt] '}' 797193326Sed/// 798193326Sed/// class-head: 799193326Sed/// class-key identifier[opt] base-clause[opt] 800193326Sed/// class-key nested-name-specifier identifier base-clause[opt] 801193326Sed/// class-key nested-name-specifier[opt] simple-template-id 802193326Sed/// base-clause[opt] 803193326Sed/// 804193326Sed/// class-key: 805193326Sed/// 'class' 806193326Sed/// 'struct' 807193326Sed/// 'union' 808193326Sed/// 809193326Sed/// cv-qualifier: 810193326Sed/// 'const' 811193326Sed/// 'volatile' 812193326Sed/// [GNU] restrict 813193326Sed/// 814193326SedParser::TPResult Parser::isCXXDeclarationSpecifier() { 815193326Sed switch (Tok.getKind()) { 816193326Sed case tok::identifier: // foo::bar 817203955Srdivacky // Check for need to substitute AltiVec __vector keyword 818203955Srdivacky // for "vector" identifier. 819203955Srdivacky if (TryAltiVecVectorToken()) 820203955Srdivacky return TPResult::True(); 821203955Srdivacky // Fall through. 822193326Sed case tok::kw_typename: // typename T::type 823193326Sed // Annotate typenames and C++ scope specifiers. If we get one, just 824193326Sed // recurse to handle whatever we get. 825193326Sed if (TryAnnotateTypeOrScopeToken()) 826204643Srdivacky return TPResult::Error(); 827204643Srdivacky if (Tok.is(tok::identifier)) 828204643Srdivacky return TPResult::False(); 829204643Srdivacky return isCXXDeclarationSpecifier(); 830193326Sed 831201361Srdivacky case tok::coloncolon: { // ::foo::bar 832201361Srdivacky const Token &Next = NextToken(); 833201361Srdivacky if (Next.is(tok::kw_new) || // ::new 834201361Srdivacky Next.is(tok::kw_delete)) // ::delete 835201361Srdivacky return TPResult::False(); 836198092Srdivacky 837193326Sed // Annotate typenames and C++ scope specifiers. If we get one, just 838193326Sed // recurse to handle whatever we get. 839193326Sed if (TryAnnotateTypeOrScopeToken()) 840204643Srdivacky return TPResult::Error(); 841204643Srdivacky return isCXXDeclarationSpecifier(); 842201361Srdivacky } 843201361Srdivacky 844193326Sed // decl-specifier: 845193326Sed // storage-class-specifier 846193326Sed // type-specifier 847193326Sed // function-specifier 848193326Sed // 'friend' 849193326Sed // 'typedef' 850198954Srdivacky // 'constexpr' 851193326Sed case tok::kw_friend: 852193326Sed case tok::kw_typedef: 853198954Srdivacky case tok::kw_constexpr: 854193326Sed // storage-class-specifier 855193326Sed case tok::kw_register: 856193326Sed case tok::kw_static: 857193326Sed case tok::kw_extern: 858193326Sed case tok::kw_mutable: 859193326Sed case tok::kw_auto: 860193326Sed case tok::kw___thread: 861193326Sed // function-specifier 862193326Sed case tok::kw_inline: 863193326Sed case tok::kw_virtual: 864193326Sed case tok::kw_explicit: 865193326Sed 866193326Sed // type-specifier: 867193326Sed // simple-type-specifier 868193326Sed // class-specifier 869193326Sed // enum-specifier 870193326Sed // elaborated-type-specifier 871193326Sed // typename-specifier 872193326Sed // cv-qualifier 873193326Sed 874193326Sed // class-specifier 875193326Sed // elaborated-type-specifier 876193326Sed case tok::kw_class: 877193326Sed case tok::kw_struct: 878193326Sed case tok::kw_union: 879193326Sed // enum-specifier 880193326Sed case tok::kw_enum: 881193326Sed // cv-qualifier 882193326Sed case tok::kw_const: 883193326Sed case tok::kw_volatile: 884193326Sed 885193326Sed // GNU 886193326Sed case tok::kw_restrict: 887193326Sed case tok::kw__Complex: 888193326Sed case tok::kw___attribute: 889193326Sed return TPResult::True(); 890198092Srdivacky 891193326Sed // Microsoft 892193326Sed case tok::kw___declspec: 893193326Sed case tok::kw___cdecl: 894193326Sed case tok::kw___stdcall: 895193326Sed case tok::kw___fastcall: 896208600Srdivacky case tok::kw___thiscall: 897194179Sed case tok::kw___w64: 898194179Sed case tok::kw___ptr64: 899194179Sed case tok::kw___forceinline: 900194179Sed return TPResult::True(); 901212904Sdim 902212904Sdim // Borland 903212904Sdim case tok::kw___pascal: 904212904Sdim return TPResult::True(); 905203955Srdivacky 906203955Srdivacky // AltiVec 907203955Srdivacky case tok::kw___vector: 908203955Srdivacky return TPResult::True(); 909193326Sed 910207619Srdivacky case tok::annot_template_id: { 911224145Sdim TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); 912207619Srdivacky if (TemplateId->Kind != TNK_Type_template) 913207619Srdivacky return TPResult::False(); 914207619Srdivacky CXXScopeSpec SS; 915221345Sdim AnnotateTemplateIdTokenAsType(); 916207619Srdivacky assert(Tok.is(tok::annot_typename)); 917207619Srdivacky goto case_typename; 918207619Srdivacky } 919207619Srdivacky 920201361Srdivacky case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed 921201361Srdivacky // We've already annotated a scope; try to annotate a type. 922204643Srdivacky if (TryAnnotateTypeOrScopeToken()) 923204643Srdivacky return TPResult::Error(); 924204643Srdivacky if (!Tok.is(tok::annot_typename)) 925201361Srdivacky return TPResult::False(); 926201361Srdivacky // If that succeeded, fallthrough into the generic simple-type-id case. 927201361Srdivacky 928193326Sed // The ambiguity resides in a simple-type-specifier/typename-specifier 929193326Sed // followed by a '('. The '(' could either be the start of: 930193326Sed // 931193326Sed // direct-declarator: 932193326Sed // '(' declarator ')' 933193326Sed // 934193326Sed // direct-abstract-declarator: 935193326Sed // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 936193326Sed // exception-specification[opt] 937193326Sed // '(' abstract-declarator ')' 938193326Sed // 939193326Sed // or part of a function-style cast expression: 940193326Sed // 941193326Sed // simple-type-specifier '(' expression-list[opt] ')' 942193326Sed // 943193326Sed 944193326Sed // simple-type-specifier: 945193326Sed 946218893Sdim case tok::annot_typename: 947218893Sdim case_typename: 948218893Sdim // In Objective-C, we might have a protocol-qualified type. 949218893Sdim if (getLang().ObjC1 && NextToken().is(tok::less)) { 950218893Sdim // Tentatively parse the 951218893Sdim TentativeParsingAction PA(*this); 952218893Sdim ConsumeToken(); // The type token 953218893Sdim 954218893Sdim TPResult TPR = TryParseProtocolQualifiers(); 955218893Sdim bool isFollowedByParen = Tok.is(tok::l_paren); 956218893Sdim 957218893Sdim PA.Revert(); 958218893Sdim 959218893Sdim if (TPR == TPResult::Error()) 960218893Sdim return TPResult::Error(); 961218893Sdim 962218893Sdim if (isFollowedByParen) 963218893Sdim return TPResult::Ambiguous(); 964218893Sdim 965218893Sdim return TPResult::True(); 966218893Sdim } 967218893Sdim 968193326Sed case tok::kw_char: 969193326Sed case tok::kw_wchar_t: 970198092Srdivacky case tok::kw_char16_t: 971198092Srdivacky case tok::kw_char32_t: 972193326Sed case tok::kw_bool: 973193326Sed case tok::kw_short: 974193326Sed case tok::kw_int: 975193326Sed case tok::kw_long: 976221345Sdim case tok::kw___int64: 977193326Sed case tok::kw_signed: 978193326Sed case tok::kw_unsigned: 979193326Sed case tok::kw_float: 980193326Sed case tok::kw_double: 981193326Sed case tok::kw_void: 982193326Sed if (NextToken().is(tok::l_paren)) 983193326Sed return TPResult::Ambiguous(); 984193326Sed 985218893Sdim if (isStartOfObjCClassMessageMissingOpenBracket()) 986218893Sdim return TPResult::False(); 987218893Sdim 988193326Sed return TPResult::True(); 989193326Sed 990195099Sed // GNU typeof support. 991193326Sed case tok::kw_typeof: { 992193326Sed if (NextToken().isNot(tok::l_paren)) 993193326Sed return TPResult::True(); 994193326Sed 995193326Sed TentativeParsingAction PA(*this); 996193326Sed 997193326Sed TPResult TPR = TryParseTypeofSpecifier(); 998193326Sed bool isFollowedByParen = Tok.is(tok::l_paren); 999193326Sed 1000193326Sed PA.Revert(); 1001193326Sed 1002193326Sed if (TPR == TPResult::Error()) 1003193326Sed return TPResult::Error(); 1004193326Sed 1005193326Sed if (isFollowedByParen) 1006193326Sed return TPResult::Ambiguous(); 1007193326Sed 1008193326Sed return TPResult::True(); 1009193326Sed } 1010193326Sed 1011195099Sed // C++0x decltype support. 1012195099Sed case tok::kw_decltype: 1013195099Sed return TPResult::True(); 1014195099Sed 1015223017Sdim // C++0x type traits support 1016223017Sdim case tok::kw___underlying_type: 1017223017Sdim return TPResult::True(); 1018223017Sdim 1019193326Sed default: 1020193326Sed return TPResult::False(); 1021193326Sed } 1022193326Sed} 1023193326Sed 1024193326Sed/// [GNU] typeof-specifier: 1025193326Sed/// 'typeof' '(' expressions ')' 1026193326Sed/// 'typeof' '(' type-name ')' 1027193326Sed/// 1028193326SedParser::TPResult Parser::TryParseTypeofSpecifier() { 1029193326Sed assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!"); 1030193326Sed ConsumeToken(); 1031193326Sed 1032193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 1033193326Sed // Parse through the parens after 'typeof'. 1034193326Sed ConsumeParen(); 1035193326Sed if (!SkipUntil(tok::r_paren)) 1036193326Sed return TPResult::Error(); 1037193326Sed 1038193326Sed return TPResult::Ambiguous(); 1039193326Sed} 1040193326Sed 1041218893Sdim/// [ObjC] protocol-qualifiers: 1042218893Sdim//// '<' identifier-list '>' 1043218893SdimParser::TPResult Parser::TryParseProtocolQualifiers() { 1044218893Sdim assert(Tok.is(tok::less) && "Expected '<' for qualifier list"); 1045218893Sdim ConsumeToken(); 1046218893Sdim do { 1047218893Sdim if (Tok.isNot(tok::identifier)) 1048218893Sdim return TPResult::Error(); 1049218893Sdim ConsumeToken(); 1050218893Sdim 1051218893Sdim if (Tok.is(tok::comma)) { 1052218893Sdim ConsumeToken(); 1053218893Sdim continue; 1054218893Sdim } 1055218893Sdim 1056218893Sdim if (Tok.is(tok::greater)) { 1057218893Sdim ConsumeToken(); 1058218893Sdim return TPResult::Ambiguous(); 1059218893Sdim } 1060218893Sdim } while (false); 1061218893Sdim 1062218893Sdim return TPResult::Error(); 1063218893Sdim} 1064218893Sdim 1065193326SedParser::TPResult Parser::TryParseDeclarationSpecifier() { 1066193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 1067193326Sed if (TPR != TPResult::Ambiguous()) 1068193326Sed return TPR; 1069193326Sed 1070193326Sed if (Tok.is(tok::kw_typeof)) 1071193326Sed TryParseTypeofSpecifier(); 1072218893Sdim else { 1073193326Sed ConsumeToken(); 1074218893Sdim 1075218893Sdim if (getLang().ObjC1 && Tok.is(tok::less)) 1076218893Sdim TryParseProtocolQualifiers(); 1077218893Sdim } 1078198092Srdivacky 1079193326Sed assert(Tok.is(tok::l_paren) && "Expected '('!"); 1080193326Sed return TPResult::Ambiguous(); 1081193326Sed} 1082193326Sed 1083193326Sed/// isCXXFunctionDeclarator - Disambiguates between a function declarator or 1084193326Sed/// a constructor-style initializer, when parsing declaration statements. 1085193326Sed/// Returns true for function declarator and false for constructor-style 1086193326Sed/// initializer. 1087193326Sed/// If during the disambiguation process a parsing error is encountered, 1088193326Sed/// the function returns true to let the declaration parsing code handle it. 1089193326Sed/// 1090193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 1091193326Sed/// exception-specification[opt] 1092193326Sed/// 1093193326Sedbool Parser::isCXXFunctionDeclarator(bool warnIfAmbiguous) { 1094193326Sed 1095193326Sed // C++ 8.2p1: 1096193326Sed // The ambiguity arising from the similarity between a function-style cast and 1097193326Sed // a declaration mentioned in 6.8 can also occur in the context of a 1098193326Sed // declaration. In that context, the choice is between a function declaration 1099193326Sed // with a redundant set of parentheses around a parameter name and an object 1100193326Sed // declaration with a function-style cast as the initializer. Just as for the 1101193326Sed // ambiguities mentioned in 6.8, the resolution is to consider any construct 1102193326Sed // that could possibly be a declaration a declaration. 1103193326Sed 1104193326Sed TentativeParsingAction PA(*this); 1105193326Sed 1106193326Sed ConsumeParen(); 1107193326Sed TPResult TPR = TryParseParameterDeclarationClause(); 1108193326Sed if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) 1109193326Sed TPR = TPResult::False(); 1110193326Sed 1111193326Sed SourceLocation TPLoc = Tok.getLocation(); 1112193326Sed PA.Revert(); 1113193326Sed 1114193326Sed // In case of an error, let the declaration parsing code handle it. 1115193326Sed if (TPR == TPResult::Error()) 1116193326Sed return true; 1117193326Sed 1118193326Sed if (TPR == TPResult::Ambiguous()) { 1119193326Sed // Function declarator has precedence over constructor-style initializer. 1120193326Sed // Emit a warning just in case the author intended a variable definition. 1121193326Sed if (warnIfAmbiguous) 1122193326Sed Diag(Tok, diag::warn_parens_disambiguated_as_function_decl) 1123193326Sed << SourceRange(Tok.getLocation(), TPLoc); 1124193326Sed return true; 1125193326Sed } 1126193326Sed 1127193326Sed return TPR == TPResult::True(); 1128193326Sed} 1129193326Sed 1130193326Sed/// parameter-declaration-clause: 1131193326Sed/// parameter-declaration-list[opt] '...'[opt] 1132193326Sed/// parameter-declaration-list ',' '...' 1133193326Sed/// 1134193326Sed/// parameter-declaration-list: 1135193326Sed/// parameter-declaration 1136193326Sed/// parameter-declaration-list ',' parameter-declaration 1137193326Sed/// 1138193326Sed/// parameter-declaration: 1139218893Sdim/// decl-specifier-seq declarator attributes[opt] 1140218893Sdim/// decl-specifier-seq declarator attributes[opt] '=' assignment-expression 1141218893Sdim/// decl-specifier-seq abstract-declarator[opt] attributes[opt] 1142218893Sdim/// decl-specifier-seq abstract-declarator[opt] attributes[opt] 1143218893Sdim/// '=' assignment-expression 1144193326Sed/// 1145193326SedParser::TPResult Parser::TryParseParameterDeclarationClause() { 1146193326Sed 1147193326Sed if (Tok.is(tok::r_paren)) 1148193326Sed return TPResult::True(); 1149193326Sed 1150193326Sed // parameter-declaration-list[opt] '...'[opt] 1151193326Sed // parameter-declaration-list ',' '...' 1152193326Sed // 1153193326Sed // parameter-declaration-list: 1154193326Sed // parameter-declaration 1155193326Sed // parameter-declaration-list ',' parameter-declaration 1156193326Sed // 1157193326Sed while (1) { 1158193326Sed // '...'[opt] 1159193326Sed if (Tok.is(tok::ellipsis)) { 1160193326Sed ConsumeToken(); 1161193326Sed return TPResult::True(); // '...' is a sign of a function declarator. 1162193326Sed } 1163193326Sed 1164221345Sdim ParsedAttributes attrs(AttrFactory); 1165218893Sdim MaybeParseMicrosoftAttributes(attrs); 1166218893Sdim 1167193326Sed // decl-specifier-seq 1168193326Sed TPResult TPR = TryParseDeclarationSpecifier(); 1169193326Sed if (TPR != TPResult::Ambiguous()) 1170193326Sed return TPR; 1171193326Sed 1172193326Sed // declarator 1173193326Sed // abstract-declarator[opt] 1174193326Sed TPR = TryParseDeclarator(true/*mayBeAbstract*/); 1175193326Sed if (TPR != TPResult::Ambiguous()) 1176193326Sed return TPR; 1177193326Sed 1178218893Sdim // [GNU] attributes[opt] 1179218893Sdim if (Tok.is(tok::kw___attribute)) 1180218893Sdim return TPResult::True(); 1181218893Sdim 1182193326Sed if (Tok.is(tok::equal)) { 1183193326Sed // '=' assignment-expression 1184193326Sed // Parse through assignment-expression. 1185218893Sdim tok::TokenKind StopToks[2] ={ tok::comma, tok::r_paren }; 1186218893Sdim if (!SkipUntil(StopToks, 2, true/*StopAtSemi*/, true/*DontConsume*/)) 1187193326Sed return TPResult::Error(); 1188193326Sed } 1189193326Sed 1190193326Sed if (Tok.is(tok::ellipsis)) { 1191193326Sed ConsumeToken(); 1192193326Sed return TPResult::True(); // '...' is a sign of a function declarator. 1193193326Sed } 1194193326Sed 1195193326Sed if (Tok.isNot(tok::comma)) 1196193326Sed break; 1197193326Sed ConsumeToken(); // the comma. 1198193326Sed } 1199193326Sed 1200193326Sed return TPResult::Ambiguous(); 1201193326Sed} 1202193326Sed 1203193326Sed/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue 1204193326Sed/// parsing as a function declarator. 1205193326Sed/// If TryParseFunctionDeclarator fully parsed the function declarator, it will 1206193326Sed/// return TPResult::Ambiguous(), otherwise it will return either False() or 1207193326Sed/// Error(). 1208198092Srdivacky/// 1209193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 1210193326Sed/// exception-specification[opt] 1211193326Sed/// 1212193326Sed/// exception-specification: 1213193326Sed/// 'throw' '(' type-id-list[opt] ')' 1214193326Sed/// 1215193326SedParser::TPResult Parser::TryParseFunctionDeclarator() { 1216193326Sed 1217193326Sed // The '(' is already parsed. 1218193326Sed 1219193326Sed TPResult TPR = TryParseParameterDeclarationClause(); 1220193326Sed if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) 1221193326Sed TPR = TPResult::False(); 1222193326Sed 1223193326Sed if (TPR == TPResult::False() || TPR == TPResult::Error()) 1224193326Sed return TPR; 1225193326Sed 1226193326Sed // Parse through the parens. 1227193326Sed if (!SkipUntil(tok::r_paren)) 1228193326Sed return TPResult::Error(); 1229193326Sed 1230193326Sed // cv-qualifier-seq 1231193326Sed while (Tok.is(tok::kw_const) || 1232193326Sed Tok.is(tok::kw_volatile) || 1233193326Sed Tok.is(tok::kw_restrict) ) 1234193326Sed ConsumeToken(); 1235193326Sed 1236218893Sdim // ref-qualifier[opt] 1237218893Sdim if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) 1238218893Sdim ConsumeToken(); 1239218893Sdim 1240193326Sed // exception-specification 1241193326Sed if (Tok.is(tok::kw_throw)) { 1242193326Sed ConsumeToken(); 1243193326Sed if (Tok.isNot(tok::l_paren)) 1244193326Sed return TPResult::Error(); 1245193326Sed 1246193326Sed // Parse through the parens after 'throw'. 1247193326Sed ConsumeParen(); 1248193326Sed if (!SkipUntil(tok::r_paren)) 1249193326Sed return TPResult::Error(); 1250193326Sed } 1251221345Sdim if (Tok.is(tok::kw_noexcept)) { 1252221345Sdim ConsumeToken(); 1253221345Sdim // Possibly an expression as well. 1254221345Sdim if (Tok.is(tok::l_paren)) { 1255221345Sdim // Find the matching rparen. 1256221345Sdim ConsumeParen(); 1257221345Sdim if (!SkipUntil(tok::r_paren)) 1258221345Sdim return TPResult::Error(); 1259221345Sdim } 1260221345Sdim } 1261193326Sed 1262193326Sed return TPResult::Ambiguous(); 1263193326Sed} 1264193326Sed 1265193326Sed/// '[' constant-expression[opt] ']' 1266193326Sed/// 1267193326SedParser::TPResult Parser::TryParseBracketDeclarator() { 1268193326Sed ConsumeBracket(); 1269193326Sed if (!SkipUntil(tok::r_square)) 1270193326Sed return TPResult::Error(); 1271193326Sed 1272193326Sed return TPResult::Ambiguous(); 1273193326Sed} 1274