ParseTentative.cpp revision 203955
1//===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the tentative parsing portions of the Parser 11// interfaces, for ambiguity resolution. 12// 13//===----------------------------------------------------------------------===// 14 15#include "clang/Parse/Parser.h" 16#include "clang/Parse/ParseDiagnostic.h" 17using namespace clang; 18 19/// isCXXDeclarationStatement - C++-specialized function that disambiguates 20/// between a declaration or an expression statement, when parsing function 21/// bodies. Returns true for declaration, false for expression. 22/// 23/// declaration-statement: 24/// block-declaration 25/// 26/// block-declaration: 27/// simple-declaration 28/// asm-definition 29/// namespace-alias-definition 30/// using-declaration 31/// using-directive 32/// [C++0x] static_assert-declaration 33/// 34/// asm-definition: 35/// 'asm' '(' string-literal ')' ';' 36/// 37/// namespace-alias-definition: 38/// 'namespace' identifier = qualified-namespace-specifier ';' 39/// 40/// using-declaration: 41/// 'using' typename[opt] '::'[opt] nested-name-specifier 42/// unqualified-id ';' 43/// 'using' '::' unqualified-id ; 44/// 45/// using-directive: 46/// 'using' 'namespace' '::'[opt] nested-name-specifier[opt] 47/// namespace-name ';' 48/// 49bool Parser::isCXXDeclarationStatement() { 50 switch (Tok.getKind()) { 51 // asm-definition 52 case tok::kw_asm: 53 // namespace-alias-definition 54 case tok::kw_namespace: 55 // using-declaration 56 // using-directive 57 case tok::kw_using: 58 // static_assert-declaration 59 case tok::kw_static_assert: 60 return true; 61 // simple-declaration 62 default: 63 return isCXXSimpleDeclaration(); 64 } 65} 66 67/// isCXXSimpleDeclaration - C++-specialized function that disambiguates 68/// between a simple-declaration or an expression-statement. 69/// If during the disambiguation process a parsing error is encountered, 70/// the function returns true to let the declaration parsing code handle it. 71/// Returns false if the statement is disambiguated as expression. 72/// 73/// simple-declaration: 74/// decl-specifier-seq init-declarator-list[opt] ';' 75/// 76bool Parser::isCXXSimpleDeclaration() { 77 // C++ 6.8p1: 78 // There is an ambiguity in the grammar involving expression-statements and 79 // declarations: An expression-statement with a function-style explicit type 80 // conversion (5.2.3) as its leftmost subexpression can be indistinguishable 81 // from a declaration where the first declarator starts with a '('. In those 82 // cases the statement is a declaration. [Note: To disambiguate, the whole 83 // statement might have to be examined to determine if it is an 84 // expression-statement or a declaration]. 85 86 // C++ 6.8p3: 87 // The disambiguation is purely syntactic; that is, the meaning of the names 88 // occurring in such a statement, beyond whether they are type-names or not, 89 // is not generally used in or changed by the disambiguation. Class 90 // templates are instantiated as necessary to determine if a qualified name 91 // is a type-name. Disambiguation precedes parsing, and a statement 92 // disambiguated as a declaration may be an ill-formed declaration. 93 94 // We don't have to parse all of the decl-specifier-seq part. There's only 95 // an ambiguity if the first decl-specifier is 96 // simple-type-specifier/typename-specifier followed by a '(', which may 97 // indicate a function-style cast expression. 98 // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such 99 // a case. 100 101 TPResult TPR = isCXXDeclarationSpecifier(); 102 if (TPR != TPResult::Ambiguous()) 103 return TPR != TPResult::False(); // Returns true for TPResult::True() or 104 // TPResult::Error(). 105 106 // FIXME: Add statistics about the number of ambiguous statements encountered 107 // and how they were resolved (number of declarations+number of expressions). 108 109 // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 110 // We need tentative parsing... 111 112 TentativeParsingAction PA(*this); 113 114 TPR = TryParseSimpleDeclaration(); 115 SourceLocation TentativeParseLoc = Tok.getLocation(); 116 117 PA.Revert(); 118 119 // In case of an error, let the declaration parsing code handle it. 120 if (TPR == TPResult::Error()) 121 return true; 122 123 // Declarations take precedence over expressions. 124 if (TPR == TPResult::Ambiguous()) 125 TPR = TPResult::True(); 126 127 assert(TPR == TPResult::True() || TPR == TPResult::False()); 128 return TPR == TPResult::True(); 129} 130 131/// simple-declaration: 132/// decl-specifier-seq init-declarator-list[opt] ';' 133/// 134Parser::TPResult Parser::TryParseSimpleDeclaration() { 135 // We know that we have a simple-type-specifier/typename-specifier followed 136 // by a '('. 137 assert(isCXXDeclarationSpecifier() == TPResult::Ambiguous()); 138 139 if (Tok.is(tok::kw_typeof)) 140 TryParseTypeofSpecifier(); 141 else 142 ConsumeToken(); 143 144 assert(Tok.is(tok::l_paren) && "Expected '('"); 145 146 TPResult TPR = TryParseInitDeclaratorList(); 147 if (TPR != TPResult::Ambiguous()) 148 return TPR; 149 150 if (Tok.isNot(tok::semi)) 151 return TPResult::False(); 152 153 return TPResult::Ambiguous(); 154} 155 156/// init-declarator-list: 157/// init-declarator 158/// init-declarator-list ',' init-declarator 159/// 160/// init-declarator: 161/// declarator initializer[opt] 162/// [GNU] declarator simple-asm-expr[opt] attributes[opt] initializer[opt] 163/// 164/// initializer: 165/// '=' initializer-clause 166/// '(' expression-list ')' 167/// 168/// initializer-clause: 169/// assignment-expression 170/// '{' initializer-list ','[opt] '}' 171/// '{' '}' 172/// 173Parser::TPResult Parser::TryParseInitDeclaratorList() { 174 // GCC only examines the first declarator for disambiguation: 175 // i.e: 176 // int(x), ++x; // GCC regards it as ill-formed declaration. 177 // 178 // Comeau and MSVC will regard the above statement as correct expression. 179 // Clang examines all of the declarators and also regards the above statement 180 // as correct expression. 181 182 while (1) { 183 // declarator 184 TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/); 185 if (TPR != TPResult::Ambiguous()) 186 return TPR; 187 188 // [GNU] simple-asm-expr[opt] attributes[opt] 189 if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) 190 return TPResult::True(); 191 192 // initializer[opt] 193 if (Tok.is(tok::l_paren)) { 194 // Parse through the parens. 195 ConsumeParen(); 196 if (!SkipUntil(tok::r_paren)) 197 return TPResult::Error(); 198 } else if (Tok.is(tok::equal)) { 199 // MSVC won't examine the rest of declarators if '=' is encountered, it 200 // will conclude that it is a declaration. 201 // Comeau and Clang will examine the rest of declarators. 202 // Note that "int(x) = {0}, ++x;" will be interpreted as ill-formed 203 // expression. 204 // 205 // Parse through the initializer-clause. 206 SkipUntil(tok::comma, true/*StopAtSemi*/, true/*DontConsume*/); 207 } 208 209 if (Tok.isNot(tok::comma)) 210 break; 211 ConsumeToken(); // the comma. 212 } 213 214 return TPResult::Ambiguous(); 215} 216 217/// isCXXConditionDeclaration - Disambiguates between a declaration or an 218/// expression for a condition of a if/switch/while/for statement. 219/// If during the disambiguation process a parsing error is encountered, 220/// the function returns true to let the declaration parsing code handle it. 221/// 222/// condition: 223/// expression 224/// type-specifier-seq declarator '=' assignment-expression 225/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] 226/// '=' assignment-expression 227/// 228bool Parser::isCXXConditionDeclaration() { 229 TPResult TPR = isCXXDeclarationSpecifier(); 230 if (TPR != TPResult::Ambiguous()) 231 return TPR != TPResult::False(); // Returns true for TPResult::True() or 232 // TPResult::Error(). 233 234 // FIXME: Add statistics about the number of ambiguous statements encountered 235 // and how they were resolved (number of declarations+number of expressions). 236 237 // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 238 // We need tentative parsing... 239 240 TentativeParsingAction PA(*this); 241 242 // type-specifier-seq 243 if (Tok.is(tok::kw_typeof)) 244 TryParseTypeofSpecifier(); 245 else 246 ConsumeToken(); 247 assert(Tok.is(tok::l_paren) && "Expected '('"); 248 249 // declarator 250 TPR = TryParseDeclarator(false/*mayBeAbstract*/); 251 252 // In case of an error, let the declaration parsing code handle it. 253 if (TPR == TPResult::Error()) 254 TPR = TPResult::True(); 255 256 if (TPR == TPResult::Ambiguous()) { 257 // '=' 258 // [GNU] simple-asm-expr[opt] attributes[opt] 259 if (Tok.is(tok::equal) || 260 Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute)) 261 TPR = TPResult::True(); 262 else 263 TPR = TPResult::False(); 264 } 265 266 PA.Revert(); 267 268 assert(TPR == TPResult::True() || TPR == TPResult::False()); 269 return TPR == TPResult::True(); 270} 271 272 /// \brief Determine whether the next set of tokens contains a type-id. 273 /// 274 /// The context parameter states what context we're parsing right 275 /// now, which affects how this routine copes with the token 276 /// following the type-id. If the context is TypeIdInParens, we have 277 /// already parsed the '(' and we will cease lookahead when we hit 278 /// the corresponding ')'. If the context is 279 /// TypeIdAsTemplateArgument, we've already parsed the '<' or ',' 280 /// before this template argument, and will cease lookahead when we 281 /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id 282 /// and false for an expression. If during the disambiguation 283 /// process a parsing error is encountered, the function returns 284 /// true to let the declaration parsing code handle it. 285 /// 286 /// type-id: 287 /// type-specifier-seq abstract-declarator[opt] 288 /// 289bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { 290 291 isAmbiguous = false; 292 293 // C++ 8.2p2: 294 // The ambiguity arising from the similarity between a function-style cast and 295 // a type-id can occur in different contexts. The ambiguity appears as a 296 // choice between a function-style cast expression and a declaration of a 297 // type. The resolution is that any construct that could possibly be a type-id 298 // in its syntactic context shall be considered a type-id. 299 300 TPResult TPR = isCXXDeclarationSpecifier(); 301 if (TPR != TPResult::Ambiguous()) 302 return TPR != TPResult::False(); // Returns true for TPResult::True() or 303 // TPResult::Error(). 304 305 // FIXME: Add statistics about the number of ambiguous statements encountered 306 // and how they were resolved (number of declarations+number of expressions). 307 308 // Ok, we have a simple-type-specifier/typename-specifier followed by a '('. 309 // We need tentative parsing... 310 311 TentativeParsingAction PA(*this); 312 313 // type-specifier-seq 314 if (Tok.is(tok::kw_typeof)) 315 TryParseTypeofSpecifier(); 316 else 317 ConsumeToken(); 318 assert(Tok.is(tok::l_paren) && "Expected '('"); 319 320 // declarator 321 TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/); 322 323 // In case of an error, let the declaration parsing code handle it. 324 if (TPR == TPResult::Error()) 325 TPR = TPResult::True(); 326 327 if (TPR == TPResult::Ambiguous()) { 328 // We are supposed to be inside parens, so if after the abstract declarator 329 // we encounter a ')' this is a type-id, otherwise it's an expression. 330 if (Context == TypeIdInParens && Tok.is(tok::r_paren)) { 331 TPR = TPResult::True(); 332 isAmbiguous = true; 333 334 // We are supposed to be inside a template argument, so if after 335 // the abstract declarator we encounter a '>', '>>' (in C++0x), or 336 // ',', this is a type-id. Otherwise, it's an expression. 337 } else if (Context == TypeIdAsTemplateArgument && 338 (Tok.is(tok::greater) || Tok.is(tok::comma) || 339 (getLang().CPlusPlus0x && Tok.is(tok::greatergreater)))) { 340 TPR = TPResult::True(); 341 isAmbiguous = true; 342 343 } else 344 TPR = TPResult::False(); 345 } 346 347 PA.Revert(); 348 349 assert(TPR == TPResult::True() || TPR == TPResult::False()); 350 return TPR == TPResult::True(); 351} 352 353/// isCXX0XAttributeSpecifier - returns true if this is a C++0x 354/// attribute-specifier. By default, unless in Obj-C++, only a cursory check is 355/// performed that will simply return true if a [[ is seen. Currently C++ has no 356/// syntactical ambiguities from this check, but it may inhibit error recovery. 357/// If CheckClosing is true, a check is made for closing ]] brackets. 358/// 359/// If given, After is set to the token after the attribute-specifier so that 360/// appropriate parsing decisions can be made; it is left untouched if false is 361/// returned. 362/// 363/// FIXME: If an error is in the closing ]] brackets, the program assumes 364/// the absence of an attribute-specifier, which can cause very yucky errors 365/// to occur. 366/// 367/// [C++0x] attribute-specifier: 368/// '[' '[' attribute-list ']' ']' 369/// 370/// [C++0x] attribute-list: 371/// attribute[opt] 372/// attribute-list ',' attribute[opt] 373/// 374/// [C++0x] attribute: 375/// attribute-token attribute-argument-clause[opt] 376/// 377/// [C++0x] attribute-token: 378/// identifier 379/// attribute-scoped-token 380/// 381/// [C++0x] attribute-scoped-token: 382/// attribute-namespace '::' identifier 383/// 384/// [C++0x] attribute-namespace: 385/// identifier 386/// 387/// [C++0x] attribute-argument-clause: 388/// '(' balanced-token-seq ')' 389/// 390/// [C++0x] balanced-token-seq: 391/// balanced-token 392/// balanced-token-seq balanced-token 393/// 394/// [C++0x] balanced-token: 395/// '(' balanced-token-seq ')' 396/// '[' balanced-token-seq ']' 397/// '{' balanced-token-seq '}' 398/// any token but '(', ')', '[', ']', '{', or '}' 399bool Parser::isCXX0XAttributeSpecifier (bool CheckClosing, 400 tok::TokenKind *After) { 401 if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square)) 402 return false; 403 404 // No tentative parsing if we don't need to look for ]] 405 if (!CheckClosing && !getLang().ObjC1) 406 return true; 407 408 struct TentativeReverter { 409 TentativeParsingAction PA; 410 411 TentativeReverter (Parser& P) 412 : PA(P) 413 {} 414 ~TentativeReverter () { 415 PA.Revert(); 416 } 417 } R(*this); 418 419 // Opening brackets were checked for above. 420 ConsumeBracket(); 421 ConsumeBracket(); 422 423 // SkipUntil will handle balanced tokens, which are guaranteed in attributes. 424 SkipUntil(tok::r_square, false); 425 426 if (Tok.isNot(tok::r_square)) 427 return false; 428 ConsumeBracket(); 429 430 if (After) 431 *After = Tok.getKind(); 432 433 return true; 434} 435 436/// declarator: 437/// direct-declarator 438/// ptr-operator declarator 439/// 440/// direct-declarator: 441/// declarator-id 442/// direct-declarator '(' parameter-declaration-clause ')' 443/// cv-qualifier-seq[opt] exception-specification[opt] 444/// direct-declarator '[' constant-expression[opt] ']' 445/// '(' declarator ')' 446/// [GNU] '(' attributes declarator ')' 447/// 448/// abstract-declarator: 449/// ptr-operator abstract-declarator[opt] 450/// direct-abstract-declarator 451/// 452/// direct-abstract-declarator: 453/// direct-abstract-declarator[opt] 454/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 455/// exception-specification[opt] 456/// direct-abstract-declarator[opt] '[' constant-expression[opt] ']' 457/// '(' abstract-declarator ')' 458/// 459/// ptr-operator: 460/// '*' cv-qualifier-seq[opt] 461/// '&' 462/// [C++0x] '&&' [TODO] 463/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt] 464/// 465/// cv-qualifier-seq: 466/// cv-qualifier cv-qualifier-seq[opt] 467/// 468/// cv-qualifier: 469/// 'const' 470/// 'volatile' 471/// 472/// declarator-id: 473/// id-expression 474/// 475/// id-expression: 476/// unqualified-id 477/// qualified-id [TODO] 478/// 479/// unqualified-id: 480/// identifier 481/// operator-function-id [TODO] 482/// conversion-function-id [TODO] 483/// '~' class-name [TODO] 484/// template-id [TODO] 485/// 486Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, 487 bool mayHaveIdentifier) { 488 // declarator: 489 // direct-declarator 490 // ptr-operator declarator 491 492 while (1) { 493 if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier)) 494 TryAnnotateCXXScopeToken(true); 495 496 if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) || 497 (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) { 498 // ptr-operator 499 ConsumeToken(); 500 while (Tok.is(tok::kw_const) || 501 Tok.is(tok::kw_volatile) || 502 Tok.is(tok::kw_restrict)) 503 ConsumeToken(); 504 } else { 505 break; 506 } 507 } 508 509 // direct-declarator: 510 // direct-abstract-declarator: 511 512 if ((Tok.is(tok::identifier) || 513 (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) && 514 mayHaveIdentifier) { 515 // declarator-id 516 if (Tok.is(tok::annot_cxxscope)) 517 ConsumeToken(); 518 ConsumeToken(); 519 } else if (Tok.is(tok::l_paren)) { 520 ConsumeParen(); 521 if (mayBeAbstract && 522 (Tok.is(tok::r_paren) || // 'int()' is a function. 523 Tok.is(tok::ellipsis) || // 'int(...)' is a function. 524 isDeclarationSpecifier())) { // 'int(int)' is a function. 525 // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 526 // exception-specification[opt] 527 TPResult TPR = TryParseFunctionDeclarator(); 528 if (TPR != TPResult::Ambiguous()) 529 return TPR; 530 } else { 531 // '(' declarator ')' 532 // '(' attributes declarator ')' 533 // '(' abstract-declarator ')' 534 if (Tok.is(tok::kw___attribute)) 535 return TPResult::True(); // attributes indicate declaration 536 TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier); 537 if (TPR != TPResult::Ambiguous()) 538 return TPR; 539 if (Tok.isNot(tok::r_paren)) 540 return TPResult::False(); 541 ConsumeParen(); 542 } 543 } else if (!mayBeAbstract) { 544 return TPResult::False(); 545 } 546 547 while (1) { 548 TPResult TPR(TPResult::Ambiguous()); 549 550 if (Tok.is(tok::l_paren)) { 551 // Check whether we have a function declarator or a possible ctor-style 552 // initializer that follows the declarator. Note that ctor-style 553 // initializers are not possible in contexts where abstract declarators 554 // are allowed. 555 if (!mayBeAbstract && !isCXXFunctionDeclarator(false/*warnIfAmbiguous*/)) 556 break; 557 558 // direct-declarator '(' parameter-declaration-clause ')' 559 // cv-qualifier-seq[opt] exception-specification[opt] 560 ConsumeParen(); 561 TPR = TryParseFunctionDeclarator(); 562 } else if (Tok.is(tok::l_square)) { 563 // direct-declarator '[' constant-expression[opt] ']' 564 // direct-abstract-declarator[opt] '[' constant-expression[opt] ']' 565 TPR = TryParseBracketDeclarator(); 566 } else { 567 break; 568 } 569 570 if (TPR != TPResult::Ambiguous()) 571 return TPR; 572 } 573 574 return TPResult::Ambiguous(); 575} 576 577/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration 578/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could 579/// be either a decl-specifier or a function-style cast, and TPResult::Error() 580/// if a parsing error was found and reported. 581/// 582/// decl-specifier: 583/// storage-class-specifier 584/// type-specifier 585/// function-specifier 586/// 'friend' 587/// 'typedef' 588/// [C++0x] 'constexpr' 589/// [GNU] attributes declaration-specifiers[opt] 590/// 591/// storage-class-specifier: 592/// 'register' 593/// 'static' 594/// 'extern' 595/// 'mutable' 596/// 'auto' 597/// [GNU] '__thread' 598/// 599/// function-specifier: 600/// 'inline' 601/// 'virtual' 602/// 'explicit' 603/// 604/// typedef-name: 605/// identifier 606/// 607/// type-specifier: 608/// simple-type-specifier 609/// class-specifier 610/// enum-specifier 611/// elaborated-type-specifier 612/// typename-specifier 613/// cv-qualifier 614/// 615/// simple-type-specifier: 616/// '::'[opt] nested-name-specifier[opt] type-name 617/// '::'[opt] nested-name-specifier 'template' 618/// simple-template-id [TODO] 619/// 'char' 620/// 'wchar_t' 621/// 'bool' 622/// 'short' 623/// 'int' 624/// 'long' 625/// 'signed' 626/// 'unsigned' 627/// 'float' 628/// 'double' 629/// 'void' 630/// [GNU] typeof-specifier 631/// [GNU] '_Complex' 632/// [C++0x] 'auto' [TODO] 633/// [C++0x] 'decltype' ( expression ) 634/// 635/// type-name: 636/// class-name 637/// enum-name 638/// typedef-name 639/// 640/// elaborated-type-specifier: 641/// class-key '::'[opt] nested-name-specifier[opt] identifier 642/// class-key '::'[opt] nested-name-specifier[opt] 'template'[opt] 643/// simple-template-id 644/// 'enum' '::'[opt] nested-name-specifier[opt] identifier 645/// 646/// enum-name: 647/// identifier 648/// 649/// enum-specifier: 650/// 'enum' identifier[opt] '{' enumerator-list[opt] '}' 651/// 'enum' identifier[opt] '{' enumerator-list ',' '}' 652/// 653/// class-specifier: 654/// class-head '{' member-specification[opt] '}' 655/// 656/// class-head: 657/// class-key identifier[opt] base-clause[opt] 658/// class-key nested-name-specifier identifier base-clause[opt] 659/// class-key nested-name-specifier[opt] simple-template-id 660/// base-clause[opt] 661/// 662/// class-key: 663/// 'class' 664/// 'struct' 665/// 'union' 666/// 667/// cv-qualifier: 668/// 'const' 669/// 'volatile' 670/// [GNU] restrict 671/// 672Parser::TPResult Parser::isCXXDeclarationSpecifier() { 673 switch (Tok.getKind()) { 674 case tok::identifier: // foo::bar 675 // Check for need to substitute AltiVec __vector keyword 676 // for "vector" identifier. 677 if (TryAltiVecVectorToken()) 678 return TPResult::True(); 679 // Fall through. 680 case tok::kw_typename: // typename T::type 681 // Annotate typenames and C++ scope specifiers. If we get one, just 682 // recurse to handle whatever we get. 683 if (TryAnnotateTypeOrScopeToken()) 684 return isCXXDeclarationSpecifier(); 685 // Otherwise, not a typename. 686 return TPResult::False(); 687 688 case tok::coloncolon: { // ::foo::bar 689 const Token &Next = NextToken(); 690 if (Next.is(tok::kw_new) || // ::new 691 Next.is(tok::kw_delete)) // ::delete 692 return TPResult::False(); 693 694 // Annotate typenames and C++ scope specifiers. If we get one, just 695 // recurse to handle whatever we get. 696 if (TryAnnotateTypeOrScopeToken()) 697 return isCXXDeclarationSpecifier(); 698 // Otherwise, not a typename. 699 return TPResult::False(); 700 } 701 702 // decl-specifier: 703 // storage-class-specifier 704 // type-specifier 705 // function-specifier 706 // 'friend' 707 // 'typedef' 708 // 'constexpr' 709 case tok::kw_friend: 710 case tok::kw_typedef: 711 case tok::kw_constexpr: 712 // storage-class-specifier 713 case tok::kw_register: 714 case tok::kw_static: 715 case tok::kw_extern: 716 case tok::kw_mutable: 717 case tok::kw_auto: 718 case tok::kw___thread: 719 // function-specifier 720 case tok::kw_inline: 721 case tok::kw_virtual: 722 case tok::kw_explicit: 723 724 // type-specifier: 725 // simple-type-specifier 726 // class-specifier 727 // enum-specifier 728 // elaborated-type-specifier 729 // typename-specifier 730 // cv-qualifier 731 732 // class-specifier 733 // elaborated-type-specifier 734 case tok::kw_class: 735 case tok::kw_struct: 736 case tok::kw_union: 737 // enum-specifier 738 case tok::kw_enum: 739 // cv-qualifier 740 case tok::kw_const: 741 case tok::kw_volatile: 742 743 // GNU 744 case tok::kw_restrict: 745 case tok::kw__Complex: 746 case tok::kw___attribute: 747 return TPResult::True(); 748 749 // Microsoft 750 case tok::kw___declspec: 751 case tok::kw___cdecl: 752 case tok::kw___stdcall: 753 case tok::kw___fastcall: 754 case tok::kw___w64: 755 case tok::kw___ptr64: 756 case tok::kw___forceinline: 757 return TPResult::True(); 758 759 // AltiVec 760 case tok::kw___vector: 761 return TPResult::True(); 762 763 case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed 764 // We've already annotated a scope; try to annotate a type. 765 if (!(TryAnnotateTypeOrScopeToken() && Tok.is(tok::annot_typename))) 766 return TPResult::False(); 767 // If that succeeded, fallthrough into the generic simple-type-id case. 768 769 // The ambiguity resides in a simple-type-specifier/typename-specifier 770 // followed by a '('. The '(' could either be the start of: 771 // 772 // direct-declarator: 773 // '(' declarator ')' 774 // 775 // direct-abstract-declarator: 776 // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 777 // exception-specification[opt] 778 // '(' abstract-declarator ')' 779 // 780 // or part of a function-style cast expression: 781 // 782 // simple-type-specifier '(' expression-list[opt] ')' 783 // 784 785 // simple-type-specifier: 786 787 case tok::kw_char: 788 case tok::kw_wchar_t: 789 case tok::kw_char16_t: 790 case tok::kw_char32_t: 791 case tok::kw_bool: 792 case tok::kw_short: 793 case tok::kw_int: 794 case tok::kw_long: 795 case tok::kw_signed: 796 case tok::kw_unsigned: 797 case tok::kw_float: 798 case tok::kw_double: 799 case tok::kw_void: 800 case tok::annot_typename: 801 if (NextToken().is(tok::l_paren)) 802 return TPResult::Ambiguous(); 803 804 return TPResult::True(); 805 806 // GNU typeof support. 807 case tok::kw_typeof: { 808 if (NextToken().isNot(tok::l_paren)) 809 return TPResult::True(); 810 811 TentativeParsingAction PA(*this); 812 813 TPResult TPR = TryParseTypeofSpecifier(); 814 bool isFollowedByParen = Tok.is(tok::l_paren); 815 816 PA.Revert(); 817 818 if (TPR == TPResult::Error()) 819 return TPResult::Error(); 820 821 if (isFollowedByParen) 822 return TPResult::Ambiguous(); 823 824 return TPResult::True(); 825 } 826 827 // C++0x decltype support. 828 case tok::kw_decltype: 829 return TPResult::True(); 830 831 default: 832 return TPResult::False(); 833 } 834} 835 836/// [GNU] typeof-specifier: 837/// 'typeof' '(' expressions ')' 838/// 'typeof' '(' type-name ')' 839/// 840Parser::TPResult Parser::TryParseTypeofSpecifier() { 841 assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!"); 842 ConsumeToken(); 843 844 assert(Tok.is(tok::l_paren) && "Expected '('"); 845 // Parse through the parens after 'typeof'. 846 ConsumeParen(); 847 if (!SkipUntil(tok::r_paren)) 848 return TPResult::Error(); 849 850 return TPResult::Ambiguous(); 851} 852 853Parser::TPResult Parser::TryParseDeclarationSpecifier() { 854 TPResult TPR = isCXXDeclarationSpecifier(); 855 if (TPR != TPResult::Ambiguous()) 856 return TPR; 857 858 if (Tok.is(tok::kw_typeof)) 859 TryParseTypeofSpecifier(); 860 else 861 ConsumeToken(); 862 863 assert(Tok.is(tok::l_paren) && "Expected '('!"); 864 return TPResult::Ambiguous(); 865} 866 867/// isCXXFunctionDeclarator - Disambiguates between a function declarator or 868/// a constructor-style initializer, when parsing declaration statements. 869/// Returns true for function declarator and false for constructor-style 870/// initializer. 871/// If during the disambiguation process a parsing error is encountered, 872/// the function returns true to let the declaration parsing code handle it. 873/// 874/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 875/// exception-specification[opt] 876/// 877bool Parser::isCXXFunctionDeclarator(bool warnIfAmbiguous) { 878 879 // C++ 8.2p1: 880 // The ambiguity arising from the similarity between a function-style cast and 881 // a declaration mentioned in 6.8 can also occur in the context of a 882 // declaration. In that context, the choice is between a function declaration 883 // with a redundant set of parentheses around a parameter name and an object 884 // declaration with a function-style cast as the initializer. Just as for the 885 // ambiguities mentioned in 6.8, the resolution is to consider any construct 886 // that could possibly be a declaration a declaration. 887 888 TentativeParsingAction PA(*this); 889 890 ConsumeParen(); 891 TPResult TPR = TryParseParameterDeclarationClause(); 892 if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) 893 TPR = TPResult::False(); 894 895 SourceLocation TPLoc = Tok.getLocation(); 896 PA.Revert(); 897 898 // In case of an error, let the declaration parsing code handle it. 899 if (TPR == TPResult::Error()) 900 return true; 901 902 if (TPR == TPResult::Ambiguous()) { 903 // Function declarator has precedence over constructor-style initializer. 904 // Emit a warning just in case the author intended a variable definition. 905 if (warnIfAmbiguous) 906 Diag(Tok, diag::warn_parens_disambiguated_as_function_decl) 907 << SourceRange(Tok.getLocation(), TPLoc); 908 return true; 909 } 910 911 return TPR == TPResult::True(); 912} 913 914/// parameter-declaration-clause: 915/// parameter-declaration-list[opt] '...'[opt] 916/// parameter-declaration-list ',' '...' 917/// 918/// parameter-declaration-list: 919/// parameter-declaration 920/// parameter-declaration-list ',' parameter-declaration 921/// 922/// parameter-declaration: 923/// decl-specifier-seq declarator 924/// decl-specifier-seq declarator '=' assignment-expression 925/// decl-specifier-seq abstract-declarator[opt] 926/// decl-specifier-seq abstract-declarator[opt] '=' assignment-expression 927/// 928Parser::TPResult Parser::TryParseParameterDeclarationClause() { 929 930 if (Tok.is(tok::r_paren)) 931 return TPResult::True(); 932 933 // parameter-declaration-list[opt] '...'[opt] 934 // parameter-declaration-list ',' '...' 935 // 936 // parameter-declaration-list: 937 // parameter-declaration 938 // parameter-declaration-list ',' parameter-declaration 939 // 940 while (1) { 941 // '...'[opt] 942 if (Tok.is(tok::ellipsis)) { 943 ConsumeToken(); 944 return TPResult::True(); // '...' is a sign of a function declarator. 945 } 946 947 // decl-specifier-seq 948 TPResult TPR = TryParseDeclarationSpecifier(); 949 if (TPR != TPResult::Ambiguous()) 950 return TPR; 951 952 // declarator 953 // abstract-declarator[opt] 954 TPR = TryParseDeclarator(true/*mayBeAbstract*/); 955 if (TPR != TPResult::Ambiguous()) 956 return TPR; 957 958 if (Tok.is(tok::equal)) { 959 // '=' assignment-expression 960 // Parse through assignment-expression. 961 tok::TokenKind StopToks[3] ={ tok::comma, tok::ellipsis, tok::r_paren }; 962 if (!SkipUntil(StopToks, 3, true/*StopAtSemi*/, true/*DontConsume*/)) 963 return TPResult::Error(); 964 } 965 966 if (Tok.is(tok::ellipsis)) { 967 ConsumeToken(); 968 return TPResult::True(); // '...' is a sign of a function declarator. 969 } 970 971 if (Tok.isNot(tok::comma)) 972 break; 973 ConsumeToken(); // the comma. 974 } 975 976 return TPResult::Ambiguous(); 977} 978 979/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue 980/// parsing as a function declarator. 981/// If TryParseFunctionDeclarator fully parsed the function declarator, it will 982/// return TPResult::Ambiguous(), otherwise it will return either False() or 983/// Error(). 984/// 985/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 986/// exception-specification[opt] 987/// 988/// exception-specification: 989/// 'throw' '(' type-id-list[opt] ')' 990/// 991Parser::TPResult Parser::TryParseFunctionDeclarator() { 992 993 // The '(' is already parsed. 994 995 TPResult TPR = TryParseParameterDeclarationClause(); 996 if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) 997 TPR = TPResult::False(); 998 999 if (TPR == TPResult::False() || TPR == TPResult::Error()) 1000 return TPR; 1001 1002 // Parse through the parens. 1003 if (!SkipUntil(tok::r_paren)) 1004 return TPResult::Error(); 1005 1006 // cv-qualifier-seq 1007 while (Tok.is(tok::kw_const) || 1008 Tok.is(tok::kw_volatile) || 1009 Tok.is(tok::kw_restrict) ) 1010 ConsumeToken(); 1011 1012 // exception-specification 1013 if (Tok.is(tok::kw_throw)) { 1014 ConsumeToken(); 1015 if (Tok.isNot(tok::l_paren)) 1016 return TPResult::Error(); 1017 1018 // Parse through the parens after 'throw'. 1019 ConsumeParen(); 1020 if (!SkipUntil(tok::r_paren)) 1021 return TPResult::Error(); 1022 } 1023 1024 return TPResult::Ambiguous(); 1025} 1026 1027/// '[' constant-expression[opt] ']' 1028/// 1029Parser::TPResult Parser::TryParseBracketDeclarator() { 1030 ConsumeBracket(); 1031 if (!SkipUntil(tok::r_square)) 1032 return TPResult::Error(); 1033 1034 return TPResult::Ambiguous(); 1035} 1036