ParseExprCXX.cpp revision 194613
1//===--- ParseExprCXX.cpp - C++ Expression 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 Expression parsing implementation for C++. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/Parse/ParseDiagnostic.h" 15#include "clang/Parse/Parser.h" 16#include "clang/Parse/DeclSpec.h" 17using namespace clang; 18 19/// ParseOptionalCXXScopeSpecifier - Parse global scope or 20/// nested-name-specifier if present. Returns true if a nested-name-specifier 21/// was parsed from the token stream. Note that this routine will not parse 22/// ::new or ::delete, it will just leave them in the token stream. 23/// 24/// '::'[opt] nested-name-specifier 25/// '::' 26/// 27/// nested-name-specifier: 28/// type-name '::' 29/// namespace-name '::' 30/// nested-name-specifier identifier '::' 31/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO] 32/// 33bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) { 34 assert(getLang().CPlusPlus && 35 "Call sites of this function should be guarded by checking for C++"); 36 37 if (Tok.is(tok::annot_cxxscope)) { 38 SS.setScopeRep(Tok.getAnnotationValue()); 39 SS.setRange(Tok.getAnnotationRange()); 40 ConsumeToken(); 41 return true; 42 } 43 44 bool HasScopeSpecifier = false; 45 46 if (Tok.is(tok::coloncolon)) { 47 // ::new and ::delete aren't nested-name-specifiers. 48 tok::TokenKind NextKind = NextToken().getKind(); 49 if (NextKind == tok::kw_new || NextKind == tok::kw_delete) 50 return false; 51 52 // '::' - Global scope qualifier. 53 SourceLocation CCLoc = ConsumeToken(); 54 SS.setBeginLoc(CCLoc); 55 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc)); 56 SS.setEndLoc(CCLoc); 57 HasScopeSpecifier = true; 58 } 59 60 while (true) { 61 // nested-name-specifier: 62 // type-name '::' 63 // namespace-name '::' 64 // nested-name-specifier identifier '::' 65 if (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) { 66 // We have an identifier followed by a '::'. Lookup this name 67 // as the name in a nested-name-specifier. 68 IdentifierInfo *II = Tok.getIdentifierInfo(); 69 SourceLocation IdLoc = ConsumeToken(); 70 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); 71 SourceLocation CCLoc = ConsumeToken(); 72 73 if (!HasScopeSpecifier) { 74 SS.setBeginLoc(IdLoc); 75 HasScopeSpecifier = true; 76 } 77 78 if (SS.isInvalid()) 79 continue; 80 81 SS.setScopeRep( 82 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II)); 83 SS.setEndLoc(CCLoc); 84 continue; 85 } 86 87 // nested-name-specifier: 88 // type-name '::' 89 // nested-name-specifier 'template'[opt] simple-template-id '::' 90 if ((Tok.is(tok::identifier) && NextToken().is(tok::less)) || 91 Tok.is(tok::kw_template)) { 92 // Parse the optional 'template' keyword, then make sure we have 93 // 'identifier <' after it. 94 if (Tok.is(tok::kw_template)) { 95 SourceLocation TemplateKWLoc = ConsumeToken(); 96 97 if (Tok.isNot(tok::identifier)) { 98 Diag(Tok.getLocation(), 99 diag::err_id_after_template_in_nested_name_spec) 100 << SourceRange(TemplateKWLoc); 101 break; 102 } 103 104 if (NextToken().isNot(tok::less)) { 105 Diag(NextToken().getLocation(), 106 diag::err_less_after_template_name_in_nested_name_spec) 107 << Tok.getIdentifierInfo()->getName() 108 << SourceRange(TemplateKWLoc, Tok.getLocation()); 109 break; 110 } 111 112 TemplateTy Template 113 = Actions.ActOnDependentTemplateName(TemplateKWLoc, 114 *Tok.getIdentifierInfo(), 115 Tok.getLocation(), 116 SS); 117 AnnotateTemplateIdToken(Template, TNK_Dependent_template_name, 118 &SS, TemplateKWLoc, false); 119 continue; 120 } 121 122 TemplateTy Template; 123 TemplateNameKind TNK = Actions.isTemplateName(*Tok.getIdentifierInfo(), 124 CurScope, Template, &SS); 125 if (TNK) { 126 // We have found a template name, so annotate this this token 127 // with a template-id annotation. We do not permit the 128 // template-id to be translated into a type annotation, 129 // because some clients (e.g., the parsing of class template 130 // specializations) still want to see the original template-id 131 // token. 132 AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(), false); 133 continue; 134 } 135 } 136 137 if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) { 138 // We have 139 // 140 // simple-template-id '::' 141 // 142 // So we need to check whether the simple-template-id is of the 143 // right kind (it should name a type or be dependent), and then 144 // convert it into a type within the nested-name-specifier. 145 TemplateIdAnnotation *TemplateId 146 = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); 147 148 if (TemplateId->Kind == TNK_Type_template || 149 TemplateId->Kind == TNK_Dependent_template_name) { 150 AnnotateTemplateIdTokenAsType(&SS); 151 SS.setScopeRep(0); 152 153 assert(Tok.is(tok::annot_typename) && 154 "AnnotateTemplateIdTokenAsType isn't working"); 155 Token TypeToken = Tok; 156 ConsumeToken(); 157 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); 158 SourceLocation CCLoc = ConsumeToken(); 159 160 if (!HasScopeSpecifier) { 161 SS.setBeginLoc(TypeToken.getLocation()); 162 HasScopeSpecifier = true; 163 } 164 165 if (TypeToken.getAnnotationValue()) 166 SS.setScopeRep( 167 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, 168 TypeToken.getAnnotationValue(), 169 TypeToken.getAnnotationRange(), 170 CCLoc)); 171 else 172 SS.setScopeRep(0); 173 SS.setEndLoc(CCLoc); 174 continue; 175 } else 176 assert(false && "FIXME: Only type template names supported here"); 177 } 178 179 // We don't have any tokens that form the beginning of a 180 // nested-name-specifier, so we're done. 181 break; 182 } 183 184 return HasScopeSpecifier; 185} 186 187/// ParseCXXIdExpression - Handle id-expression. 188/// 189/// id-expression: 190/// unqualified-id 191/// qualified-id 192/// 193/// unqualified-id: 194/// identifier 195/// operator-function-id 196/// conversion-function-id [TODO] 197/// '~' class-name [TODO] 198/// template-id [TODO] 199/// 200/// qualified-id: 201/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id 202/// '::' identifier 203/// '::' operator-function-id 204/// '::' template-id [TODO] 205/// 206/// nested-name-specifier: 207/// type-name '::' 208/// namespace-name '::' 209/// nested-name-specifier identifier '::' 210/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO] 211/// 212/// NOTE: The standard specifies that, for qualified-id, the parser does not 213/// expect: 214/// 215/// '::' conversion-function-id 216/// '::' '~' class-name 217/// 218/// This may cause a slight inconsistency on diagnostics: 219/// 220/// class C {}; 221/// namespace A {} 222/// void f() { 223/// :: A :: ~ C(); // Some Sema error about using destructor with a 224/// // namespace. 225/// :: ~ C(); // Some Parser error like 'unexpected ~'. 226/// } 227/// 228/// We simplify the parser a bit and make it work like: 229/// 230/// qualified-id: 231/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id 232/// '::' unqualified-id 233/// 234/// That way Sema can handle and report similar errors for namespaces and the 235/// global scope. 236/// 237/// The isAddressOfOperand parameter indicates that this id-expression is a 238/// direct operand of the address-of operator. This is, besides member contexts, 239/// the only place where a qualified-id naming a non-static class member may 240/// appear. 241/// 242Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { 243 // qualified-id: 244 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id 245 // '::' unqualified-id 246 // 247 CXXScopeSpec SS; 248 ParseOptionalCXXScopeSpecifier(SS); 249 250 // unqualified-id: 251 // identifier 252 // operator-function-id 253 // conversion-function-id 254 // '~' class-name [TODO] 255 // template-id [TODO] 256 // 257 switch (Tok.getKind()) { 258 default: 259 return ExprError(Diag(Tok, diag::err_expected_unqualified_id)); 260 261 case tok::identifier: { 262 // Consume the identifier so that we can see if it is followed by a '('. 263 IdentifierInfo &II = *Tok.getIdentifierInfo(); 264 SourceLocation L = ConsumeToken(); 265 return Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren), 266 &SS, isAddressOfOperand); 267 } 268 269 case tok::kw_operator: { 270 SourceLocation OperatorLoc = Tok.getLocation(); 271 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) 272 return Actions.ActOnCXXOperatorFunctionIdExpr( 273 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS, 274 isAddressOfOperand); 275 if (TypeTy *Type = ParseConversionFunctionId()) 276 return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type, 277 Tok.is(tok::l_paren), SS, 278 isAddressOfOperand); 279 280 // We already complained about a bad conversion-function-id, 281 // above. 282 return ExprError(); 283 } 284 285 } // switch. 286 287 assert(0 && "The switch was supposed to take care everything."); 288} 289 290/// ParseCXXCasts - This handles the various ways to cast expressions to another 291/// type. 292/// 293/// postfix-expression: [C++ 5.2p1] 294/// 'dynamic_cast' '<' type-name '>' '(' expression ')' 295/// 'static_cast' '<' type-name '>' '(' expression ')' 296/// 'reinterpret_cast' '<' type-name '>' '(' expression ')' 297/// 'const_cast' '<' type-name '>' '(' expression ')' 298/// 299Parser::OwningExprResult Parser::ParseCXXCasts() { 300 tok::TokenKind Kind = Tok.getKind(); 301 const char *CastName = 0; // For error messages 302 303 switch (Kind) { 304 default: assert(0 && "Unknown C++ cast!"); abort(); 305 case tok::kw_const_cast: CastName = "const_cast"; break; 306 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break; 307 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break; 308 case tok::kw_static_cast: CastName = "static_cast"; break; 309 } 310 311 SourceLocation OpLoc = ConsumeToken(); 312 SourceLocation LAngleBracketLoc = Tok.getLocation(); 313 314 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName)) 315 return ExprError(); 316 317 TypeResult CastTy = ParseTypeName(); 318 SourceLocation RAngleBracketLoc = Tok.getLocation(); 319 320 if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) 321 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<"); 322 323 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc; 324 325 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, CastName)) 326 return ExprError(); 327 328 OwningExprResult Result = ParseExpression(); 329 330 // Match the ')'. 331 if (Result.isInvalid()) 332 SkipUntil(tok::r_paren); 333 334 if (Tok.is(tok::r_paren)) 335 RParenLoc = ConsumeParen(); 336 else 337 MatchRHSPunctuation(tok::r_paren, LParenLoc); 338 339 if (!Result.isInvalid() && !CastTy.isInvalid()) 340 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind, 341 LAngleBracketLoc, CastTy.get(), 342 RAngleBracketLoc, 343 LParenLoc, move(Result), RParenLoc); 344 345 return move(Result); 346} 347 348/// ParseCXXTypeid - This handles the C++ typeid expression. 349/// 350/// postfix-expression: [C++ 5.2p1] 351/// 'typeid' '(' expression ')' 352/// 'typeid' '(' type-id ')' 353/// 354Parser::OwningExprResult Parser::ParseCXXTypeid() { 355 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!"); 356 357 SourceLocation OpLoc = ConsumeToken(); 358 SourceLocation LParenLoc = Tok.getLocation(); 359 SourceLocation RParenLoc; 360 361 // typeid expressions are always parenthesized. 362 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, 363 "typeid")) 364 return ExprError(); 365 366 OwningExprResult Result(Actions); 367 368 if (isTypeIdInParens()) { 369 TypeResult Ty = ParseTypeName(); 370 371 // Match the ')'. 372 MatchRHSPunctuation(tok::r_paren, LParenLoc); 373 374 if (Ty.isInvalid()) 375 return ExprError(); 376 377 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true, 378 Ty.get(), RParenLoc); 379 } else { 380 // C++0x [expr.typeid]p3: 381 // When typeid is applied to an expression other than an lvalue of a 382 // polymorphic class type [...] The expression is an unevaluated 383 // operand (Clause 5). 384 // 385 // Note that we can't tell whether the expression is an lvalue of a 386 // polymorphic class type until after we've parsed the expression, so 387 // we treat the expression as an unevaluated operand and let semantic 388 // analysis cope with case where the expression is not an unevaluated 389 // operand. 390 EnterUnevaluatedOperand Unevaluated(Actions); 391 Result = ParseExpression(); 392 393 // Match the ')'. 394 if (Result.isInvalid()) 395 SkipUntil(tok::r_paren); 396 else { 397 MatchRHSPunctuation(tok::r_paren, LParenLoc); 398 399 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false, 400 Result.release(), RParenLoc); 401 } 402 } 403 404 return move(Result); 405} 406 407/// ParseCXXBoolLiteral - This handles the C++ Boolean literals. 408/// 409/// boolean-literal: [C++ 2.13.5] 410/// 'true' 411/// 'false' 412Parser::OwningExprResult Parser::ParseCXXBoolLiteral() { 413 tok::TokenKind Kind = Tok.getKind(); 414 return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind); 415} 416 417/// ParseThrowExpression - This handles the C++ throw expression. 418/// 419/// throw-expression: [C++ 15] 420/// 'throw' assignment-expression[opt] 421Parser::OwningExprResult Parser::ParseThrowExpression() { 422 assert(Tok.is(tok::kw_throw) && "Not throw!"); 423 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token. 424 425 // If the current token isn't the start of an assignment-expression, 426 // then the expression is not present. This handles things like: 427 // "C ? throw : (void)42", which is crazy but legal. 428 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common. 429 case tok::semi: 430 case tok::r_paren: 431 case tok::r_square: 432 case tok::r_brace: 433 case tok::colon: 434 case tok::comma: 435 return Actions.ActOnCXXThrow(ThrowLoc, ExprArg(Actions)); 436 437 default: 438 OwningExprResult Expr(ParseAssignmentExpression()); 439 if (Expr.isInvalid()) return move(Expr); 440 return Actions.ActOnCXXThrow(ThrowLoc, move(Expr)); 441 } 442} 443 444/// ParseCXXThis - This handles the C++ 'this' pointer. 445/// 446/// C++ 9.3.2: In the body of a non-static member function, the keyword this is 447/// a non-lvalue expression whose value is the address of the object for which 448/// the function is called. 449Parser::OwningExprResult Parser::ParseCXXThis() { 450 assert(Tok.is(tok::kw_this) && "Not 'this'!"); 451 SourceLocation ThisLoc = ConsumeToken(); 452 return Actions.ActOnCXXThis(ThisLoc); 453} 454 455/// ParseCXXTypeConstructExpression - Parse construction of a specified type. 456/// Can be interpreted either as function-style casting ("int(x)") 457/// or class type construction ("ClassType(x,y,z)") 458/// or creation of a value-initialized type ("int()"). 459/// 460/// postfix-expression: [C++ 5.2p1] 461/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] 462/// typename-specifier '(' expression-list[opt] ')' [TODO] 463/// 464Parser::OwningExprResult 465Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { 466 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); 467 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get(); 468 469 assert(Tok.is(tok::l_paren) && "Expected '('!"); 470 SourceLocation LParenLoc = ConsumeParen(); 471 472 ExprVector Exprs(Actions); 473 CommaLocsTy CommaLocs; 474 475 if (Tok.isNot(tok::r_paren)) { 476 if (ParseExpressionList(Exprs, CommaLocs)) { 477 SkipUntil(tok::r_paren); 478 return ExprError(); 479 } 480 } 481 482 // Match the ')'. 483 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); 484 485 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& 486 "Unexpected number of commas!"); 487 return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep, 488 LParenLoc, move_arg(Exprs), 489 CommaLocs.data(), RParenLoc); 490} 491 492/// ParseCXXCondition - if/switch/while/for condition expression. 493/// 494/// condition: 495/// expression 496/// type-specifier-seq declarator '=' assignment-expression 497/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] 498/// '=' assignment-expression 499/// 500Parser::OwningExprResult Parser::ParseCXXCondition() { 501 if (!isCXXConditionDeclaration()) 502 return ParseExpression(); // expression 503 504 SourceLocation StartLoc = Tok.getLocation(); 505 506 // type-specifier-seq 507 DeclSpec DS; 508 ParseSpecifierQualifierList(DS); 509 510 // declarator 511 Declarator DeclaratorInfo(DS, Declarator::ConditionContext); 512 ParseDeclarator(DeclaratorInfo); 513 514 // simple-asm-expr[opt] 515 if (Tok.is(tok::kw_asm)) { 516 SourceLocation Loc; 517 OwningExprResult AsmLabel(ParseSimpleAsm(&Loc)); 518 if (AsmLabel.isInvalid()) { 519 SkipUntil(tok::semi); 520 return ExprError(); 521 } 522 DeclaratorInfo.setAsmLabel(AsmLabel.release()); 523 DeclaratorInfo.SetRangeEnd(Loc); 524 } 525 526 // If attributes are present, parse them. 527 if (Tok.is(tok::kw___attribute)) { 528 SourceLocation Loc; 529 AttributeList *AttrList = ParseAttributes(&Loc); 530 DeclaratorInfo.AddAttributes(AttrList, Loc); 531 } 532 533 // '=' assignment-expression 534 if (Tok.isNot(tok::equal)) 535 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator)); 536 SourceLocation EqualLoc = ConsumeToken(); 537 OwningExprResult AssignExpr(ParseAssignmentExpression()); 538 if (AssignExpr.isInvalid()) 539 return ExprError(); 540 541 return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc, 542 DeclaratorInfo,EqualLoc, 543 move(AssignExpr)); 544} 545 546/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. 547/// This should only be called when the current token is known to be part of 548/// simple-type-specifier. 549/// 550/// simple-type-specifier: 551/// '::'[opt] nested-name-specifier[opt] type-name 552/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO] 553/// char 554/// wchar_t 555/// bool 556/// short 557/// int 558/// long 559/// signed 560/// unsigned 561/// float 562/// double 563/// void 564/// [GNU] typeof-specifier 565/// [C++0x] auto [TODO] 566/// 567/// type-name: 568/// class-name 569/// enum-name 570/// typedef-name 571/// 572void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { 573 DS.SetRangeStart(Tok.getLocation()); 574 const char *PrevSpec; 575 SourceLocation Loc = Tok.getLocation(); 576 577 switch (Tok.getKind()) { 578 case tok::identifier: // foo::bar 579 case tok::coloncolon: // ::foo::bar 580 assert(0 && "Annotation token should already be formed!"); 581 default: 582 assert(0 && "Not a simple-type-specifier token!"); 583 abort(); 584 585 // type-name 586 case tok::annot_typename: { 587 DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, 588 Tok.getAnnotationValue()); 589 break; 590 } 591 592 // builtin types 593 case tok::kw_short: 594 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec); 595 break; 596 case tok::kw_long: 597 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec); 598 break; 599 case tok::kw_signed: 600 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec); 601 break; 602 case tok::kw_unsigned: 603 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec); 604 break; 605 case tok::kw_void: 606 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec); 607 break; 608 case tok::kw_char: 609 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec); 610 break; 611 case tok::kw_int: 612 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec); 613 break; 614 case tok::kw_float: 615 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec); 616 break; 617 case tok::kw_double: 618 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec); 619 break; 620 case tok::kw_wchar_t: 621 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec); 622 break; 623 case tok::kw_bool: 624 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec); 625 break; 626 627 // GNU typeof support. 628 case tok::kw_typeof: 629 ParseTypeofSpecifier(DS); 630 DS.Finish(Diags, PP); 631 return; 632 } 633 if (Tok.is(tok::annot_typename)) 634 DS.SetRangeEnd(Tok.getAnnotationEndLoc()); 635 else 636 DS.SetRangeEnd(Tok.getLocation()); 637 ConsumeToken(); 638 DS.Finish(Diags, PP); 639} 640 641/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++ 642/// [dcl.name]), which is a non-empty sequence of type-specifiers, 643/// e.g., "const short int". Note that the DeclSpec is *not* finished 644/// by parsing the type-specifier-seq, because these sequences are 645/// typically followed by some form of declarator. Returns true and 646/// emits diagnostics if this is not a type-specifier-seq, false 647/// otherwise. 648/// 649/// type-specifier-seq: [C++ 8.1] 650/// type-specifier type-specifier-seq[opt] 651/// 652bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { 653 DS.SetRangeStart(Tok.getLocation()); 654 const char *PrevSpec = 0; 655 int isInvalid = 0; 656 657 // Parse one or more of the type specifiers. 658 if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) { 659 Diag(Tok, diag::err_operator_missing_type_specifier); 660 return true; 661 } 662 663 while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) ; 664 665 return false; 666} 667 668/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded 669/// operator name (C++ [over.oper]). If successful, returns the 670/// predefined identifier that corresponds to that overloaded 671/// operator. Otherwise, returns NULL and does not consume any tokens. 672/// 673/// operator-function-id: [C++ 13.5] 674/// 'operator' operator 675/// 676/// operator: one of 677/// new delete new[] delete[] 678/// + - * / % ^ & | ~ 679/// ! = < > += -= *= /= %= 680/// ^= &= |= << >> >>= <<= == != 681/// <= >= && || ++ -- , ->* -> 682/// () [] 683OverloadedOperatorKind 684Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) { 685 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); 686 SourceLocation Loc; 687 688 OverloadedOperatorKind Op = OO_None; 689 switch (NextToken().getKind()) { 690 case tok::kw_new: 691 ConsumeToken(); // 'operator' 692 Loc = ConsumeToken(); // 'new' 693 if (Tok.is(tok::l_square)) { 694 ConsumeBracket(); // '[' 695 Loc = Tok.getLocation(); 696 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 697 Op = OO_Array_New; 698 } else { 699 Op = OO_New; 700 } 701 if (EndLoc) 702 *EndLoc = Loc; 703 return Op; 704 705 case tok::kw_delete: 706 ConsumeToken(); // 'operator' 707 Loc = ConsumeToken(); // 'delete' 708 if (Tok.is(tok::l_square)) { 709 ConsumeBracket(); // '[' 710 Loc = Tok.getLocation(); 711 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 712 Op = OO_Array_Delete; 713 } else { 714 Op = OO_Delete; 715 } 716 if (EndLoc) 717 *EndLoc = Loc; 718 return Op; 719 720#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ 721 case tok::Token: Op = OO_##Name; break; 722#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) 723#include "clang/Basic/OperatorKinds.def" 724 725 case tok::l_paren: 726 ConsumeToken(); // 'operator' 727 ConsumeParen(); // '(' 728 Loc = Tok.getLocation(); 729 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')' 730 if (EndLoc) 731 *EndLoc = Loc; 732 return OO_Call; 733 734 case tok::l_square: 735 ConsumeToken(); // 'operator' 736 ConsumeBracket(); // '[' 737 Loc = Tok.getLocation(); 738 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 739 if (EndLoc) 740 *EndLoc = Loc; 741 return OO_Subscript; 742 743 default: 744 return OO_None; 745 } 746 747 ConsumeToken(); // 'operator' 748 Loc = ConsumeAnyToken(); // the operator itself 749 if (EndLoc) 750 *EndLoc = Loc; 751 return Op; 752} 753 754/// ParseConversionFunctionId - Parse a C++ conversion-function-id, 755/// which expresses the name of a user-defined conversion operator 756/// (C++ [class.conv.fct]p1). Returns the type that this operator is 757/// specifying a conversion for, or NULL if there was an error. 758/// 759/// conversion-function-id: [C++ 12.3.2] 760/// operator conversion-type-id 761/// 762/// conversion-type-id: 763/// type-specifier-seq conversion-declarator[opt] 764/// 765/// conversion-declarator: 766/// ptr-operator conversion-declarator[opt] 767Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) { 768 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); 769 ConsumeToken(); // 'operator' 770 771 // Parse the type-specifier-seq. 772 DeclSpec DS; 773 if (ParseCXXTypeSpecifierSeq(DS)) 774 return 0; 775 776 // Parse the conversion-declarator, which is merely a sequence of 777 // ptr-operators. 778 Declarator D(DS, Declarator::TypeNameContext); 779 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0); 780 if (EndLoc) 781 *EndLoc = D.getSourceRange().getEnd(); 782 783 // Finish up the type. 784 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D); 785 if (Result.isInvalid()) 786 return 0; 787 else 788 return Result.get(); 789} 790 791/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate 792/// memory in a typesafe manner and call constructors. 793/// 794/// This method is called to parse the new expression after the optional :: has 795/// been already parsed. If the :: was present, "UseGlobal" is true and "Start" 796/// is its location. Otherwise, "Start" is the location of the 'new' token. 797/// 798/// new-expression: 799/// '::'[opt] 'new' new-placement[opt] new-type-id 800/// new-initializer[opt] 801/// '::'[opt] 'new' new-placement[opt] '(' type-id ')' 802/// new-initializer[opt] 803/// 804/// new-placement: 805/// '(' expression-list ')' 806/// 807/// new-type-id: 808/// type-specifier-seq new-declarator[opt] 809/// 810/// new-declarator: 811/// ptr-operator new-declarator[opt] 812/// direct-new-declarator 813/// 814/// new-initializer: 815/// '(' expression-list[opt] ')' 816/// [C++0x] braced-init-list [TODO] 817/// 818Parser::OwningExprResult 819Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { 820 assert(Tok.is(tok::kw_new) && "expected 'new' token"); 821 ConsumeToken(); // Consume 'new' 822 823 // A '(' now can be a new-placement or the '(' wrapping the type-id in the 824 // second form of new-expression. It can't be a new-type-id. 825 826 ExprVector PlacementArgs(Actions); 827 SourceLocation PlacementLParen, PlacementRParen; 828 829 bool ParenTypeId; 830 DeclSpec DS; 831 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); 832 if (Tok.is(tok::l_paren)) { 833 // If it turns out to be a placement, we change the type location. 834 PlacementLParen = ConsumeParen(); 835 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) { 836 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 837 return ExprError(); 838 } 839 840 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen); 841 if (PlacementRParen.isInvalid()) { 842 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 843 return ExprError(); 844 } 845 846 if (PlacementArgs.empty()) { 847 // Reset the placement locations. There was no placement. 848 PlacementLParen = PlacementRParen = SourceLocation(); 849 ParenTypeId = true; 850 } else { 851 // We still need the type. 852 if (Tok.is(tok::l_paren)) { 853 SourceLocation LParen = ConsumeParen(); 854 ParseSpecifierQualifierList(DS); 855 DeclaratorInfo.SetSourceRange(DS.getSourceRange()); 856 ParseDeclarator(DeclaratorInfo); 857 MatchRHSPunctuation(tok::r_paren, LParen); 858 ParenTypeId = true; 859 } else { 860 if (ParseCXXTypeSpecifierSeq(DS)) 861 DeclaratorInfo.setInvalidType(true); 862 else { 863 DeclaratorInfo.SetSourceRange(DS.getSourceRange()); 864 ParseDeclaratorInternal(DeclaratorInfo, 865 &Parser::ParseDirectNewDeclarator); 866 } 867 ParenTypeId = false; 868 } 869 } 870 } else { 871 // A new-type-id is a simplified type-id, where essentially the 872 // direct-declarator is replaced by a direct-new-declarator. 873 if (ParseCXXTypeSpecifierSeq(DS)) 874 DeclaratorInfo.setInvalidType(true); 875 else { 876 DeclaratorInfo.SetSourceRange(DS.getSourceRange()); 877 ParseDeclaratorInternal(DeclaratorInfo, 878 &Parser::ParseDirectNewDeclarator); 879 } 880 ParenTypeId = false; 881 } 882 if (DeclaratorInfo.isInvalidType()) { 883 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 884 return ExprError(); 885 } 886 887 ExprVector ConstructorArgs(Actions); 888 SourceLocation ConstructorLParen, ConstructorRParen; 889 890 if (Tok.is(tok::l_paren)) { 891 ConstructorLParen = ConsumeParen(); 892 if (Tok.isNot(tok::r_paren)) { 893 CommaLocsTy CommaLocs; 894 if (ParseExpressionList(ConstructorArgs, CommaLocs)) { 895 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 896 return ExprError(); 897 } 898 } 899 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen); 900 if (ConstructorRParen.isInvalid()) { 901 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 902 return ExprError(); 903 } 904 } 905 906 return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, 907 move_arg(PlacementArgs), PlacementRParen, 908 ParenTypeId, DeclaratorInfo, ConstructorLParen, 909 move_arg(ConstructorArgs), ConstructorRParen); 910} 911 912/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be 913/// passed to ParseDeclaratorInternal. 914/// 915/// direct-new-declarator: 916/// '[' expression ']' 917/// direct-new-declarator '[' constant-expression ']' 918/// 919void Parser::ParseDirectNewDeclarator(Declarator &D) { 920 // Parse the array dimensions. 921 bool first = true; 922 while (Tok.is(tok::l_square)) { 923 SourceLocation LLoc = ConsumeBracket(); 924 OwningExprResult Size(first ? ParseExpression() 925 : ParseConstantExpression()); 926 if (Size.isInvalid()) { 927 // Recover 928 SkipUntil(tok::r_square); 929 return; 930 } 931 first = false; 932 933 SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc); 934 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, 935 Size.release(), LLoc), 936 RLoc); 937 938 if (RLoc.isInvalid()) 939 return; 940 } 941} 942 943/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id. 944/// This ambiguity appears in the syntax of the C++ new operator. 945/// 946/// new-expression: 947/// '::'[opt] 'new' new-placement[opt] '(' type-id ')' 948/// new-initializer[opt] 949/// 950/// new-placement: 951/// '(' expression-list ')' 952/// 953bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs, 954 Declarator &D) { 955 // The '(' was already consumed. 956 if (isTypeIdInParens()) { 957 ParseSpecifierQualifierList(D.getMutableDeclSpec()); 958 D.SetSourceRange(D.getDeclSpec().getSourceRange()); 959 ParseDeclarator(D); 960 return D.isInvalidType(); 961 } 962 963 // It's not a type, it has to be an expression list. 964 // Discard the comma locations - ActOnCXXNew has enough parameters. 965 CommaLocsTy CommaLocs; 966 return ParseExpressionList(PlacementArgs, CommaLocs); 967} 968 969/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used 970/// to free memory allocated by new. 971/// 972/// This method is called to parse the 'delete' expression after the optional 973/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true 974/// and "Start" is its location. Otherwise, "Start" is the location of the 975/// 'delete' token. 976/// 977/// delete-expression: 978/// '::'[opt] 'delete' cast-expression 979/// '::'[opt] 'delete' '[' ']' cast-expression 980Parser::OwningExprResult 981Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { 982 assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword"); 983 ConsumeToken(); // Consume 'delete' 984 985 // Array delete? 986 bool ArrayDelete = false; 987 if (Tok.is(tok::l_square)) { 988 ArrayDelete = true; 989 SourceLocation LHS = ConsumeBracket(); 990 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS); 991 if (RHS.isInvalid()) 992 return ExprError(); 993 } 994 995 OwningExprResult Operand(ParseCastExpression(false)); 996 if (Operand.isInvalid()) 997 return move(Operand); 998 999 return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, move(Operand)); 1000} 1001 1002static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) 1003{ 1004 switch(kind) { 1005 default: assert(false && "Not a known unary type trait."); 1006 case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign; 1007 case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy; 1008 case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor; 1009 case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign; 1010 case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy; 1011 case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor; 1012 case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor; 1013 case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor; 1014 case tok::kw___is_abstract: return UTT_IsAbstract; 1015 case tok::kw___is_class: return UTT_IsClass; 1016 case tok::kw___is_empty: return UTT_IsEmpty; 1017 case tok::kw___is_enum: return UTT_IsEnum; 1018 case tok::kw___is_pod: return UTT_IsPOD; 1019 case tok::kw___is_polymorphic: return UTT_IsPolymorphic; 1020 case tok::kw___is_union: return UTT_IsUnion; 1021 } 1022} 1023 1024/// ParseUnaryTypeTrait - Parse the built-in unary type-trait 1025/// pseudo-functions that allow implementation of the TR1/C++0x type traits 1026/// templates. 1027/// 1028/// primary-expression: 1029/// [GNU] unary-type-trait '(' type-id ')' 1030/// 1031Parser::OwningExprResult Parser::ParseUnaryTypeTrait() 1032{ 1033 UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind()); 1034 SourceLocation Loc = ConsumeToken(); 1035 1036 SourceLocation LParen = Tok.getLocation(); 1037 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) 1038 return ExprError(); 1039 1040 // FIXME: Error reporting absolutely sucks! If the this fails to parse a type 1041 // there will be cryptic errors about mismatched parentheses and missing 1042 // specifiers. 1043 TypeResult Ty = ParseTypeName(); 1044 1045 SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); 1046 1047 if (Ty.isInvalid()) 1048 return ExprError(); 1049 1050 return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen); 1051} 1052 1053/// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a 1054/// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate 1055/// based on the context past the parens. 1056Parser::OwningExprResult 1057Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, 1058 TypeTy *&CastTy, 1059 SourceLocation LParenLoc, 1060 SourceLocation &RParenLoc) { 1061 assert(getLang().CPlusPlus && "Should only be called for C++!"); 1062 assert(ExprType == CastExpr && "Compound literals are not ambiguous!"); 1063 assert(isTypeIdInParens() && "Not a type-id!"); 1064 1065 OwningExprResult Result(Actions, true); 1066 CastTy = 0; 1067 1068 // We need to disambiguate a very ugly part of the C++ syntax: 1069 // 1070 // (T())x; - type-id 1071 // (T())*x; - type-id 1072 // (T())/x; - expression 1073 // (T()); - expression 1074 // 1075 // The bad news is that we cannot use the specialized tentative parser, since 1076 // it can only verify that the thing inside the parens can be parsed as 1077 // type-id, it is not useful for determining the context past the parens. 1078 // 1079 // The good news is that the parser can disambiguate this part without 1080 // making any unnecessary Action calls. 1081 // 1082 // It uses a scheme similar to parsing inline methods. The parenthesized 1083 // tokens are cached, the context that follows is determined (possibly by 1084 // parsing a cast-expression), and then we re-introduce the cached tokens 1085 // into the token stream and parse them appropriately. 1086 1087 ParenParseOption ParseAs; 1088 CachedTokens Toks; 1089 1090 // Store the tokens of the parentheses. We will parse them after we determine 1091 // the context that follows them. 1092 if (!ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks, tok::semi)) { 1093 // We didn't find the ')' we expected. 1094 MatchRHSPunctuation(tok::r_paren, LParenLoc); 1095 return ExprError(); 1096 } 1097 1098 if (Tok.is(tok::l_brace)) { 1099 ParseAs = CompoundLiteral; 1100 } else { 1101 bool NotCastExpr; 1102 // FIXME: Special-case ++ and --: "(S())++;" is not a cast-expression 1103 if (Tok.is(tok::l_paren) && NextToken().is(tok::r_paren)) { 1104 NotCastExpr = true; 1105 } else { 1106 // Try parsing the cast-expression that may follow. 1107 // If it is not a cast-expression, NotCastExpr will be true and no token 1108 // will be consumed. 1109 Result = ParseCastExpression(false/*isUnaryExpression*/, 1110 false/*isAddressofOperand*/, 1111 NotCastExpr); 1112 } 1113 1114 // If we parsed a cast-expression, it's really a type-id, otherwise it's 1115 // an expression. 1116 ParseAs = NotCastExpr ? SimpleExpr : CastExpr; 1117 } 1118 1119 // The current token should go after the cached tokens. 1120 Toks.push_back(Tok); 1121 // Re-enter the stored parenthesized tokens into the token stream, so we may 1122 // parse them now. 1123 PP.EnterTokenStream(Toks.data(), Toks.size(), 1124 true/*DisableMacroExpansion*/, false/*OwnsTokens*/); 1125 // Drop the current token and bring the first cached one. It's the same token 1126 // as when we entered this function. 1127 ConsumeAnyToken(); 1128 1129 if (ParseAs >= CompoundLiteral) { 1130 TypeResult Ty = ParseTypeName(); 1131 1132 // Match the ')'. 1133 if (Tok.is(tok::r_paren)) 1134 RParenLoc = ConsumeParen(); 1135 else 1136 MatchRHSPunctuation(tok::r_paren, LParenLoc); 1137 1138 if (ParseAs == CompoundLiteral) { 1139 ExprType = CompoundLiteral; 1140 return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc); 1141 } 1142 1143 // We parsed '(' type-id ')' and the thing after it wasn't a '{'. 1144 assert(ParseAs == CastExpr); 1145 1146 if (Ty.isInvalid()) 1147 return ExprError(); 1148 1149 CastTy = Ty.get(); 1150 1151 // Result is what ParseCastExpression returned earlier. 1152 if (!Result.isInvalid()) 1153 Result = Actions.ActOnCastExpr(LParenLoc, CastTy, RParenLoc,move(Result)); 1154 return move(Result); 1155 } 1156 1157 // Not a compound literal, and not followed by a cast-expression. 1158 assert(ParseAs == SimpleExpr); 1159 1160 ExprType = SimpleExpr; 1161 Result = ParseExpression(); 1162 if (!Result.isInvalid() && Tok.is(tok::r_paren)) 1163 Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), move(Result)); 1164 1165 // Match the ')'. 1166 if (Result.isInvalid()) { 1167 SkipUntil(tok::r_paren); 1168 return ExprError(); 1169 } 1170 1171 if (Tok.is(tok::r_paren)) 1172 RParenLoc = ConsumeParen(); 1173 else 1174 MatchRHSPunctuation(tok::r_paren, LParenLoc); 1175 1176 return move(Result); 1177} 1178