ParseTentative.cpp revision 204643
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" 17193326Sedusing namespace clang; 18193326Sed 19193326Sed/// isCXXDeclarationStatement - C++-specialized function that disambiguates 20193326Sed/// between a declaration or an expression statement, when parsing function 21193326Sed/// bodies. Returns true for declaration, false for expression. 22193326Sed/// 23193326Sed/// declaration-statement: 24193326Sed/// block-declaration 25193326Sed/// 26193326Sed/// block-declaration: 27193326Sed/// simple-declaration 28193326Sed/// asm-definition 29193326Sed/// namespace-alias-definition 30193326Sed/// using-declaration 31193326Sed/// using-directive 32193326Sed/// [C++0x] static_assert-declaration 33193326Sed/// 34193326Sed/// asm-definition: 35193326Sed/// 'asm' '(' string-literal ')' ';' 36193326Sed/// 37193326Sed/// namespace-alias-definition: 38193326Sed/// 'namespace' identifier = qualified-namespace-specifier ';' 39193326Sed/// 40193326Sed/// using-declaration: 41193326Sed/// 'using' typename[opt] '::'[opt] nested-name-specifier 42193326Sed/// unqualified-id ';' 43193326Sed/// 'using' '::' unqualified-id ; 44193326Sed/// 45193326Sed/// using-directive: 46193326Sed/// 'using' 'namespace' '::'[opt] nested-name-specifier[opt] 47193326Sed/// namespace-name ';' 48193326Sed/// 49193326Sedbool Parser::isCXXDeclarationStatement() { 50193326Sed switch (Tok.getKind()) { 51193326Sed // asm-definition 52193326Sed case tok::kw_asm: 53193326Sed // namespace-alias-definition 54193326Sed case tok::kw_namespace: 55193326Sed // using-declaration 56193326Sed // using-directive 57193326Sed case tok::kw_using: 58199990Srdivacky // static_assert-declaration 59193326Sed case tok::kw_static_assert: 60193326Sed return true; 61199990Srdivacky // simple-declaration 62193326Sed default: 63193326Sed return isCXXSimpleDeclaration(); 64193326Sed } 65193326Sed} 66193326Sed 67193326Sed/// isCXXSimpleDeclaration - C++-specialized function that disambiguates 68193326Sed/// between a simple-declaration or an expression-statement. 69193326Sed/// If during the disambiguation process a parsing error is encountered, 70193326Sed/// the function returns true to let the declaration parsing code handle it. 71193326Sed/// Returns false if the statement is disambiguated as expression. 72193326Sed/// 73193326Sed/// simple-declaration: 74193326Sed/// decl-specifier-seq init-declarator-list[opt] ';' 75193326Sed/// 76193326Sedbool Parser::isCXXSimpleDeclaration() { 77193326Sed // C++ 6.8p1: 78193326Sed // There is an ambiguity in the grammar involving expression-statements and 79193326Sed // declarations: An expression-statement with a function-style explicit type 80193326Sed // conversion (5.2.3) as its leftmost subexpression can be indistinguishable 81193326Sed // from a declaration where the first declarator starts with a '('. In those 82193326Sed // cases the statement is a declaration. [Note: To disambiguate, the whole 83193326Sed // statement might have to be examined to determine if it is an 84193326Sed // expression-statement or a declaration]. 85193326Sed 86193326Sed // C++ 6.8p3: 87193326Sed // The disambiguation is purely syntactic; that is, the meaning of the names 88193326Sed // occurring in such a statement, beyond whether they are type-names or not, 89193326Sed // is not generally used in or changed by the disambiguation. Class 90193326Sed // templates are instantiated as necessary to determine if a qualified name 91193326Sed // is a type-name. Disambiguation precedes parsing, and a statement 92193326Sed // disambiguated as a declaration may be an ill-formed declaration. 93193326Sed 94193326Sed // We don't have to parse all of the decl-specifier-seq part. There's only 95193326Sed // an ambiguity if the first decl-specifier is 96193326Sed // simple-type-specifier/typename-specifier followed by a '(', which may 97193326Sed // indicate a function-style cast expression. 98193326Sed // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such 99193326Sed // a case. 100193326Sed 101193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 102193326Sed if (TPR != TPResult::Ambiguous()) 103193326Sed return TPR != TPResult::False(); // Returns true for TPResult::True() or 104193326Sed // TPResult::Error(). 105193326Sed 106193326Sed // FIXME: Add statistics about the number of ambiguous statements encountered 107193326Sed // and how they were resolved (number of declarations+number of expressions). 108193326Sed 109193326Sed // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 110193326Sed // We need tentative parsing... 111193326Sed 112193326Sed TentativeParsingAction PA(*this); 113193326Sed 114193326Sed TPR = TryParseSimpleDeclaration(); 115193326Sed SourceLocation TentativeParseLoc = Tok.getLocation(); 116193326Sed 117193326Sed PA.Revert(); 118193326Sed 119193326Sed // In case of an error, let the declaration parsing code handle it. 120193326Sed if (TPR == TPResult::Error()) 121193326Sed return true; 122193326Sed 123193326Sed // Declarations take precedence over expressions. 124193326Sed if (TPR == TPResult::Ambiguous()) 125193326Sed TPR = TPResult::True(); 126193326Sed 127193326Sed assert(TPR == TPResult::True() || TPR == TPResult::False()); 128193326Sed return TPR == TPResult::True(); 129193326Sed} 130193326Sed 131193326Sed/// simple-declaration: 132193326Sed/// decl-specifier-seq init-declarator-list[opt] ';' 133193326Sed/// 134193326SedParser::TPResult Parser::TryParseSimpleDeclaration() { 135193326Sed // We know that we have a simple-type-specifier/typename-specifier followed 136193326Sed // by a '('. 137193326Sed assert(isCXXDeclarationSpecifier() == TPResult::Ambiguous()); 138193326Sed 139193326Sed if (Tok.is(tok::kw_typeof)) 140193326Sed TryParseTypeofSpecifier(); 141193326Sed else 142193326Sed ConsumeToken(); 143193326Sed 144193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 145193326Sed 146193326Sed TPResult TPR = TryParseInitDeclaratorList(); 147193326Sed if (TPR != TPResult::Ambiguous()) 148193326Sed return TPR; 149193326Sed 150193326Sed if (Tok.isNot(tok::semi)) 151193326Sed return TPResult::False(); 152193326Sed 153193326Sed return TPResult::Ambiguous(); 154193326Sed} 155193326Sed 156193326Sed/// init-declarator-list: 157193326Sed/// init-declarator 158193326Sed/// init-declarator-list ',' init-declarator 159193326Sed/// 160193326Sed/// init-declarator: 161193326Sed/// declarator initializer[opt] 162193326Sed/// [GNU] declarator simple-asm-expr[opt] attributes[opt] initializer[opt] 163193326Sed/// 164193326Sed/// initializer: 165193326Sed/// '=' initializer-clause 166193326Sed/// '(' expression-list ')' 167193326Sed/// 168193326Sed/// initializer-clause: 169193326Sed/// assignment-expression 170193326Sed/// '{' initializer-list ','[opt] '}' 171193326Sed/// '{' '}' 172193326Sed/// 173193326SedParser::TPResult Parser::TryParseInitDeclaratorList() { 174193326Sed // GCC only examines the first declarator for disambiguation: 175193326Sed // i.e: 176193326Sed // int(x), ++x; // GCC regards it as ill-formed declaration. 177193326Sed // 178193326Sed // Comeau and MSVC will regard the above statement as correct expression. 179193326Sed // Clang examines all of the declarators and also regards the above statement 180193326Sed // as correct expression. 181193326Sed 182193326Sed while (1) { 183193326Sed // declarator 184193326Sed TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/); 185193326Sed if (TPR != TPResult::Ambiguous()) 186193326Sed return TPR; 187193326Sed 188193326Sed // [GNU] simple-asm-expr[opt] attributes[opt] 189193326Sed if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) 190193326Sed return TPResult::True(); 191193326Sed 192193326Sed // initializer[opt] 193193326Sed if (Tok.is(tok::l_paren)) { 194193326Sed // Parse through the parens. 195193326Sed ConsumeParen(); 196193326Sed if (!SkipUntil(tok::r_paren)) 197193326Sed return TPResult::Error(); 198193326Sed } else if (Tok.is(tok::equal)) { 199193326Sed // MSVC won't examine the rest of declarators if '=' is encountered, it 200193326Sed // will conclude that it is a declaration. 201193326Sed // Comeau and Clang will examine the rest of declarators. 202193326Sed // Note that "int(x) = {0}, ++x;" will be interpreted as ill-formed 203193326Sed // expression. 204193326Sed // 205193326Sed // Parse through the initializer-clause. 206193326Sed SkipUntil(tok::comma, true/*StopAtSemi*/, true/*DontConsume*/); 207193326Sed } 208193326Sed 209193326Sed if (Tok.isNot(tok::comma)) 210193326Sed break; 211193326Sed ConsumeToken(); // the comma. 212193326Sed } 213193326Sed 214193326Sed return TPResult::Ambiguous(); 215193326Sed} 216193326Sed 217193326Sed/// isCXXConditionDeclaration - Disambiguates between a declaration or an 218193326Sed/// expression for a condition of a if/switch/while/for statement. 219193326Sed/// If during the disambiguation process a parsing error is encountered, 220193326Sed/// the function returns true to let the declaration parsing code handle it. 221193326Sed/// 222193326Sed/// condition: 223193326Sed/// expression 224193326Sed/// type-specifier-seq declarator '=' assignment-expression 225193326Sed/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] 226193326Sed/// '=' assignment-expression 227193326Sed/// 228193326Sedbool Parser::isCXXConditionDeclaration() { 229193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 230193326Sed if (TPR != TPResult::Ambiguous()) 231193326Sed return TPR != TPResult::False(); // Returns true for TPResult::True() or 232193326Sed // TPResult::Error(). 233193326Sed 234193326Sed // FIXME: Add statistics about the number of ambiguous statements encountered 235193326Sed // and how they were resolved (number of declarations+number of expressions). 236193326Sed 237193326Sed // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 238193326Sed // We need tentative parsing... 239193326Sed 240193326Sed TentativeParsingAction PA(*this); 241193326Sed 242193326Sed // type-specifier-seq 243193326Sed if (Tok.is(tok::kw_typeof)) 244193326Sed TryParseTypeofSpecifier(); 245193326Sed else 246193326Sed ConsumeToken(); 247193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 248193326Sed 249193326Sed // declarator 250193326Sed TPR = TryParseDeclarator(false/*mayBeAbstract*/); 251193326Sed 252193326Sed // In case of an error, let the declaration parsing code handle it. 253193326Sed if (TPR == TPResult::Error()) 254193326Sed TPR = TPResult::True(); 255193326Sed 256193326Sed if (TPR == TPResult::Ambiguous()) { 257193326Sed // '=' 258193326Sed // [GNU] simple-asm-expr[opt] attributes[opt] 259193326Sed if (Tok.is(tok::equal) || 260193326Sed Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) 261193326Sed TPR = TPResult::True(); 262193326Sed else 263193326Sed TPR = TPResult::False(); 264193326Sed } 265193326Sed 266193326Sed PA.Revert(); 267193326Sed 268193326Sed assert(TPR == TPResult::True() || TPR == TPResult::False()); 269193326Sed return TPR == TPResult::True(); 270193326Sed} 271193326Sed 272198092Srdivacky /// \brief Determine whether the next set of tokens contains a type-id. 273193326Sed /// 274193326Sed /// The context parameter states what context we're parsing right 275193326Sed /// now, which affects how this routine copes with the token 276193326Sed /// following the type-id. If the context is TypeIdInParens, we have 277193326Sed /// already parsed the '(' and we will cease lookahead when we hit 278193326Sed /// the corresponding ')'. If the context is 279193326Sed /// TypeIdAsTemplateArgument, we've already parsed the '<' or ',' 280193326Sed /// before this template argument, and will cease lookahead when we 281193326Sed /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id 282193326Sed /// and false for an expression. If during the disambiguation 283193326Sed /// process a parsing error is encountered, the function returns 284193326Sed /// true to let the declaration parsing code handle it. 285193326Sed /// 286193326Sed /// type-id: 287193326Sed /// type-specifier-seq abstract-declarator[opt] 288193326Sed /// 289193326Sedbool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { 290198092Srdivacky 291193326Sed isAmbiguous = false; 292193326Sed 293193326Sed // C++ 8.2p2: 294193326Sed // The ambiguity arising from the similarity between a function-style cast and 295193326Sed // a type-id can occur in different contexts. The ambiguity appears as a 296193326Sed // choice between a function-style cast expression and a declaration of a 297193326Sed // type. The resolution is that any construct that could possibly be a type-id 298193326Sed // in its syntactic context shall be considered a type-id. 299193326Sed 300193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 301193326Sed if (TPR != TPResult::Ambiguous()) 302193326Sed return TPR != TPResult::False(); // Returns true for TPResult::True() or 303193326Sed // TPResult::Error(). 304193326Sed 305193326Sed // FIXME: Add statistics about the number of ambiguous statements encountered 306193326Sed // and how they were resolved (number of declarations+number of expressions). 307193326Sed 308193326Sed // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 309193326Sed // We need tentative parsing... 310193326Sed 311193326Sed TentativeParsingAction PA(*this); 312193326Sed 313193326Sed // type-specifier-seq 314193326Sed if (Tok.is(tok::kw_typeof)) 315193326Sed TryParseTypeofSpecifier(); 316193326Sed else 317193326Sed ConsumeToken(); 318193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 319193326Sed 320193326Sed // declarator 321193326Sed TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/); 322193326Sed 323193326Sed // In case of an error, let the declaration parsing code handle it. 324193326Sed if (TPR == TPResult::Error()) 325193326Sed TPR = TPResult::True(); 326193326Sed 327193326Sed if (TPR == TPResult::Ambiguous()) { 328193326Sed // We are supposed to be inside parens, so if after the abstract declarator 329193326Sed // we encounter a ')' this is a type-id, otherwise it's an expression. 330193326Sed if (Context == TypeIdInParens && Tok.is(tok::r_paren)) { 331193326Sed TPR = TPResult::True(); 332193326Sed isAmbiguous = true; 333193326Sed 334193326Sed // We are supposed to be inside a template argument, so if after 335193326Sed // the abstract declarator we encounter a '>', '>>' (in C++0x), or 336193326Sed // ',', this is a type-id. Otherwise, it's an expression. 337193326Sed } else if (Context == TypeIdAsTemplateArgument && 338193326Sed (Tok.is(tok::greater) || Tok.is(tok::comma) || 339193326Sed (getLang().CPlusPlus0x && Tok.is(tok::greatergreater)))) { 340193326Sed TPR = TPResult::True(); 341193326Sed isAmbiguous = true; 342193326Sed 343193326Sed } else 344193326Sed TPR = TPResult::False(); 345193326Sed } 346193326Sed 347193326Sed PA.Revert(); 348193326Sed 349193326Sed assert(TPR == TPResult::True() || TPR == TPResult::False()); 350193326Sed return TPR == TPResult::True(); 351193326Sed} 352193326Sed 353199990Srdivacky/// isCXX0XAttributeSpecifier - returns true if this is a C++0x 354199990Srdivacky/// attribute-specifier. By default, unless in Obj-C++, only a cursory check is 355199990Srdivacky/// performed that will simply return true if a [[ is seen. Currently C++ has no 356199990Srdivacky/// syntactical ambiguities from this check, but it may inhibit error recovery. 357199990Srdivacky/// If CheckClosing is true, a check is made for closing ]] brackets. 358199990Srdivacky/// 359199990Srdivacky/// If given, After is set to the token after the attribute-specifier so that 360199990Srdivacky/// appropriate parsing decisions can be made; it is left untouched if false is 361199990Srdivacky/// returned. 362199990Srdivacky/// 363199990Srdivacky/// FIXME: If an error is in the closing ]] brackets, the program assumes 364199990Srdivacky/// the absence of an attribute-specifier, which can cause very yucky errors 365199990Srdivacky/// to occur. 366199990Srdivacky/// 367199990Srdivacky/// [C++0x] attribute-specifier: 368199990Srdivacky/// '[' '[' attribute-list ']' ']' 369199990Srdivacky/// 370199990Srdivacky/// [C++0x] attribute-list: 371199990Srdivacky/// attribute[opt] 372199990Srdivacky/// attribute-list ',' attribute[opt] 373199990Srdivacky/// 374199990Srdivacky/// [C++0x] attribute: 375199990Srdivacky/// attribute-token attribute-argument-clause[opt] 376199990Srdivacky/// 377199990Srdivacky/// [C++0x] attribute-token: 378199990Srdivacky/// identifier 379199990Srdivacky/// attribute-scoped-token 380199990Srdivacky/// 381199990Srdivacky/// [C++0x] attribute-scoped-token: 382199990Srdivacky/// attribute-namespace '::' identifier 383199990Srdivacky/// 384199990Srdivacky/// [C++0x] attribute-namespace: 385199990Srdivacky/// identifier 386199990Srdivacky/// 387199990Srdivacky/// [C++0x] attribute-argument-clause: 388199990Srdivacky/// '(' balanced-token-seq ')' 389199990Srdivacky/// 390199990Srdivacky/// [C++0x] balanced-token-seq: 391199990Srdivacky/// balanced-token 392199990Srdivacky/// balanced-token-seq balanced-token 393199990Srdivacky/// 394199990Srdivacky/// [C++0x] balanced-token: 395199990Srdivacky/// '(' balanced-token-seq ')' 396199990Srdivacky/// '[' balanced-token-seq ']' 397199990Srdivacky/// '{' balanced-token-seq '}' 398199990Srdivacky/// any token but '(', ')', '[', ']', '{', or '}' 399199990Srdivackybool Parser::isCXX0XAttributeSpecifier (bool CheckClosing, 400199990Srdivacky tok::TokenKind *After) { 401199990Srdivacky if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) 402199990Srdivacky return false; 403199990Srdivacky 404199990Srdivacky // No tentative parsing if we don't need to look for ]] 405199990Srdivacky if (!CheckClosing && !getLang().ObjC1) 406199990Srdivacky return true; 407199990Srdivacky 408199990Srdivacky struct TentativeReverter { 409199990Srdivacky TentativeParsingAction PA; 410199990Srdivacky 411199990Srdivacky TentativeReverter (Parser& P) 412199990Srdivacky : PA(P) 413199990Srdivacky {} 414199990Srdivacky ~TentativeReverter () { 415199990Srdivacky PA.Revert(); 416199990Srdivacky } 417199990Srdivacky } R(*this); 418199990Srdivacky 419199990Srdivacky // Opening brackets were checked for above. 420199990Srdivacky ConsumeBracket(); 421199990Srdivacky ConsumeBracket(); 422199990Srdivacky 423199990Srdivacky // SkipUntil will handle balanced tokens, which are guaranteed in attributes. 424199990Srdivacky SkipUntil(tok::r_square, false); 425199990Srdivacky 426199990Srdivacky if (Tok.isNot(tok::r_square)) 427199990Srdivacky return false; 428199990Srdivacky ConsumeBracket(); 429199990Srdivacky 430199990Srdivacky if (After) 431199990Srdivacky *After = Tok.getKind(); 432199990Srdivacky 433199990Srdivacky return true; 434199990Srdivacky} 435199990Srdivacky 436193326Sed/// declarator: 437193326Sed/// direct-declarator 438193326Sed/// ptr-operator declarator 439193326Sed/// 440193326Sed/// direct-declarator: 441193326Sed/// declarator-id 442193326Sed/// direct-declarator '(' parameter-declaration-clause ')' 443193326Sed/// cv-qualifier-seq[opt] exception-specification[opt] 444193326Sed/// direct-declarator '[' constant-expression[opt] ']' 445193326Sed/// '(' declarator ')' 446193326Sed/// [GNU] '(' attributes declarator ')' 447193326Sed/// 448193326Sed/// abstract-declarator: 449193326Sed/// ptr-operator abstract-declarator[opt] 450193326Sed/// direct-abstract-declarator 451193326Sed/// 452193326Sed/// direct-abstract-declarator: 453193326Sed/// direct-abstract-declarator[opt] 454193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 455193326Sed/// exception-specification[opt] 456193326Sed/// direct-abstract-declarator[opt] '[' constant-expression[opt] ']' 457193326Sed/// '(' abstract-declarator ')' 458193326Sed/// 459193326Sed/// ptr-operator: 460193326Sed/// '*' cv-qualifier-seq[opt] 461193326Sed/// '&' 462193326Sed/// [C++0x] '&&' [TODO] 463193326Sed/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt] 464193326Sed/// 465193326Sed/// cv-qualifier-seq: 466193326Sed/// cv-qualifier cv-qualifier-seq[opt] 467193326Sed/// 468193326Sed/// cv-qualifier: 469193326Sed/// 'const' 470193326Sed/// 'volatile' 471193326Sed/// 472193326Sed/// declarator-id: 473193326Sed/// id-expression 474193326Sed/// 475193326Sed/// id-expression: 476193326Sed/// unqualified-id 477193326Sed/// qualified-id [TODO] 478193326Sed/// 479193326Sed/// unqualified-id: 480193326Sed/// identifier 481193326Sed/// operator-function-id [TODO] 482193326Sed/// conversion-function-id [TODO] 483193326Sed/// '~' class-name [TODO] 484193326Sed/// template-id [TODO] 485193326Sed/// 486193326SedParser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, 487193326Sed bool mayHaveIdentifier) { 488193326Sed // declarator: 489193326Sed // direct-declarator 490193326Sed // ptr-operator declarator 491193326Sed 492193326Sed while (1) { 493193326Sed if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier)) 494204643Srdivacky if (TryAnnotateCXXScopeToken(true)) 495204643Srdivacky return TPResult::Error(); 496193326Sed 497193326Sed if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) || 498193326Sed (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) { 499193326Sed // ptr-operator 500193326Sed ConsumeToken(); 501193326Sed while (Tok.is(tok::kw_const) || 502193326Sed Tok.is(tok::kw_volatile) || 503193326Sed Tok.is(tok::kw_restrict)) 504193326Sed ConsumeToken(); 505193326Sed } else { 506193326Sed break; 507193326Sed } 508193326Sed } 509193326Sed 510193326Sed // direct-declarator: 511193326Sed // direct-abstract-declarator: 512193326Sed 513198092Srdivacky if ((Tok.is(tok::identifier) || 514198092Srdivacky (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) && 515198092Srdivacky mayHaveIdentifier) { 516193326Sed // declarator-id 517198092Srdivacky if (Tok.is(tok::annot_cxxscope)) 518198092Srdivacky ConsumeToken(); 519193326Sed ConsumeToken(); 520193326Sed } else if (Tok.is(tok::l_paren)) { 521193326Sed ConsumeParen(); 522193326Sed if (mayBeAbstract && 523193326Sed (Tok.is(tok::r_paren) || // 'int()' is a function. 524193326Sed Tok.is(tok::ellipsis) || // 'int(...)' is a function. 525193326Sed isDeclarationSpecifier())) { // 'int(int)' is a function. 526193326Sed // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 527193326Sed // exception-specification[opt] 528193326Sed TPResult TPR = TryParseFunctionDeclarator(); 529193326Sed if (TPR != TPResult::Ambiguous()) 530193326Sed return TPR; 531193326Sed } else { 532193326Sed // '(' declarator ')' 533193326Sed // '(' attributes declarator ')' 534193326Sed // '(' abstract-declarator ')' 535193326Sed if (Tok.is(tok::kw___attribute)) 536193326Sed return TPResult::True(); // attributes indicate declaration 537193326Sed TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier); 538193326Sed if (TPR != TPResult::Ambiguous()) 539193326Sed return TPR; 540193326Sed if (Tok.isNot(tok::r_paren)) 541193326Sed return TPResult::False(); 542193326Sed ConsumeParen(); 543193326Sed } 544193326Sed } else if (!mayBeAbstract) { 545193326Sed return TPResult::False(); 546193326Sed } 547193326Sed 548193326Sed while (1) { 549193326Sed TPResult TPR(TPResult::Ambiguous()); 550193326Sed 551193326Sed if (Tok.is(tok::l_paren)) { 552193326Sed // Check whether we have a function declarator or a possible ctor-style 553193326Sed // initializer that follows the declarator. Note that ctor-style 554193326Sed // initializers are not possible in contexts where abstract declarators 555193326Sed // are allowed. 556193326Sed if (!mayBeAbstract && !isCXXFunctionDeclarator(false/*warnIfAmbiguous*/)) 557193326Sed break; 558193326Sed 559193326Sed // direct-declarator '(' parameter-declaration-clause ')' 560193326Sed // cv-qualifier-seq[opt] exception-specification[opt] 561193326Sed ConsumeParen(); 562193326Sed TPR = TryParseFunctionDeclarator(); 563193326Sed } else if (Tok.is(tok::l_square)) { 564193326Sed // direct-declarator '[' constant-expression[opt] ']' 565193326Sed // direct-abstract-declarator[opt] '[' constant-expression[opt] ']' 566193326Sed TPR = TryParseBracketDeclarator(); 567193326Sed } else { 568193326Sed break; 569193326Sed } 570193326Sed 571193326Sed if (TPR != TPResult::Ambiguous()) 572193326Sed return TPR; 573193326Sed } 574193326Sed 575193326Sed return TPResult::Ambiguous(); 576193326Sed} 577193326Sed 578193326Sed/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration 579193326Sed/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could 580193326Sed/// be either a decl-specifier or a function-style cast, and TPResult::Error() 581193326Sed/// if a parsing error was found and reported. 582193326Sed/// 583193326Sed/// decl-specifier: 584193326Sed/// storage-class-specifier 585193326Sed/// type-specifier 586193326Sed/// function-specifier 587193326Sed/// 'friend' 588193326Sed/// 'typedef' 589198954Srdivacky/// [C++0x] 'constexpr' 590193326Sed/// [GNU] attributes declaration-specifiers[opt] 591193326Sed/// 592193326Sed/// storage-class-specifier: 593193326Sed/// 'register' 594193326Sed/// 'static' 595193326Sed/// 'extern' 596193326Sed/// 'mutable' 597193326Sed/// 'auto' 598193326Sed/// [GNU] '__thread' 599193326Sed/// 600193326Sed/// function-specifier: 601193326Sed/// 'inline' 602193326Sed/// 'virtual' 603193326Sed/// 'explicit' 604193326Sed/// 605193326Sed/// typedef-name: 606193326Sed/// identifier 607193326Sed/// 608193326Sed/// type-specifier: 609193326Sed/// simple-type-specifier 610193326Sed/// class-specifier 611193326Sed/// enum-specifier 612193326Sed/// elaborated-type-specifier 613193326Sed/// typename-specifier 614193326Sed/// cv-qualifier 615193326Sed/// 616193326Sed/// simple-type-specifier: 617193326Sed/// '::'[opt] nested-name-specifier[opt] type-name 618193326Sed/// '::'[opt] nested-name-specifier 'template' 619193326Sed/// simple-template-id [TODO] 620193326Sed/// 'char' 621193326Sed/// 'wchar_t' 622193326Sed/// 'bool' 623193326Sed/// 'short' 624193326Sed/// 'int' 625193326Sed/// 'long' 626193326Sed/// 'signed' 627193326Sed/// 'unsigned' 628193326Sed/// 'float' 629193326Sed/// 'double' 630193326Sed/// 'void' 631193326Sed/// [GNU] typeof-specifier 632193326Sed/// [GNU] '_Complex' 633193326Sed/// [C++0x] 'auto' [TODO] 634195099Sed/// [C++0x] 'decltype' ( expression ) 635193326Sed/// 636193326Sed/// type-name: 637193326Sed/// class-name 638193326Sed/// enum-name 639193326Sed/// typedef-name 640193326Sed/// 641193326Sed/// elaborated-type-specifier: 642193326Sed/// class-key '::'[opt] nested-name-specifier[opt] identifier 643193326Sed/// class-key '::'[opt] nested-name-specifier[opt] 'template'[opt] 644193326Sed/// simple-template-id 645193326Sed/// 'enum' '::'[opt] nested-name-specifier[opt] identifier 646193326Sed/// 647193326Sed/// enum-name: 648193326Sed/// identifier 649193326Sed/// 650193326Sed/// enum-specifier: 651193326Sed/// 'enum' identifier[opt] '{' enumerator-list[opt] '}' 652193326Sed/// 'enum' identifier[opt] '{' enumerator-list ',' '}' 653193326Sed/// 654193326Sed/// class-specifier: 655193326Sed/// class-head '{' member-specification[opt] '}' 656193326Sed/// 657193326Sed/// class-head: 658193326Sed/// class-key identifier[opt] base-clause[opt] 659193326Sed/// class-key nested-name-specifier identifier base-clause[opt] 660193326Sed/// class-key nested-name-specifier[opt] simple-template-id 661193326Sed/// base-clause[opt] 662193326Sed/// 663193326Sed/// class-key: 664193326Sed/// 'class' 665193326Sed/// 'struct' 666193326Sed/// 'union' 667193326Sed/// 668193326Sed/// cv-qualifier: 669193326Sed/// 'const' 670193326Sed/// 'volatile' 671193326Sed/// [GNU] restrict 672193326Sed/// 673193326SedParser::TPResult Parser::isCXXDeclarationSpecifier() { 674193326Sed switch (Tok.getKind()) { 675193326Sed case tok::identifier: // foo::bar 676203955Srdivacky // Check for need to substitute AltiVec __vector keyword 677203955Srdivacky // for "vector" identifier. 678203955Srdivacky if (TryAltiVecVectorToken()) 679203955Srdivacky return TPResult::True(); 680203955Srdivacky // Fall through. 681193326Sed case tok::kw_typename: // typename T::type 682193326Sed // Annotate typenames and C++ scope specifiers. If we get one, just 683193326Sed // recurse to handle whatever we get. 684193326Sed if (TryAnnotateTypeOrScopeToken()) 685204643Srdivacky return TPResult::Error(); 686204643Srdivacky if (Tok.is(tok::identifier)) 687204643Srdivacky return TPResult::False(); 688204643Srdivacky return isCXXDeclarationSpecifier(); 689193326Sed 690201361Srdivacky case tok::coloncolon: { // ::foo::bar 691201361Srdivacky const Token &Next = NextToken(); 692201361Srdivacky if (Next.is(tok::kw_new) || // ::new 693201361Srdivacky Next.is(tok::kw_delete)) // ::delete 694201361Srdivacky return TPResult::False(); 695198092Srdivacky 696193326Sed // Annotate typenames and C++ scope specifiers. If we get one, just 697193326Sed // recurse to handle whatever we get. 698193326Sed if (TryAnnotateTypeOrScopeToken()) 699204643Srdivacky return TPResult::Error(); 700204643Srdivacky return isCXXDeclarationSpecifier(); 701201361Srdivacky } 702201361Srdivacky 703193326Sed // decl-specifier: 704193326Sed // storage-class-specifier 705193326Sed // type-specifier 706193326Sed // function-specifier 707193326Sed // 'friend' 708193326Sed // 'typedef' 709198954Srdivacky // 'constexpr' 710193326Sed case tok::kw_friend: 711193326Sed case tok::kw_typedef: 712198954Srdivacky case tok::kw_constexpr: 713193326Sed // storage-class-specifier 714193326Sed case tok::kw_register: 715193326Sed case tok::kw_static: 716193326Sed case tok::kw_extern: 717193326Sed case tok::kw_mutable: 718193326Sed case tok::kw_auto: 719193326Sed case tok::kw___thread: 720193326Sed // function-specifier 721193326Sed case tok::kw_inline: 722193326Sed case tok::kw_virtual: 723193326Sed case tok::kw_explicit: 724193326Sed 725193326Sed // type-specifier: 726193326Sed // simple-type-specifier 727193326Sed // class-specifier 728193326Sed // enum-specifier 729193326Sed // elaborated-type-specifier 730193326Sed // typename-specifier 731193326Sed // cv-qualifier 732193326Sed 733193326Sed // class-specifier 734193326Sed // elaborated-type-specifier 735193326Sed case tok::kw_class: 736193326Sed case tok::kw_struct: 737193326Sed case tok::kw_union: 738193326Sed // enum-specifier 739193326Sed case tok::kw_enum: 740193326Sed // cv-qualifier 741193326Sed case tok::kw_const: 742193326Sed case tok::kw_volatile: 743193326Sed 744193326Sed // GNU 745193326Sed case tok::kw_restrict: 746193326Sed case tok::kw__Complex: 747193326Sed case tok::kw___attribute: 748193326Sed return TPResult::True(); 749198092Srdivacky 750193326Sed // Microsoft 751193326Sed case tok::kw___declspec: 752193326Sed case tok::kw___cdecl: 753193326Sed case tok::kw___stdcall: 754193326Sed case tok::kw___fastcall: 755194179Sed case tok::kw___w64: 756194179Sed case tok::kw___ptr64: 757194179Sed case tok::kw___forceinline: 758194179Sed return TPResult::True(); 759203955Srdivacky 760203955Srdivacky // AltiVec 761203955Srdivacky case tok::kw___vector: 762203955Srdivacky return TPResult::True(); 763193326Sed 764201361Srdivacky case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed 765201361Srdivacky // We've already annotated a scope; try to annotate a type. 766204643Srdivacky if (TryAnnotateTypeOrScopeToken()) 767204643Srdivacky return TPResult::Error(); 768204643Srdivacky if (!Tok.is(tok::annot_typename)) 769201361Srdivacky return TPResult::False(); 770201361Srdivacky // If that succeeded, fallthrough into the generic simple-type-id case. 771201361Srdivacky 772193326Sed // The ambiguity resides in a simple-type-specifier/typename-specifier 773193326Sed // followed by a '('. The '(' could either be the start of: 774193326Sed // 775193326Sed // direct-declarator: 776193326Sed // '(' declarator ')' 777193326Sed // 778193326Sed // direct-abstract-declarator: 779193326Sed // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 780193326Sed // exception-specification[opt] 781193326Sed // '(' abstract-declarator ')' 782193326Sed // 783193326Sed // or part of a function-style cast expression: 784193326Sed // 785193326Sed // simple-type-specifier '(' expression-list[opt] ')' 786193326Sed // 787193326Sed 788193326Sed // simple-type-specifier: 789193326Sed 790193326Sed case tok::kw_char: 791193326Sed case tok::kw_wchar_t: 792198092Srdivacky case tok::kw_char16_t: 793198092Srdivacky case tok::kw_char32_t: 794193326Sed case tok::kw_bool: 795193326Sed case tok::kw_short: 796193326Sed case tok::kw_int: 797193326Sed case tok::kw_long: 798193326Sed case tok::kw_signed: 799193326Sed case tok::kw_unsigned: 800193326Sed case tok::kw_float: 801193326Sed case tok::kw_double: 802193326Sed case tok::kw_void: 803193326Sed case tok::annot_typename: 804193326Sed if (NextToken().is(tok::l_paren)) 805193326Sed return TPResult::Ambiguous(); 806193326Sed 807193326Sed return TPResult::True(); 808193326Sed 809195099Sed // GNU typeof support. 810193326Sed case tok::kw_typeof: { 811193326Sed if (NextToken().isNot(tok::l_paren)) 812193326Sed return TPResult::True(); 813193326Sed 814193326Sed TentativeParsingAction PA(*this); 815193326Sed 816193326Sed TPResult TPR = TryParseTypeofSpecifier(); 817193326Sed bool isFollowedByParen = Tok.is(tok::l_paren); 818193326Sed 819193326Sed PA.Revert(); 820193326Sed 821193326Sed if (TPR == TPResult::Error()) 822193326Sed return TPResult::Error(); 823193326Sed 824193326Sed if (isFollowedByParen) 825193326Sed return TPResult::Ambiguous(); 826193326Sed 827193326Sed return TPResult::True(); 828193326Sed } 829193326Sed 830195099Sed // C++0x decltype support. 831195099Sed case tok::kw_decltype: 832195099Sed return TPResult::True(); 833195099Sed 834193326Sed default: 835193326Sed return TPResult::False(); 836193326Sed } 837193326Sed} 838193326Sed 839193326Sed/// [GNU] typeof-specifier: 840193326Sed/// 'typeof' '(' expressions ')' 841193326Sed/// 'typeof' '(' type-name ')' 842193326Sed/// 843193326SedParser::TPResult Parser::TryParseTypeofSpecifier() { 844193326Sed assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!"); 845193326Sed ConsumeToken(); 846193326Sed 847193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 848193326Sed // Parse through the parens after 'typeof'. 849193326Sed ConsumeParen(); 850193326Sed if (!SkipUntil(tok::r_paren)) 851193326Sed return TPResult::Error(); 852193326Sed 853193326Sed return TPResult::Ambiguous(); 854193326Sed} 855193326Sed 856193326SedParser::TPResult Parser::TryParseDeclarationSpecifier() { 857193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 858193326Sed if (TPR != TPResult::Ambiguous()) 859193326Sed return TPR; 860193326Sed 861193326Sed if (Tok.is(tok::kw_typeof)) 862193326Sed TryParseTypeofSpecifier(); 863193326Sed else 864193326Sed ConsumeToken(); 865198092Srdivacky 866193326Sed assert(Tok.is(tok::l_paren) && "Expected '('!"); 867193326Sed return TPResult::Ambiguous(); 868193326Sed} 869193326Sed 870193326Sed/// isCXXFunctionDeclarator - Disambiguates between a function declarator or 871193326Sed/// a constructor-style initializer, when parsing declaration statements. 872193326Sed/// Returns true for function declarator and false for constructor-style 873193326Sed/// initializer. 874193326Sed/// If during the disambiguation process a parsing error is encountered, 875193326Sed/// the function returns true to let the declaration parsing code handle it. 876193326Sed/// 877193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 878193326Sed/// exception-specification[opt] 879193326Sed/// 880193326Sedbool Parser::isCXXFunctionDeclarator(bool warnIfAmbiguous) { 881193326Sed 882193326Sed // C++ 8.2p1: 883193326Sed // The ambiguity arising from the similarity between a function-style cast and 884193326Sed // a declaration mentioned in 6.8 can also occur in the context of a 885193326Sed // declaration. In that context, the choice is between a function declaration 886193326Sed // with a redundant set of parentheses around a parameter name and an object 887193326Sed // declaration with a function-style cast as the initializer. Just as for the 888193326Sed // ambiguities mentioned in 6.8, the resolution is to consider any construct 889193326Sed // that could possibly be a declaration a declaration. 890193326Sed 891193326Sed TentativeParsingAction PA(*this); 892193326Sed 893193326Sed ConsumeParen(); 894193326Sed TPResult TPR = TryParseParameterDeclarationClause(); 895193326Sed if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) 896193326Sed TPR = TPResult::False(); 897193326Sed 898193326Sed SourceLocation TPLoc = Tok.getLocation(); 899193326Sed PA.Revert(); 900193326Sed 901193326Sed // In case of an error, let the declaration parsing code handle it. 902193326Sed if (TPR == TPResult::Error()) 903193326Sed return true; 904193326Sed 905193326Sed if (TPR == TPResult::Ambiguous()) { 906193326Sed // Function declarator has precedence over constructor-style initializer. 907193326Sed // Emit a warning just in case the author intended a variable definition. 908193326Sed if (warnIfAmbiguous) 909193326Sed Diag(Tok, diag::warn_parens_disambiguated_as_function_decl) 910193326Sed << SourceRange(Tok.getLocation(), TPLoc); 911193326Sed return true; 912193326Sed } 913193326Sed 914193326Sed return TPR == TPResult::True(); 915193326Sed} 916193326Sed 917193326Sed/// parameter-declaration-clause: 918193326Sed/// parameter-declaration-list[opt] '...'[opt] 919193326Sed/// parameter-declaration-list ',' '...' 920193326Sed/// 921193326Sed/// parameter-declaration-list: 922193326Sed/// parameter-declaration 923193326Sed/// parameter-declaration-list ',' parameter-declaration 924193326Sed/// 925193326Sed/// parameter-declaration: 926193326Sed/// decl-specifier-seq declarator 927193326Sed/// decl-specifier-seq declarator '=' assignment-expression 928193326Sed/// decl-specifier-seq abstract-declarator[opt] 929193326Sed/// decl-specifier-seq abstract-declarator[opt] '=' assignment-expression 930193326Sed/// 931193326SedParser::TPResult Parser::TryParseParameterDeclarationClause() { 932193326Sed 933193326Sed if (Tok.is(tok::r_paren)) 934193326Sed return TPResult::True(); 935193326Sed 936193326Sed // parameter-declaration-list[opt] '...'[opt] 937193326Sed // parameter-declaration-list ',' '...' 938193326Sed // 939193326Sed // parameter-declaration-list: 940193326Sed // parameter-declaration 941193326Sed // parameter-declaration-list ',' parameter-declaration 942193326Sed // 943193326Sed while (1) { 944193326Sed // '...'[opt] 945193326Sed if (Tok.is(tok::ellipsis)) { 946193326Sed ConsumeToken(); 947193326Sed return TPResult::True(); // '...' is a sign of a function declarator. 948193326Sed } 949193326Sed 950193326Sed // decl-specifier-seq 951193326Sed TPResult TPR = TryParseDeclarationSpecifier(); 952193326Sed if (TPR != TPResult::Ambiguous()) 953193326Sed return TPR; 954193326Sed 955193326Sed // declarator 956193326Sed // abstract-declarator[opt] 957193326Sed TPR = TryParseDeclarator(true/*mayBeAbstract*/); 958193326Sed if (TPR != TPResult::Ambiguous()) 959193326Sed return TPR; 960193326Sed 961193326Sed if (Tok.is(tok::equal)) { 962193326Sed // '=' assignment-expression 963193326Sed // Parse through assignment-expression. 964193326Sed tok::TokenKind StopToks[3] ={ tok::comma, tok::ellipsis, tok::r_paren }; 965193326Sed if (!SkipUntil(StopToks, 3, true/*StopAtSemi*/, true/*DontConsume*/)) 966193326Sed return TPResult::Error(); 967193326Sed } 968193326Sed 969193326Sed if (Tok.is(tok::ellipsis)) { 970193326Sed ConsumeToken(); 971193326Sed return TPResult::True(); // '...' is a sign of a function declarator. 972193326Sed } 973193326Sed 974193326Sed if (Tok.isNot(tok::comma)) 975193326Sed break; 976193326Sed ConsumeToken(); // the comma. 977193326Sed } 978193326Sed 979193326Sed return TPResult::Ambiguous(); 980193326Sed} 981193326Sed 982193326Sed/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue 983193326Sed/// parsing as a function declarator. 984193326Sed/// If TryParseFunctionDeclarator fully parsed the function declarator, it will 985193326Sed/// return TPResult::Ambiguous(), otherwise it will return either False() or 986193326Sed/// Error(). 987198092Srdivacky/// 988193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 989193326Sed/// exception-specification[opt] 990193326Sed/// 991193326Sed/// exception-specification: 992193326Sed/// 'throw' '(' type-id-list[opt] ')' 993193326Sed/// 994193326SedParser::TPResult Parser::TryParseFunctionDeclarator() { 995193326Sed 996193326Sed // The '(' is already parsed. 997193326Sed 998193326Sed TPResult TPR = TryParseParameterDeclarationClause(); 999193326Sed if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) 1000193326Sed TPR = TPResult::False(); 1001193326Sed 1002193326Sed if (TPR == TPResult::False() || TPR == TPResult::Error()) 1003193326Sed return TPR; 1004193326Sed 1005193326Sed // Parse through the parens. 1006193326Sed if (!SkipUntil(tok::r_paren)) 1007193326Sed return TPResult::Error(); 1008193326Sed 1009193326Sed // cv-qualifier-seq 1010193326Sed while (Tok.is(tok::kw_const) || 1011193326Sed Tok.is(tok::kw_volatile) || 1012193326Sed Tok.is(tok::kw_restrict) ) 1013193326Sed ConsumeToken(); 1014193326Sed 1015193326Sed // exception-specification 1016193326Sed if (Tok.is(tok::kw_throw)) { 1017193326Sed ConsumeToken(); 1018193326Sed if (Tok.isNot(tok::l_paren)) 1019193326Sed return TPResult::Error(); 1020193326Sed 1021193326Sed // Parse through the parens after 'throw'. 1022193326Sed ConsumeParen(); 1023193326Sed if (!SkipUntil(tok::r_paren)) 1024193326Sed return TPResult::Error(); 1025193326Sed } 1026193326Sed 1027193326Sed return TPResult::Ambiguous(); 1028193326Sed} 1029193326Sed 1030193326Sed/// '[' constant-expression[opt] ']' 1031193326Sed/// 1032193326SedParser::TPResult Parser::TryParseBracketDeclarator() { 1033193326Sed ConsumeBracket(); 1034193326Sed if (!SkipUntil(tok::r_square)) 1035193326Sed return TPResult::Error(); 1036193326Sed 1037193326Sed return TPResult::Ambiguous(); 1038193326Sed} 1039