ParseTentative.cpp revision 194179
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: 58193326Sed return true; 59193326Sed case tok::kw_static_assert: 60193326Sed // static_assert-declaration 61193326Sed return true; 62193326Sed default: 63193326Sed // simple-declaration 64193326Sed return isCXXSimpleDeclaration(); 65193326Sed } 66193326Sed} 67193326Sed 68193326Sed/// isCXXSimpleDeclaration - C++-specialized function that disambiguates 69193326Sed/// between a simple-declaration or an expression-statement. 70193326Sed/// If during the disambiguation process a parsing error is encountered, 71193326Sed/// the function returns true to let the declaration parsing code handle it. 72193326Sed/// Returns false if the statement is disambiguated as expression. 73193326Sed/// 74193326Sed/// simple-declaration: 75193326Sed/// decl-specifier-seq init-declarator-list[opt] ';' 76193326Sed/// 77193326Sedbool Parser::isCXXSimpleDeclaration() { 78193326Sed // C++ 6.8p1: 79193326Sed // There is an ambiguity in the grammar involving expression-statements and 80193326Sed // declarations: An expression-statement with a function-style explicit type 81193326Sed // conversion (5.2.3) as its leftmost subexpression can be indistinguishable 82193326Sed // from a declaration where the first declarator starts with a '('. In those 83193326Sed // cases the statement is a declaration. [Note: To disambiguate, the whole 84193326Sed // statement might have to be examined to determine if it is an 85193326Sed // expression-statement or a declaration]. 86193326Sed 87193326Sed // C++ 6.8p3: 88193326Sed // The disambiguation is purely syntactic; that is, the meaning of the names 89193326Sed // occurring in such a statement, beyond whether they are type-names or not, 90193326Sed // is not generally used in or changed by the disambiguation. Class 91193326Sed // templates are instantiated as necessary to determine if a qualified name 92193326Sed // is a type-name. Disambiguation precedes parsing, and a statement 93193326Sed // disambiguated as a declaration may be an ill-formed declaration. 94193326Sed 95193326Sed // We don't have to parse all of the decl-specifier-seq part. There's only 96193326Sed // an ambiguity if the first decl-specifier is 97193326Sed // simple-type-specifier/typename-specifier followed by a '(', which may 98193326Sed // indicate a function-style cast expression. 99193326Sed // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such 100193326Sed // a case. 101193326Sed 102193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 103193326Sed if (TPR != TPResult::Ambiguous()) 104193326Sed return TPR != TPResult::False(); // Returns true for TPResult::True() or 105193326Sed // TPResult::Error(). 106193326Sed 107193326Sed // FIXME: Add statistics about the number of ambiguous statements encountered 108193326Sed // and how they were resolved (number of declarations+number of expressions). 109193326Sed 110193326Sed // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 111193326Sed // We need tentative parsing... 112193326Sed 113193326Sed TentativeParsingAction PA(*this); 114193326Sed 115193326Sed TPR = TryParseSimpleDeclaration(); 116193326Sed SourceLocation TentativeParseLoc = Tok.getLocation(); 117193326Sed 118193326Sed PA.Revert(); 119193326Sed 120193326Sed // In case of an error, let the declaration parsing code handle it. 121193326Sed if (TPR == TPResult::Error()) 122193326Sed return true; 123193326Sed 124193326Sed // Declarations take precedence over expressions. 125193326Sed if (TPR == TPResult::Ambiguous()) 126193326Sed TPR = TPResult::True(); 127193326Sed 128193326Sed assert(TPR == TPResult::True() || TPR == TPResult::False()); 129193326Sed return TPR == TPResult::True(); 130193326Sed} 131193326Sed 132193326Sed/// simple-declaration: 133193326Sed/// decl-specifier-seq init-declarator-list[opt] ';' 134193326Sed/// 135193326SedParser::TPResult Parser::TryParseSimpleDeclaration() { 136193326Sed // We know that we have a simple-type-specifier/typename-specifier followed 137193326Sed // by a '('. 138193326Sed assert(isCXXDeclarationSpecifier() == TPResult::Ambiguous()); 139193326Sed 140193326Sed if (Tok.is(tok::kw_typeof)) 141193326Sed TryParseTypeofSpecifier(); 142193326Sed else 143193326Sed ConsumeToken(); 144193326Sed 145193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 146193326Sed 147193326Sed TPResult TPR = TryParseInitDeclaratorList(); 148193326Sed if (TPR != TPResult::Ambiguous()) 149193326Sed return TPR; 150193326Sed 151193326Sed if (Tok.isNot(tok::semi)) 152193326Sed return TPResult::False(); 153193326Sed 154193326Sed return TPResult::Ambiguous(); 155193326Sed} 156193326Sed 157193326Sed/// init-declarator-list: 158193326Sed/// init-declarator 159193326Sed/// init-declarator-list ',' init-declarator 160193326Sed/// 161193326Sed/// init-declarator: 162193326Sed/// declarator initializer[opt] 163193326Sed/// [GNU] declarator simple-asm-expr[opt] attributes[opt] initializer[opt] 164193326Sed/// 165193326Sed/// initializer: 166193326Sed/// '=' initializer-clause 167193326Sed/// '(' expression-list ')' 168193326Sed/// 169193326Sed/// initializer-clause: 170193326Sed/// assignment-expression 171193326Sed/// '{' initializer-list ','[opt] '}' 172193326Sed/// '{' '}' 173193326Sed/// 174193326SedParser::TPResult Parser::TryParseInitDeclaratorList() { 175193326Sed // GCC only examines the first declarator for disambiguation: 176193326Sed // i.e: 177193326Sed // int(x), ++x; // GCC regards it as ill-formed declaration. 178193326Sed // 179193326Sed // Comeau and MSVC will regard the above statement as correct expression. 180193326Sed // Clang examines all of the declarators and also regards the above statement 181193326Sed // as correct expression. 182193326Sed 183193326Sed while (1) { 184193326Sed // declarator 185193326Sed TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/); 186193326Sed if (TPR != TPResult::Ambiguous()) 187193326Sed return TPR; 188193326Sed 189193326Sed // [GNU] simple-asm-expr[opt] attributes[opt] 190193326Sed if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) 191193326Sed return TPResult::True(); 192193326Sed 193193326Sed // initializer[opt] 194193326Sed if (Tok.is(tok::l_paren)) { 195193326Sed // Parse through the parens. 196193326Sed ConsumeParen(); 197193326Sed if (!SkipUntil(tok::r_paren)) 198193326Sed return TPResult::Error(); 199193326Sed } else if (Tok.is(tok::equal)) { 200193326Sed // MSVC won't examine the rest of declarators if '=' is encountered, it 201193326Sed // will conclude that it is a declaration. 202193326Sed // Comeau and Clang will examine the rest of declarators. 203193326Sed // Note that "int(x) = {0}, ++x;" will be interpreted as ill-formed 204193326Sed // expression. 205193326Sed // 206193326Sed // Parse through the initializer-clause. 207193326Sed SkipUntil(tok::comma, true/*StopAtSemi*/, true/*DontConsume*/); 208193326Sed } 209193326Sed 210193326Sed if (Tok.isNot(tok::comma)) 211193326Sed break; 212193326Sed ConsumeToken(); // the comma. 213193326Sed } 214193326Sed 215193326Sed return TPResult::Ambiguous(); 216193326Sed} 217193326Sed 218193326Sed/// isCXXConditionDeclaration - Disambiguates between a declaration or an 219193326Sed/// expression for a condition of a if/switch/while/for statement. 220193326Sed/// If during the disambiguation process a parsing error is encountered, 221193326Sed/// the function returns true to let the declaration parsing code handle it. 222193326Sed/// 223193326Sed/// condition: 224193326Sed/// expression 225193326Sed/// type-specifier-seq declarator '=' assignment-expression 226193326Sed/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] 227193326Sed/// '=' assignment-expression 228193326Sed/// 229193326Sedbool Parser::isCXXConditionDeclaration() { 230193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 231193326Sed if (TPR != TPResult::Ambiguous()) 232193326Sed return TPR != TPResult::False(); // Returns true for TPResult::True() or 233193326Sed // TPResult::Error(). 234193326Sed 235193326Sed // FIXME: Add statistics about the number of ambiguous statements encountered 236193326Sed // and how they were resolved (number of declarations+number of expressions). 237193326Sed 238193326Sed // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 239193326Sed // We need tentative parsing... 240193326Sed 241193326Sed TentativeParsingAction PA(*this); 242193326Sed 243193326Sed // type-specifier-seq 244193326Sed if (Tok.is(tok::kw_typeof)) 245193326Sed TryParseTypeofSpecifier(); 246193326Sed else 247193326Sed ConsumeToken(); 248193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 249193326Sed 250193326Sed // declarator 251193326Sed TPR = TryParseDeclarator(false/*mayBeAbstract*/); 252193326Sed 253193326Sed // In case of an error, let the declaration parsing code handle it. 254193326Sed if (TPR == TPResult::Error()) 255193326Sed TPR = TPResult::True(); 256193326Sed 257193326Sed if (TPR == TPResult::Ambiguous()) { 258193326Sed // '=' 259193326Sed // [GNU] simple-asm-expr[opt] attributes[opt] 260193326Sed if (Tok.is(tok::equal) || 261193326Sed Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) 262193326Sed TPR = TPResult::True(); 263193326Sed else 264193326Sed TPR = TPResult::False(); 265193326Sed } 266193326Sed 267193326Sed PA.Revert(); 268193326Sed 269193326Sed assert(TPR == TPResult::True() || TPR == TPResult::False()); 270193326Sed return TPR == TPResult::True(); 271193326Sed} 272193326Sed 273193326Sed /// \brief Determine whether the next set of tokens contains a type-id. 274193326Sed /// 275193326Sed /// The context parameter states what context we're parsing right 276193326Sed /// now, which affects how this routine copes with the token 277193326Sed /// following the type-id. If the context is TypeIdInParens, we have 278193326Sed /// already parsed the '(' and we will cease lookahead when we hit 279193326Sed /// the corresponding ')'. If the context is 280193326Sed /// TypeIdAsTemplateArgument, we've already parsed the '<' or ',' 281193326Sed /// before this template argument, and will cease lookahead when we 282193326Sed /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id 283193326Sed /// and false for an expression. If during the disambiguation 284193326Sed /// process a parsing error is encountered, the function returns 285193326Sed /// true to let the declaration parsing code handle it. 286193326Sed /// 287193326Sed /// type-id: 288193326Sed /// type-specifier-seq abstract-declarator[opt] 289193326Sed /// 290193326Sedbool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { 291193326Sed 292193326Sed isAmbiguous = false; 293193326Sed 294193326Sed // C++ 8.2p2: 295193326Sed // The ambiguity arising from the similarity between a function-style cast and 296193326Sed // a type-id can occur in different contexts. The ambiguity appears as a 297193326Sed // choice between a function-style cast expression and a declaration of a 298193326Sed // type. The resolution is that any construct that could possibly be a type-id 299193326Sed // in its syntactic context shall be considered a type-id. 300193326Sed 301193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 302193326Sed if (TPR != TPResult::Ambiguous()) 303193326Sed return TPR != TPResult::False(); // Returns true for TPResult::True() or 304193326Sed // TPResult::Error(). 305193326Sed 306193326Sed // FIXME: Add statistics about the number of ambiguous statements encountered 307193326Sed // and how they were resolved (number of declarations+number of expressions). 308193326Sed 309193326Sed // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 310193326Sed // We need tentative parsing... 311193326Sed 312193326Sed TentativeParsingAction PA(*this); 313193326Sed 314193326Sed // type-specifier-seq 315193326Sed if (Tok.is(tok::kw_typeof)) 316193326Sed TryParseTypeofSpecifier(); 317193326Sed else 318193326Sed ConsumeToken(); 319193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 320193326Sed 321193326Sed // declarator 322193326Sed TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/); 323193326Sed 324193326Sed // In case of an error, let the declaration parsing code handle it. 325193326Sed if (TPR == TPResult::Error()) 326193326Sed TPR = TPResult::True(); 327193326Sed 328193326Sed if (TPR == TPResult::Ambiguous()) { 329193326Sed // We are supposed to be inside parens, so if after the abstract declarator 330193326Sed // we encounter a ')' this is a type-id, otherwise it's an expression. 331193326Sed if (Context == TypeIdInParens && Tok.is(tok::r_paren)) { 332193326Sed TPR = TPResult::True(); 333193326Sed isAmbiguous = true; 334193326Sed 335193326Sed // We are supposed to be inside a template argument, so if after 336193326Sed // the abstract declarator we encounter a '>', '>>' (in C++0x), or 337193326Sed // ',', this is a type-id. Otherwise, it's an expression. 338193326Sed } else if (Context == TypeIdAsTemplateArgument && 339193326Sed (Tok.is(tok::greater) || Tok.is(tok::comma) || 340193326Sed (getLang().CPlusPlus0x && Tok.is(tok::greatergreater)))) { 341193326Sed TPR = TPResult::True(); 342193326Sed isAmbiguous = true; 343193326Sed 344193326Sed } else 345193326Sed TPR = TPResult::False(); 346193326Sed } 347193326Sed 348193326Sed PA.Revert(); 349193326Sed 350193326Sed assert(TPR == TPResult::True() || TPR == TPResult::False()); 351193326Sed return TPR == TPResult::True(); 352193326Sed} 353193326Sed 354193326Sed/// declarator: 355193326Sed/// direct-declarator 356193326Sed/// ptr-operator declarator 357193326Sed/// 358193326Sed/// direct-declarator: 359193326Sed/// declarator-id 360193326Sed/// direct-declarator '(' parameter-declaration-clause ')' 361193326Sed/// cv-qualifier-seq[opt] exception-specification[opt] 362193326Sed/// direct-declarator '[' constant-expression[opt] ']' 363193326Sed/// '(' declarator ')' 364193326Sed/// [GNU] '(' attributes declarator ')' 365193326Sed/// 366193326Sed/// abstract-declarator: 367193326Sed/// ptr-operator abstract-declarator[opt] 368193326Sed/// direct-abstract-declarator 369193326Sed/// 370193326Sed/// direct-abstract-declarator: 371193326Sed/// direct-abstract-declarator[opt] 372193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 373193326Sed/// exception-specification[opt] 374193326Sed/// direct-abstract-declarator[opt] '[' constant-expression[opt] ']' 375193326Sed/// '(' abstract-declarator ')' 376193326Sed/// 377193326Sed/// ptr-operator: 378193326Sed/// '*' cv-qualifier-seq[opt] 379193326Sed/// '&' 380193326Sed/// [C++0x] '&&' [TODO] 381193326Sed/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt] 382193326Sed/// 383193326Sed/// cv-qualifier-seq: 384193326Sed/// cv-qualifier cv-qualifier-seq[opt] 385193326Sed/// 386193326Sed/// cv-qualifier: 387193326Sed/// 'const' 388193326Sed/// 'volatile' 389193326Sed/// 390193326Sed/// declarator-id: 391193326Sed/// id-expression 392193326Sed/// 393193326Sed/// id-expression: 394193326Sed/// unqualified-id 395193326Sed/// qualified-id [TODO] 396193326Sed/// 397193326Sed/// unqualified-id: 398193326Sed/// identifier 399193326Sed/// operator-function-id [TODO] 400193326Sed/// conversion-function-id [TODO] 401193326Sed/// '~' class-name [TODO] 402193326Sed/// template-id [TODO] 403193326Sed/// 404193326SedParser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, 405193326Sed bool mayHaveIdentifier) { 406193326Sed // declarator: 407193326Sed // direct-declarator 408193326Sed // ptr-operator declarator 409193326Sed 410193326Sed while (1) { 411193326Sed if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier)) 412193326Sed TryAnnotateCXXScopeToken(); 413193326Sed 414193326Sed if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) || 415193326Sed (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) { 416193326Sed // ptr-operator 417193326Sed ConsumeToken(); 418193326Sed while (Tok.is(tok::kw_const) || 419193326Sed Tok.is(tok::kw_volatile) || 420193326Sed Tok.is(tok::kw_restrict)) 421193326Sed ConsumeToken(); 422193326Sed } else { 423193326Sed break; 424193326Sed } 425193326Sed } 426193326Sed 427193326Sed // direct-declarator: 428193326Sed // direct-abstract-declarator: 429193326Sed 430193326Sed if (Tok.is(tok::identifier) && mayHaveIdentifier) { 431193326Sed // declarator-id 432193326Sed ConsumeToken(); 433193326Sed } else if (Tok.is(tok::l_paren)) { 434193326Sed ConsumeParen(); 435193326Sed if (mayBeAbstract && 436193326Sed (Tok.is(tok::r_paren) || // 'int()' is a function. 437193326Sed Tok.is(tok::ellipsis) || // 'int(...)' is a function. 438193326Sed isDeclarationSpecifier())) { // 'int(int)' is a function. 439193326Sed // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 440193326Sed // exception-specification[opt] 441193326Sed TPResult TPR = TryParseFunctionDeclarator(); 442193326Sed if (TPR != TPResult::Ambiguous()) 443193326Sed return TPR; 444193326Sed } else { 445193326Sed // '(' declarator ')' 446193326Sed // '(' attributes declarator ')' 447193326Sed // '(' abstract-declarator ')' 448193326Sed if (Tok.is(tok::kw___attribute)) 449193326Sed return TPResult::True(); // attributes indicate declaration 450193326Sed TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier); 451193326Sed if (TPR != TPResult::Ambiguous()) 452193326Sed return TPR; 453193326Sed if (Tok.isNot(tok::r_paren)) 454193326Sed return TPResult::False(); 455193326Sed ConsumeParen(); 456193326Sed } 457193326Sed } else if (!mayBeAbstract) { 458193326Sed return TPResult::False(); 459193326Sed } 460193326Sed 461193326Sed while (1) { 462193326Sed TPResult TPR(TPResult::Ambiguous()); 463193326Sed 464193326Sed if (Tok.is(tok::l_paren)) { 465193326Sed // Check whether we have a function declarator or a possible ctor-style 466193326Sed // initializer that follows the declarator. Note that ctor-style 467193326Sed // initializers are not possible in contexts where abstract declarators 468193326Sed // are allowed. 469193326Sed if (!mayBeAbstract && !isCXXFunctionDeclarator(false/*warnIfAmbiguous*/)) 470193326Sed break; 471193326Sed 472193326Sed // direct-declarator '(' parameter-declaration-clause ')' 473193326Sed // cv-qualifier-seq[opt] exception-specification[opt] 474193326Sed ConsumeParen(); 475193326Sed TPR = TryParseFunctionDeclarator(); 476193326Sed } else if (Tok.is(tok::l_square)) { 477193326Sed // direct-declarator '[' constant-expression[opt] ']' 478193326Sed // direct-abstract-declarator[opt] '[' constant-expression[opt] ']' 479193326Sed TPR = TryParseBracketDeclarator(); 480193326Sed } else { 481193326Sed break; 482193326Sed } 483193326Sed 484193326Sed if (TPR != TPResult::Ambiguous()) 485193326Sed return TPR; 486193326Sed } 487193326Sed 488193326Sed return TPResult::Ambiguous(); 489193326Sed} 490193326Sed 491193326Sed/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration 492193326Sed/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could 493193326Sed/// be either a decl-specifier or a function-style cast, and TPResult::Error() 494193326Sed/// if a parsing error was found and reported. 495193326Sed/// 496193326Sed/// decl-specifier: 497193326Sed/// storage-class-specifier 498193326Sed/// type-specifier 499193326Sed/// function-specifier 500193326Sed/// 'friend' 501193326Sed/// 'typedef' 502193326Sed/// [GNU] attributes declaration-specifiers[opt] 503193326Sed/// 504193326Sed/// storage-class-specifier: 505193326Sed/// 'register' 506193326Sed/// 'static' 507193326Sed/// 'extern' 508193326Sed/// 'mutable' 509193326Sed/// 'auto' 510193326Sed/// [GNU] '__thread' 511193326Sed/// 512193326Sed/// function-specifier: 513193326Sed/// 'inline' 514193326Sed/// 'virtual' 515193326Sed/// 'explicit' 516193326Sed/// 517193326Sed/// typedef-name: 518193326Sed/// identifier 519193326Sed/// 520193326Sed/// type-specifier: 521193326Sed/// simple-type-specifier 522193326Sed/// class-specifier 523193326Sed/// enum-specifier 524193326Sed/// elaborated-type-specifier 525193326Sed/// typename-specifier 526193326Sed/// cv-qualifier 527193326Sed/// 528193326Sed/// simple-type-specifier: 529193326Sed/// '::'[opt] nested-name-specifier[opt] type-name 530193326Sed/// '::'[opt] nested-name-specifier 'template' 531193326Sed/// simple-template-id [TODO] 532193326Sed/// 'char' 533193326Sed/// 'wchar_t' 534193326Sed/// 'bool' 535193326Sed/// 'short' 536193326Sed/// 'int' 537193326Sed/// 'long' 538193326Sed/// 'signed' 539193326Sed/// 'unsigned' 540193326Sed/// 'float' 541193326Sed/// 'double' 542193326Sed/// 'void' 543193326Sed/// [GNU] typeof-specifier 544193326Sed/// [GNU] '_Complex' 545193326Sed/// [C++0x] 'auto' [TODO] 546193326Sed/// 547193326Sed/// type-name: 548193326Sed/// class-name 549193326Sed/// enum-name 550193326Sed/// typedef-name 551193326Sed/// 552193326Sed/// elaborated-type-specifier: 553193326Sed/// class-key '::'[opt] nested-name-specifier[opt] identifier 554193326Sed/// class-key '::'[opt] nested-name-specifier[opt] 'template'[opt] 555193326Sed/// simple-template-id 556193326Sed/// 'enum' '::'[opt] nested-name-specifier[opt] identifier 557193326Sed/// 558193326Sed/// enum-name: 559193326Sed/// identifier 560193326Sed/// 561193326Sed/// enum-specifier: 562193326Sed/// 'enum' identifier[opt] '{' enumerator-list[opt] '}' 563193326Sed/// 'enum' identifier[opt] '{' enumerator-list ',' '}' 564193326Sed/// 565193326Sed/// class-specifier: 566193326Sed/// class-head '{' member-specification[opt] '}' 567193326Sed/// 568193326Sed/// class-head: 569193326Sed/// class-key identifier[opt] base-clause[opt] 570193326Sed/// class-key nested-name-specifier identifier base-clause[opt] 571193326Sed/// class-key nested-name-specifier[opt] simple-template-id 572193326Sed/// base-clause[opt] 573193326Sed/// 574193326Sed/// class-key: 575193326Sed/// 'class' 576193326Sed/// 'struct' 577193326Sed/// 'union' 578193326Sed/// 579193326Sed/// cv-qualifier: 580193326Sed/// 'const' 581193326Sed/// 'volatile' 582193326Sed/// [GNU] restrict 583193326Sed/// 584193326SedParser::TPResult Parser::isCXXDeclarationSpecifier() { 585193326Sed switch (Tok.getKind()) { 586193326Sed case tok::identifier: // foo::bar 587193326Sed case tok::kw_typename: // typename T::type 588193326Sed // Annotate typenames and C++ scope specifiers. If we get one, just 589193326Sed // recurse to handle whatever we get. 590193326Sed if (TryAnnotateTypeOrScopeToken()) 591193326Sed return isCXXDeclarationSpecifier(); 592193326Sed // Otherwise, not a typename. 593193326Sed return TPResult::False(); 594193326Sed 595193326Sed case tok::coloncolon: // ::foo::bar 596193326Sed if (NextToken().is(tok::kw_new) || // ::new 597193326Sed NextToken().is(tok::kw_delete)) // ::delete 598193326Sed return TPResult::False(); 599193326Sed 600193326Sed // Annotate typenames and C++ scope specifiers. If we get one, just 601193326Sed // recurse to handle whatever we get. 602193326Sed if (TryAnnotateTypeOrScopeToken()) 603193326Sed return isCXXDeclarationSpecifier(); 604193326Sed // Otherwise, not a typename. 605193326Sed return TPResult::False(); 606193326Sed 607193326Sed // decl-specifier: 608193326Sed // storage-class-specifier 609193326Sed // type-specifier 610193326Sed // function-specifier 611193326Sed // 'friend' 612193326Sed // 'typedef' 613193326Sed 614193326Sed case tok::kw_friend: 615193326Sed case tok::kw_typedef: 616193326Sed // storage-class-specifier 617193326Sed case tok::kw_register: 618193326Sed case tok::kw_static: 619193326Sed case tok::kw_extern: 620193326Sed case tok::kw_mutable: 621193326Sed case tok::kw_auto: 622193326Sed case tok::kw___thread: 623193326Sed // function-specifier 624193326Sed case tok::kw_inline: 625193326Sed case tok::kw_virtual: 626193326Sed case tok::kw_explicit: 627193326Sed 628193326Sed // type-specifier: 629193326Sed // simple-type-specifier 630193326Sed // class-specifier 631193326Sed // enum-specifier 632193326Sed // elaborated-type-specifier 633193326Sed // typename-specifier 634193326Sed // cv-qualifier 635193326Sed 636193326Sed // class-specifier 637193326Sed // elaborated-type-specifier 638193326Sed case tok::kw_class: 639193326Sed case tok::kw_struct: 640193326Sed case tok::kw_union: 641193326Sed // enum-specifier 642193326Sed case tok::kw_enum: 643193326Sed // cv-qualifier 644193326Sed case tok::kw_const: 645193326Sed case tok::kw_volatile: 646193326Sed 647193326Sed // GNU 648193326Sed case tok::kw_restrict: 649193326Sed case tok::kw__Complex: 650193326Sed case tok::kw___attribute: 651193326Sed return TPResult::True(); 652193326Sed 653193326Sed // Microsoft 654193326Sed case tok::kw___declspec: 655193326Sed case tok::kw___cdecl: 656193326Sed case tok::kw___stdcall: 657193326Sed case tok::kw___fastcall: 658194179Sed case tok::kw___w64: 659194179Sed case tok::kw___ptr64: 660194179Sed case tok::kw___forceinline: 661194179Sed return TPResult::True(); 662193326Sed 663193326Sed // The ambiguity resides in a simple-type-specifier/typename-specifier 664193326Sed // followed by a '('. The '(' could either be the start of: 665193326Sed // 666193326Sed // direct-declarator: 667193326Sed // '(' declarator ')' 668193326Sed // 669193326Sed // direct-abstract-declarator: 670193326Sed // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 671193326Sed // exception-specification[opt] 672193326Sed // '(' abstract-declarator ')' 673193326Sed // 674193326Sed // or part of a function-style cast expression: 675193326Sed // 676193326Sed // simple-type-specifier '(' expression-list[opt] ')' 677193326Sed // 678193326Sed 679193326Sed // simple-type-specifier: 680193326Sed 681193326Sed case tok::kw_char: 682193326Sed case tok::kw_wchar_t: 683193326Sed case tok::kw_bool: 684193326Sed case tok::kw_short: 685193326Sed case tok::kw_int: 686193326Sed case tok::kw_long: 687193326Sed case tok::kw_signed: 688193326Sed case tok::kw_unsigned: 689193326Sed case tok::kw_float: 690193326Sed case tok::kw_double: 691193326Sed case tok::kw_void: 692193326Sed case tok::annot_typename: 693193326Sed if (NextToken().is(tok::l_paren)) 694193326Sed return TPResult::Ambiguous(); 695193326Sed 696193326Sed return TPResult::True(); 697193326Sed 698193326Sed // GNU typeof support. 699193326Sed case tok::kw_typeof: { 700193326Sed if (NextToken().isNot(tok::l_paren)) 701193326Sed return TPResult::True(); 702193326Sed 703193326Sed TentativeParsingAction PA(*this); 704193326Sed 705193326Sed TPResult TPR = TryParseTypeofSpecifier(); 706193326Sed bool isFollowedByParen = Tok.is(tok::l_paren); 707193326Sed 708193326Sed PA.Revert(); 709193326Sed 710193326Sed if (TPR == TPResult::Error()) 711193326Sed return TPResult::Error(); 712193326Sed 713193326Sed if (isFollowedByParen) 714193326Sed return TPResult::Ambiguous(); 715193326Sed 716193326Sed return TPResult::True(); 717193326Sed } 718193326Sed 719193326Sed default: 720193326Sed return TPResult::False(); 721193326Sed } 722193326Sed} 723193326Sed 724193326Sed/// [GNU] typeof-specifier: 725193326Sed/// 'typeof' '(' expressions ')' 726193326Sed/// 'typeof' '(' type-name ')' 727193326Sed/// 728193326SedParser::TPResult Parser::TryParseTypeofSpecifier() { 729193326Sed assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!"); 730193326Sed ConsumeToken(); 731193326Sed 732193326Sed assert(Tok.is(tok::l_paren) && "Expected '('"); 733193326Sed // Parse through the parens after 'typeof'. 734193326Sed ConsumeParen(); 735193326Sed if (!SkipUntil(tok::r_paren)) 736193326Sed return TPResult::Error(); 737193326Sed 738193326Sed return TPResult::Ambiguous(); 739193326Sed} 740193326Sed 741193326SedParser::TPResult Parser::TryParseDeclarationSpecifier() { 742193326Sed TPResult TPR = isCXXDeclarationSpecifier(); 743193326Sed if (TPR != TPResult::Ambiguous()) 744193326Sed return TPR; 745193326Sed 746193326Sed if (Tok.is(tok::kw_typeof)) 747193326Sed TryParseTypeofSpecifier(); 748193326Sed else 749193326Sed ConsumeToken(); 750193326Sed 751193326Sed assert(Tok.is(tok::l_paren) && "Expected '('!"); 752193326Sed return TPResult::Ambiguous(); 753193326Sed} 754193326Sed 755193326Sed/// isCXXFunctionDeclarator - Disambiguates between a function declarator or 756193326Sed/// a constructor-style initializer, when parsing declaration statements. 757193326Sed/// Returns true for function declarator and false for constructor-style 758193326Sed/// initializer. 759193326Sed/// If during the disambiguation process a parsing error is encountered, 760193326Sed/// the function returns true to let the declaration parsing code handle it. 761193326Sed/// 762193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 763193326Sed/// exception-specification[opt] 764193326Sed/// 765193326Sedbool Parser::isCXXFunctionDeclarator(bool warnIfAmbiguous) { 766193326Sed 767193326Sed // C++ 8.2p1: 768193326Sed // The ambiguity arising from the similarity between a function-style cast and 769193326Sed // a declaration mentioned in 6.8 can also occur in the context of a 770193326Sed // declaration. In that context, the choice is between a function declaration 771193326Sed // with a redundant set of parentheses around a parameter name and an object 772193326Sed // declaration with a function-style cast as the initializer. Just as for the 773193326Sed // ambiguities mentioned in 6.8, the resolution is to consider any construct 774193326Sed // that could possibly be a declaration a declaration. 775193326Sed 776193326Sed TentativeParsingAction PA(*this); 777193326Sed 778193326Sed ConsumeParen(); 779193326Sed TPResult TPR = TryParseParameterDeclarationClause(); 780193326Sed if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) 781193326Sed TPR = TPResult::False(); 782193326Sed 783193326Sed SourceLocation TPLoc = Tok.getLocation(); 784193326Sed PA.Revert(); 785193326Sed 786193326Sed // In case of an error, let the declaration parsing code handle it. 787193326Sed if (TPR == TPResult::Error()) 788193326Sed return true; 789193326Sed 790193326Sed if (TPR == TPResult::Ambiguous()) { 791193326Sed // Function declarator has precedence over constructor-style initializer. 792193326Sed // Emit a warning just in case the author intended a variable definition. 793193326Sed if (warnIfAmbiguous) 794193326Sed Diag(Tok, diag::warn_parens_disambiguated_as_function_decl) 795193326Sed << SourceRange(Tok.getLocation(), TPLoc); 796193326Sed return true; 797193326Sed } 798193326Sed 799193326Sed return TPR == TPResult::True(); 800193326Sed} 801193326Sed 802193326Sed/// parameter-declaration-clause: 803193326Sed/// parameter-declaration-list[opt] '...'[opt] 804193326Sed/// parameter-declaration-list ',' '...' 805193326Sed/// 806193326Sed/// parameter-declaration-list: 807193326Sed/// parameter-declaration 808193326Sed/// parameter-declaration-list ',' parameter-declaration 809193326Sed/// 810193326Sed/// parameter-declaration: 811193326Sed/// decl-specifier-seq declarator 812193326Sed/// decl-specifier-seq declarator '=' assignment-expression 813193326Sed/// decl-specifier-seq abstract-declarator[opt] 814193326Sed/// decl-specifier-seq abstract-declarator[opt] '=' assignment-expression 815193326Sed/// 816193326SedParser::TPResult Parser::TryParseParameterDeclarationClause() { 817193326Sed 818193326Sed if (Tok.is(tok::r_paren)) 819193326Sed return TPResult::True(); 820193326Sed 821193326Sed // parameter-declaration-list[opt] '...'[opt] 822193326Sed // parameter-declaration-list ',' '...' 823193326Sed // 824193326Sed // parameter-declaration-list: 825193326Sed // parameter-declaration 826193326Sed // parameter-declaration-list ',' parameter-declaration 827193326Sed // 828193326Sed while (1) { 829193326Sed // '...'[opt] 830193326Sed if (Tok.is(tok::ellipsis)) { 831193326Sed ConsumeToken(); 832193326Sed return TPResult::True(); // '...' is a sign of a function declarator. 833193326Sed } 834193326Sed 835193326Sed // decl-specifier-seq 836193326Sed TPResult TPR = TryParseDeclarationSpecifier(); 837193326Sed if (TPR != TPResult::Ambiguous()) 838193326Sed return TPR; 839193326Sed 840193326Sed // declarator 841193326Sed // abstract-declarator[opt] 842193326Sed TPR = TryParseDeclarator(true/*mayBeAbstract*/); 843193326Sed if (TPR != TPResult::Ambiguous()) 844193326Sed return TPR; 845193326Sed 846193326Sed if (Tok.is(tok::equal)) { 847193326Sed // '=' assignment-expression 848193326Sed // Parse through assignment-expression. 849193326Sed tok::TokenKind StopToks[3] ={ tok::comma, tok::ellipsis, tok::r_paren }; 850193326Sed if (!SkipUntil(StopToks, 3, true/*StopAtSemi*/, true/*DontConsume*/)) 851193326Sed return TPResult::Error(); 852193326Sed } 853193326Sed 854193326Sed if (Tok.is(tok::ellipsis)) { 855193326Sed ConsumeToken(); 856193326Sed return TPResult::True(); // '...' is a sign of a function declarator. 857193326Sed } 858193326Sed 859193326Sed if (Tok.isNot(tok::comma)) 860193326Sed break; 861193326Sed ConsumeToken(); // the comma. 862193326Sed } 863193326Sed 864193326Sed return TPResult::Ambiguous(); 865193326Sed} 866193326Sed 867193326Sed/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue 868193326Sed/// parsing as a function declarator. 869193326Sed/// If TryParseFunctionDeclarator fully parsed the function declarator, it will 870193326Sed/// return TPResult::Ambiguous(), otherwise it will return either False() or 871193326Sed/// Error(). 872193326Sed/// 873193326Sed/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 874193326Sed/// exception-specification[opt] 875193326Sed/// 876193326Sed/// exception-specification: 877193326Sed/// 'throw' '(' type-id-list[opt] ')' 878193326Sed/// 879193326SedParser::TPResult Parser::TryParseFunctionDeclarator() { 880193326Sed 881193326Sed // The '(' is already parsed. 882193326Sed 883193326Sed TPResult TPR = TryParseParameterDeclarationClause(); 884193326Sed if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) 885193326Sed TPR = TPResult::False(); 886193326Sed 887193326Sed if (TPR == TPResult::False() || TPR == TPResult::Error()) 888193326Sed return TPR; 889193326Sed 890193326Sed // Parse through the parens. 891193326Sed if (!SkipUntil(tok::r_paren)) 892193326Sed return TPResult::Error(); 893193326Sed 894193326Sed // cv-qualifier-seq 895193326Sed while (Tok.is(tok::kw_const) || 896193326Sed Tok.is(tok::kw_volatile) || 897193326Sed Tok.is(tok::kw_restrict) ) 898193326Sed ConsumeToken(); 899193326Sed 900193326Sed // exception-specification 901193326Sed if (Tok.is(tok::kw_throw)) { 902193326Sed ConsumeToken(); 903193326Sed if (Tok.isNot(tok::l_paren)) 904193326Sed return TPResult::Error(); 905193326Sed 906193326Sed // Parse through the parens after 'throw'. 907193326Sed ConsumeParen(); 908193326Sed if (!SkipUntil(tok::r_paren)) 909193326Sed return TPResult::Error(); 910193326Sed } 911193326Sed 912193326Sed return TPResult::Ambiguous(); 913193326Sed} 914193326Sed 915193326Sed/// '[' constant-expression[opt] ']' 916193326Sed/// 917193326SedParser::TPResult Parser::TryParseBracketDeclarator() { 918193326Sed ConsumeBracket(); 919193326Sed if (!SkipUntil(tok::r_square)) 920193326Sed return TPResult::Error(); 921193326Sed 922193326Sed return TPResult::Ambiguous(); 923193326Sed} 924