ParseTentative.cpp revision 2ee9b408a5cf3055fd974f01025b80fb3fd5f7e6
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 case tok::kw_typename: // typename T::type 676 // Annotate typenames and C++ scope specifiers. If we get one, just 677 // recurse to handle whatever we get. 678 if (TryAnnotateTypeOrScopeToken()) 679 return isCXXDeclarationSpecifier(); 680 // Otherwise, not a typename. 681 return TPResult::False(); 682 683 case tok::coloncolon: { // ::foo::bar 684 const Token &Next = NextToken(); 685 if (Next.is(tok::kw_new) || // ::new 686 Next.is(tok::kw_delete)) // ::delete 687 return TPResult::False(); 688 689 // Annotate typenames and C++ scope specifiers. If we get one, just 690 // recurse to handle whatever we get. 691 if (TryAnnotateTypeOrScopeToken()) 692 return isCXXDeclarationSpecifier(); 693 // Otherwise, not a typename. 694 return TPResult::False(); 695 } 696 697 // decl-specifier: 698 // storage-class-specifier 699 // type-specifier 700 // function-specifier 701 // 'friend' 702 // 'typedef' 703 // 'constexpr' 704 case tok::kw_friend: 705 case tok::kw_typedef: 706 case tok::kw_constexpr: 707 // storage-class-specifier 708 case tok::kw_register: 709 case tok::kw_static: 710 case tok::kw_extern: 711 case tok::kw_mutable: 712 case tok::kw_auto: 713 case tok::kw___thread: 714 // function-specifier 715 case tok::kw_inline: 716 case tok::kw_virtual: 717 case tok::kw_explicit: 718 719 // type-specifier: 720 // simple-type-specifier 721 // class-specifier 722 // enum-specifier 723 // elaborated-type-specifier 724 // typename-specifier 725 // cv-qualifier 726 727 // class-specifier 728 // elaborated-type-specifier 729 case tok::kw_class: 730 case tok::kw_struct: 731 case tok::kw_union: 732 // enum-specifier 733 case tok::kw_enum: 734 // cv-qualifier 735 case tok::kw_const: 736 case tok::kw_volatile: 737 738 // GNU 739 case tok::kw_restrict: 740 case tok::kw__Complex: 741 case tok::kw___attribute: 742 return TPResult::True(); 743 744 // Microsoft 745 case tok::kw___declspec: 746 case tok::kw___cdecl: 747 case tok::kw___stdcall: 748 case tok::kw___fastcall: 749 case tok::kw___w64: 750 case tok::kw___ptr64: 751 case tok::kw___forceinline: 752 return TPResult::True(); 753 754 case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed 755 // We've already annotated a scope; try to annotate a type. 756 if (!(TryAnnotateTypeOrScopeToken() && Tok.is(tok::annot_typename))) 757 return TPResult::False(); 758 // If that succeeded, fallthrough into the generic simple-type-id case. 759 760 // The ambiguity resides in a simple-type-specifier/typename-specifier 761 // followed by a '('. The '(' could either be the start of: 762 // 763 // direct-declarator: 764 // '(' declarator ')' 765 // 766 // direct-abstract-declarator: 767 // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 768 // exception-specification[opt] 769 // '(' abstract-declarator ')' 770 // 771 // or part of a function-style cast expression: 772 // 773 // simple-type-specifier '(' expression-list[opt] ')' 774 // 775 776 // simple-type-specifier: 777 778 case tok::kw_char: 779 case tok::kw_wchar_t: 780 case tok::kw_char16_t: 781 case tok::kw_char32_t: 782 case tok::kw_bool: 783 case tok::kw_short: 784 case tok::kw_int: 785 case tok::kw_long: 786 case tok::kw_signed: 787 case tok::kw_unsigned: 788 case tok::kw_float: 789 case tok::kw_double: 790 case tok::kw_void: 791 case tok::annot_typename: 792 if (NextToken().is(tok::l_paren)) 793 return TPResult::Ambiguous(); 794 795 return TPResult::True(); 796 797 // GNU typeof support. 798 case tok::kw_typeof: { 799 if (NextToken().isNot(tok::l_paren)) 800 return TPResult::True(); 801 802 TentativeParsingAction PA(*this); 803 804 TPResult TPR = TryParseTypeofSpecifier(); 805 bool isFollowedByParen = Tok.is(tok::l_paren); 806 807 PA.Revert(); 808 809 if (TPR == TPResult::Error()) 810 return TPResult::Error(); 811 812 if (isFollowedByParen) 813 return TPResult::Ambiguous(); 814 815 return TPResult::True(); 816 } 817 818 // C++0x decltype support. 819 case tok::kw_decltype: 820 return TPResult::True(); 821 822 default: 823 return TPResult::False(); 824 } 825} 826 827/// [GNU] typeof-specifier: 828/// 'typeof' '(' expressions ')' 829/// 'typeof' '(' type-name ')' 830/// 831Parser::TPResult Parser::TryParseTypeofSpecifier() { 832 assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!"); 833 ConsumeToken(); 834 835 assert(Tok.is(tok::l_paren) && "Expected '('"); 836 // Parse through the parens after 'typeof'. 837 ConsumeParen(); 838 if (!SkipUntil(tok::r_paren)) 839 return TPResult::Error(); 840 841 return TPResult::Ambiguous(); 842} 843 844Parser::TPResult Parser::TryParseDeclarationSpecifier() { 845 TPResult TPR = isCXXDeclarationSpecifier(); 846 if (TPR != TPResult::Ambiguous()) 847 return TPR; 848 849 if (Tok.is(tok::kw_typeof)) 850 TryParseTypeofSpecifier(); 851 else 852 ConsumeToken(); 853 854 assert(Tok.is(tok::l_paren) && "Expected '('!"); 855 return TPResult::Ambiguous(); 856} 857 858/// isCXXFunctionDeclarator - Disambiguates between a function declarator or 859/// a constructor-style initializer, when parsing declaration statements. 860/// Returns true for function declarator and false for constructor-style 861/// initializer. 862/// If during the disambiguation process a parsing error is encountered, 863/// the function returns true to let the declaration parsing code handle it. 864/// 865/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 866/// exception-specification[opt] 867/// 868bool Parser::isCXXFunctionDeclarator(bool warnIfAmbiguous) { 869 870 // C++ 8.2p1: 871 // The ambiguity arising from the similarity between a function-style cast and 872 // a declaration mentioned in 6.8 can also occur in the context of a 873 // declaration. In that context, the choice is between a function declaration 874 // with a redundant set of parentheses around a parameter name and an object 875 // declaration with a function-style cast as the initializer. Just as for the 876 // ambiguities mentioned in 6.8, the resolution is to consider any construct 877 // that could possibly be a declaration a declaration. 878 879 TentativeParsingAction PA(*this); 880 881 ConsumeParen(); 882 TPResult TPR = TryParseParameterDeclarationClause(); 883 if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) 884 TPR = TPResult::False(); 885 886 SourceLocation TPLoc = Tok.getLocation(); 887 PA.Revert(); 888 889 // In case of an error, let the declaration parsing code handle it. 890 if (TPR == TPResult::Error()) 891 return true; 892 893 if (TPR == TPResult::Ambiguous()) { 894 // Function declarator has precedence over constructor-style initializer. 895 // Emit a warning just in case the author intended a variable definition. 896 if (warnIfAmbiguous) 897 Diag(Tok, diag::warn_parens_disambiguated_as_function_decl) 898 << SourceRange(Tok.getLocation(), TPLoc); 899 return true; 900 } 901 902 return TPR == TPResult::True(); 903} 904 905/// parameter-declaration-clause: 906/// parameter-declaration-list[opt] '...'[opt] 907/// parameter-declaration-list ',' '...' 908/// 909/// parameter-declaration-list: 910/// parameter-declaration 911/// parameter-declaration-list ',' parameter-declaration 912/// 913/// parameter-declaration: 914/// decl-specifier-seq declarator 915/// decl-specifier-seq declarator '=' assignment-expression 916/// decl-specifier-seq abstract-declarator[opt] 917/// decl-specifier-seq abstract-declarator[opt] '=' assignment-expression 918/// 919Parser::TPResult Parser::TryParseParameterDeclarationClause() { 920 921 if (Tok.is(tok::r_paren)) 922 return TPResult::True(); 923 924 // parameter-declaration-list[opt] '...'[opt] 925 // parameter-declaration-list ',' '...' 926 // 927 // parameter-declaration-list: 928 // parameter-declaration 929 // parameter-declaration-list ',' parameter-declaration 930 // 931 while (1) { 932 // '...'[opt] 933 if (Tok.is(tok::ellipsis)) { 934 ConsumeToken(); 935 return TPResult::True(); // '...' is a sign of a function declarator. 936 } 937 938 // decl-specifier-seq 939 TPResult TPR = TryParseDeclarationSpecifier(); 940 if (TPR != TPResult::Ambiguous()) 941 return TPR; 942 943 // declarator 944 // abstract-declarator[opt] 945 TPR = TryParseDeclarator(true/*mayBeAbstract*/); 946 if (TPR != TPResult::Ambiguous()) 947 return TPR; 948 949 if (Tok.is(tok::equal)) { 950 // '=' assignment-expression 951 // Parse through assignment-expression. 952 tok::TokenKind StopToks[3] ={ tok::comma, tok::ellipsis, tok::r_paren }; 953 if (!SkipUntil(StopToks, 3, true/*StopAtSemi*/, true/*DontConsume*/)) 954 return TPResult::Error(); 955 } 956 957 if (Tok.is(tok::ellipsis)) { 958 ConsumeToken(); 959 return TPResult::True(); // '...' is a sign of a function declarator. 960 } 961 962 if (Tok.isNot(tok::comma)) 963 break; 964 ConsumeToken(); // the comma. 965 } 966 967 return TPResult::Ambiguous(); 968} 969 970/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue 971/// parsing as a function declarator. 972/// If TryParseFunctionDeclarator fully parsed the function declarator, it will 973/// return TPResult::Ambiguous(), otherwise it will return either False() or 974/// Error(). 975/// 976/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 977/// exception-specification[opt] 978/// 979/// exception-specification: 980/// 'throw' '(' type-id-list[opt] ')' 981/// 982Parser::TPResult Parser::TryParseFunctionDeclarator() { 983 984 // The '(' is already parsed. 985 986 TPResult TPR = TryParseParameterDeclarationClause(); 987 if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) 988 TPR = TPResult::False(); 989 990 if (TPR == TPResult::False() || TPR == TPResult::Error()) 991 return TPR; 992 993 // Parse through the parens. 994 if (!SkipUntil(tok::r_paren)) 995 return TPResult::Error(); 996 997 // cv-qualifier-seq 998 while (Tok.is(tok::kw_const) || 999 Tok.is(tok::kw_volatile) || 1000 Tok.is(tok::kw_restrict) ) 1001 ConsumeToken(); 1002 1003 // exception-specification 1004 if (Tok.is(tok::kw_throw)) { 1005 ConsumeToken(); 1006 if (Tok.isNot(tok::l_paren)) 1007 return TPResult::Error(); 1008 1009 // Parse through the parens after 'throw'. 1010 ConsumeParen(); 1011 if (!SkipUntil(tok::r_paren)) 1012 return TPResult::Error(); 1013 } 1014 1015 return TPResult::Ambiguous(); 1016} 1017 1018/// '[' constant-expression[opt] ']' 1019/// 1020Parser::TPResult Parser::TryParseBracketDeclarator() { 1021 ConsumeBracket(); 1022 if (!SkipUntil(tok::r_square)) 1023 return TPResult::Error(); 1024 1025 return TPResult::Ambiguous(); 1026} 1027