ParseTentative.cpp revision 9ba6166f4a78722e7df8ffbd64eb788bfdf2764a
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 if (TryAnnotateCXXScopeToken(true)) 495 return TPResult::Error(); 496 497 if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) || 498 (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) { 499 // ptr-operator 500 ConsumeToken(); 501 while (Tok.is(tok::kw_const) || 502 Tok.is(tok::kw_volatile) || 503 Tok.is(tok::kw_restrict)) 504 ConsumeToken(); 505 } else { 506 break; 507 } 508 } 509 510 // direct-declarator: 511 // direct-abstract-declarator: 512 513 if ((Tok.is(tok::identifier) || 514 (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) && 515 mayHaveIdentifier) { 516 // declarator-id 517 if (Tok.is(tok::annot_cxxscope)) 518 ConsumeToken(); 519 ConsumeToken(); 520 } else if (Tok.is(tok::l_paren)) { 521 ConsumeParen(); 522 if (mayBeAbstract && 523 (Tok.is(tok::r_paren) || // 'int()' is a function. 524 Tok.is(tok::ellipsis) || // 'int(...)' is a function. 525 isDeclarationSpecifier())) { // 'int(int)' is a function. 526 // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 527 // exception-specification[opt] 528 TPResult TPR = TryParseFunctionDeclarator(); 529 if (TPR != TPResult::Ambiguous()) 530 return TPR; 531 } else { 532 // '(' declarator ')' 533 // '(' attributes declarator ')' 534 // '(' abstract-declarator ')' 535 if (Tok.is(tok::kw___attribute)) 536 return TPResult::True(); // attributes indicate declaration 537 TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier); 538 if (TPR != TPResult::Ambiguous()) 539 return TPR; 540 if (Tok.isNot(tok::r_paren)) 541 return TPResult::False(); 542 ConsumeParen(); 543 } 544 } else if (!mayBeAbstract) { 545 return TPResult::False(); 546 } 547 548 while (1) { 549 TPResult TPR(TPResult::Ambiguous()); 550 551 if (Tok.is(tok::l_paren)) { 552 // Check whether we have a function declarator or a possible ctor-style 553 // initializer that follows the declarator. Note that ctor-style 554 // initializers are not possible in contexts where abstract declarators 555 // are allowed. 556 if (!mayBeAbstract && !isCXXFunctionDeclarator(false/*warnIfAmbiguous*/)) 557 break; 558 559 // direct-declarator '(' parameter-declaration-clause ')' 560 // cv-qualifier-seq[opt] exception-specification[opt] 561 ConsumeParen(); 562 TPR = TryParseFunctionDeclarator(); 563 } else if (Tok.is(tok::l_square)) { 564 // direct-declarator '[' constant-expression[opt] ']' 565 // direct-abstract-declarator[opt] '[' constant-expression[opt] ']' 566 TPR = TryParseBracketDeclarator(); 567 } else { 568 break; 569 } 570 571 if (TPR != TPResult::Ambiguous()) 572 return TPR; 573 } 574 575 return TPResult::Ambiguous(); 576} 577 578/// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration 579/// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could 580/// be either a decl-specifier or a function-style cast, and TPResult::Error() 581/// if a parsing error was found and reported. 582/// 583/// decl-specifier: 584/// storage-class-specifier 585/// type-specifier 586/// function-specifier 587/// 'friend' 588/// 'typedef' 589/// [C++0x] 'constexpr' 590/// [GNU] attributes declaration-specifiers[opt] 591/// 592/// storage-class-specifier: 593/// 'register' 594/// 'static' 595/// 'extern' 596/// 'mutable' 597/// 'auto' 598/// [GNU] '__thread' 599/// 600/// function-specifier: 601/// 'inline' 602/// 'virtual' 603/// 'explicit' 604/// 605/// typedef-name: 606/// identifier 607/// 608/// type-specifier: 609/// simple-type-specifier 610/// class-specifier 611/// enum-specifier 612/// elaborated-type-specifier 613/// typename-specifier 614/// cv-qualifier 615/// 616/// simple-type-specifier: 617/// '::'[opt] nested-name-specifier[opt] type-name 618/// '::'[opt] nested-name-specifier 'template' 619/// simple-template-id [TODO] 620/// 'char' 621/// 'wchar_t' 622/// 'bool' 623/// 'short' 624/// 'int' 625/// 'long' 626/// 'signed' 627/// 'unsigned' 628/// 'float' 629/// 'double' 630/// 'void' 631/// [GNU] typeof-specifier 632/// [GNU] '_Complex' 633/// [C++0x] 'auto' [TODO] 634/// [C++0x] 'decltype' ( expression ) 635/// 636/// type-name: 637/// class-name 638/// enum-name 639/// typedef-name 640/// 641/// elaborated-type-specifier: 642/// class-key '::'[opt] nested-name-specifier[opt] identifier 643/// class-key '::'[opt] nested-name-specifier[opt] 'template'[opt] 644/// simple-template-id 645/// 'enum' '::'[opt] nested-name-specifier[opt] identifier 646/// 647/// enum-name: 648/// identifier 649/// 650/// enum-specifier: 651/// 'enum' identifier[opt] '{' enumerator-list[opt] '}' 652/// 'enum' identifier[opt] '{' enumerator-list ',' '}' 653/// 654/// class-specifier: 655/// class-head '{' member-specification[opt] '}' 656/// 657/// class-head: 658/// class-key identifier[opt] base-clause[opt] 659/// class-key nested-name-specifier identifier base-clause[opt] 660/// class-key nested-name-specifier[opt] simple-template-id 661/// base-clause[opt] 662/// 663/// class-key: 664/// 'class' 665/// 'struct' 666/// 'union' 667/// 668/// cv-qualifier: 669/// 'const' 670/// 'volatile' 671/// [GNU] restrict 672/// 673Parser::TPResult Parser::isCXXDeclarationSpecifier() { 674 switch (Tok.getKind()) { 675 case tok::identifier: // foo::bar 676 // Check for need to substitute AltiVec __vector keyword 677 // for "vector" identifier. 678 if (TryAltiVecVectorToken()) 679 return TPResult::True(); 680 // Fall through. 681 case tok::kw_typename: // typename T::type 682 // Annotate typenames and C++ scope specifiers. If we get one, just 683 // recurse to handle whatever we get. 684 if (TryAnnotateTypeOrScopeToken()) 685 return TPResult::Error(); 686 if (Tok.is(tok::identifier)) 687 return TPResult::False(); 688 return isCXXDeclarationSpecifier(); 689 690 case tok::coloncolon: { // ::foo::bar 691 const Token &Next = NextToken(); 692 if (Next.is(tok::kw_new) || // ::new 693 Next.is(tok::kw_delete)) // ::delete 694 return TPResult::False(); 695 696 // Annotate typenames and C++ scope specifiers. If we get one, just 697 // recurse to handle whatever we get. 698 if (TryAnnotateTypeOrScopeToken()) 699 return TPResult::Error(); 700 return isCXXDeclarationSpecifier(); 701 } 702 703 // decl-specifier: 704 // storage-class-specifier 705 // type-specifier 706 // function-specifier 707 // 'friend' 708 // 'typedef' 709 // 'constexpr' 710 case tok::kw_friend: 711 case tok::kw_typedef: 712 case tok::kw_constexpr: 713 // storage-class-specifier 714 case tok::kw_register: 715 case tok::kw_static: 716 case tok::kw_extern: 717 case tok::kw_mutable: 718 case tok::kw_auto: 719 case tok::kw___thread: 720 // function-specifier 721 case tok::kw_inline: 722 case tok::kw_virtual: 723 case tok::kw_explicit: 724 725 // type-specifier: 726 // simple-type-specifier 727 // class-specifier 728 // enum-specifier 729 // elaborated-type-specifier 730 // typename-specifier 731 // cv-qualifier 732 733 // class-specifier 734 // elaborated-type-specifier 735 case tok::kw_class: 736 case tok::kw_struct: 737 case tok::kw_union: 738 // enum-specifier 739 case tok::kw_enum: 740 // cv-qualifier 741 case tok::kw_const: 742 case tok::kw_volatile: 743 744 // GNU 745 case tok::kw_restrict: 746 case tok::kw__Complex: 747 case tok::kw___attribute: 748 return TPResult::True(); 749 750 // Microsoft 751 case tok::kw___declspec: 752 case tok::kw___cdecl: 753 case tok::kw___stdcall: 754 case tok::kw___fastcall: 755 case tok::kw___w64: 756 case tok::kw___ptr64: 757 case tok::kw___forceinline: 758 return TPResult::True(); 759 760 // AltiVec 761 case tok::kw___vector: 762 return TPResult::True(); 763 764 case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed 765 // We've already annotated a scope; try to annotate a type. 766 if (TryAnnotateTypeOrScopeToken()) 767 return TPResult::Error(); 768 if (!Tok.is(tok::annot_typename)) 769 return TPResult::False(); 770 // If that succeeded, fallthrough into the generic simple-type-id case. 771 772 // The ambiguity resides in a simple-type-specifier/typename-specifier 773 // followed by a '('. The '(' could either be the start of: 774 // 775 // direct-declarator: 776 // '(' declarator ')' 777 // 778 // direct-abstract-declarator: 779 // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 780 // exception-specification[opt] 781 // '(' abstract-declarator ')' 782 // 783 // or part of a function-style cast expression: 784 // 785 // simple-type-specifier '(' expression-list[opt] ')' 786 // 787 788 // simple-type-specifier: 789 790 case tok::kw_char: 791 case tok::kw_wchar_t: 792 case tok::kw_char16_t: 793 case tok::kw_char32_t: 794 case tok::kw_bool: 795 case tok::kw_short: 796 case tok::kw_int: 797 case tok::kw_long: 798 case tok::kw_signed: 799 case tok::kw_unsigned: 800 case tok::kw_float: 801 case tok::kw_double: 802 case tok::kw_void: 803 case tok::annot_typename: 804 if (NextToken().is(tok::l_paren)) 805 return TPResult::Ambiguous(); 806 807 return TPResult::True(); 808 809 // GNU typeof support. 810 case tok::kw_typeof: { 811 if (NextToken().isNot(tok::l_paren)) 812 return TPResult::True(); 813 814 TentativeParsingAction PA(*this); 815 816 TPResult TPR = TryParseTypeofSpecifier(); 817 bool isFollowedByParen = Tok.is(tok::l_paren); 818 819 PA.Revert(); 820 821 if (TPR == TPResult::Error()) 822 return TPResult::Error(); 823 824 if (isFollowedByParen) 825 return TPResult::Ambiguous(); 826 827 return TPResult::True(); 828 } 829 830 // C++0x decltype support. 831 case tok::kw_decltype: 832 return TPResult::True(); 833 834 default: 835 return TPResult::False(); 836 } 837} 838 839/// [GNU] typeof-specifier: 840/// 'typeof' '(' expressions ')' 841/// 'typeof' '(' type-name ')' 842/// 843Parser::TPResult Parser::TryParseTypeofSpecifier() { 844 assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!"); 845 ConsumeToken(); 846 847 assert(Tok.is(tok::l_paren) && "Expected '('"); 848 // Parse through the parens after 'typeof'. 849 ConsumeParen(); 850 if (!SkipUntil(tok::r_paren)) 851 return TPResult::Error(); 852 853 return TPResult::Ambiguous(); 854} 855 856Parser::TPResult Parser::TryParseDeclarationSpecifier() { 857 TPResult TPR = isCXXDeclarationSpecifier(); 858 if (TPR != TPResult::Ambiguous()) 859 return TPR; 860 861 if (Tok.is(tok::kw_typeof)) 862 TryParseTypeofSpecifier(); 863 else 864 ConsumeToken(); 865 866 assert(Tok.is(tok::l_paren) && "Expected '('!"); 867 return TPResult::Ambiguous(); 868} 869 870/// isCXXFunctionDeclarator - Disambiguates between a function declarator or 871/// a constructor-style initializer, when parsing declaration statements. 872/// Returns true for function declarator and false for constructor-style 873/// initializer. 874/// If during the disambiguation process a parsing error is encountered, 875/// the function returns true to let the declaration parsing code handle it. 876/// 877/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 878/// exception-specification[opt] 879/// 880bool Parser::isCXXFunctionDeclarator(bool warnIfAmbiguous) { 881 882 // C++ 8.2p1: 883 // The ambiguity arising from the similarity between a function-style cast and 884 // a declaration mentioned in 6.8 can also occur in the context of a 885 // declaration. In that context, the choice is between a function declaration 886 // with a redundant set of parentheses around a parameter name and an object 887 // declaration with a function-style cast as the initializer. Just as for the 888 // ambiguities mentioned in 6.8, the resolution is to consider any construct 889 // that could possibly be a declaration a declaration. 890 891 TentativeParsingAction PA(*this); 892 893 ConsumeParen(); 894 TPResult TPR = TryParseParameterDeclarationClause(); 895 if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) 896 TPR = TPResult::False(); 897 898 SourceLocation TPLoc = Tok.getLocation(); 899 PA.Revert(); 900 901 // In case of an error, let the declaration parsing code handle it. 902 if (TPR == TPResult::Error()) 903 return true; 904 905 if (TPR == TPResult::Ambiguous()) { 906 // Function declarator has precedence over constructor-style initializer. 907 // Emit a warning just in case the author intended a variable definition. 908 if (warnIfAmbiguous) 909 Diag(Tok, diag::warn_parens_disambiguated_as_function_decl) 910 << SourceRange(Tok.getLocation(), TPLoc); 911 return true; 912 } 913 914 return TPR == TPResult::True(); 915} 916 917/// parameter-declaration-clause: 918/// parameter-declaration-list[opt] '...'[opt] 919/// parameter-declaration-list ',' '...' 920/// 921/// parameter-declaration-list: 922/// parameter-declaration 923/// parameter-declaration-list ',' parameter-declaration 924/// 925/// parameter-declaration: 926/// decl-specifier-seq declarator 927/// decl-specifier-seq declarator '=' assignment-expression 928/// decl-specifier-seq abstract-declarator[opt] 929/// decl-specifier-seq abstract-declarator[opt] '=' assignment-expression 930/// 931Parser::TPResult Parser::TryParseParameterDeclarationClause() { 932 933 if (Tok.is(tok::r_paren)) 934 return TPResult::True(); 935 936 // parameter-declaration-list[opt] '...'[opt] 937 // parameter-declaration-list ',' '...' 938 // 939 // parameter-declaration-list: 940 // parameter-declaration 941 // parameter-declaration-list ',' parameter-declaration 942 // 943 while (1) { 944 // '...'[opt] 945 if (Tok.is(tok::ellipsis)) { 946 ConsumeToken(); 947 return TPResult::True(); // '...' is a sign of a function declarator. 948 } 949 950 // decl-specifier-seq 951 TPResult TPR = TryParseDeclarationSpecifier(); 952 if (TPR != TPResult::Ambiguous()) 953 return TPR; 954 955 // declarator 956 // abstract-declarator[opt] 957 TPR = TryParseDeclarator(true/*mayBeAbstract*/); 958 if (TPR != TPResult::Ambiguous()) 959 return TPR; 960 961 if (Tok.is(tok::equal)) { 962 // '=' assignment-expression 963 // Parse through assignment-expression. 964 tok::TokenKind StopToks[3] ={ tok::comma, tok::ellipsis, tok::r_paren }; 965 if (!SkipUntil(StopToks, 3, true/*StopAtSemi*/, true/*DontConsume*/)) 966 return TPResult::Error(); 967 } 968 969 if (Tok.is(tok::ellipsis)) { 970 ConsumeToken(); 971 return TPResult::True(); // '...' is a sign of a function declarator. 972 } 973 974 if (Tok.isNot(tok::comma)) 975 break; 976 ConsumeToken(); // the comma. 977 } 978 979 return TPResult::Ambiguous(); 980} 981 982/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue 983/// parsing as a function declarator. 984/// If TryParseFunctionDeclarator fully parsed the function declarator, it will 985/// return TPResult::Ambiguous(), otherwise it will return either False() or 986/// Error(). 987/// 988/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] 989/// exception-specification[opt] 990/// 991/// exception-specification: 992/// 'throw' '(' type-id-list[opt] ')' 993/// 994Parser::TPResult Parser::TryParseFunctionDeclarator() { 995 996 // The '(' is already parsed. 997 998 TPResult TPR = TryParseParameterDeclarationClause(); 999 if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren)) 1000 TPR = TPResult::False(); 1001 1002 if (TPR == TPResult::False() || TPR == TPResult::Error()) 1003 return TPR; 1004 1005 // Parse through the parens. 1006 if (!SkipUntil(tok::r_paren)) 1007 return TPResult::Error(); 1008 1009 // cv-qualifier-seq 1010 while (Tok.is(tok::kw_const) || 1011 Tok.is(tok::kw_volatile) || 1012 Tok.is(tok::kw_restrict) ) 1013 ConsumeToken(); 1014 1015 // exception-specification 1016 if (Tok.is(tok::kw_throw)) { 1017 ConsumeToken(); 1018 if (Tok.isNot(tok::l_paren)) 1019 return TPResult::Error(); 1020 1021 // Parse through the parens after 'throw'. 1022 ConsumeParen(); 1023 if (!SkipUntil(tok::r_paren)) 1024 return TPResult::Error(); 1025 } 1026 1027 return TPResult::Ambiguous(); 1028} 1029 1030/// '[' constant-expression[opt] ']' 1031/// 1032Parser::TPResult Parser::TryParseBracketDeclarator() { 1033 ConsumeBracket(); 1034 if (!SkipUntil(tok::r_square)) 1035 return TPResult::Error(); 1036 1037 return TPResult::Ambiguous(); 1038} 1039