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