ParseExprCXX.cpp revision a7bc7c880f86bc180684ef032d06df51bcae7a23
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/Basic/Diagnostic.h" 15#include "clang/Parse/Parser.h" 16#include "clang/Parse/DeclSpec.h" 17#include "AstGuard.h" 18using namespace clang; 19 20/// MaybeParseCXXScopeSpecifier - Parse global scope or nested-name-specifier. 21/// Returns true if a nested-name-specifier was parsed from the token stream. 22/// 23/// '::'[opt] nested-name-specifier 24/// '::' 25/// 26/// nested-name-specifier: 27/// type-name '::' 28/// namespace-name '::' 29/// nested-name-specifier identifier '::' 30/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO] 31/// 32bool Parser::MaybeParseCXXScopeSpecifier(CXXScopeSpec &SS, 33 const Token *GlobalQualifier) { 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 assert(GlobalQualifier == 0 && 39 "Cannot have :: followed by a resolve annotation scope"); 40 SS.setScopeRep(Tok.getAnnotationValue()); 41 SS.setRange(Tok.getAnnotationRange()); 42 ConsumeToken(); 43 return true; 44 } 45 46 if (GlobalQualifier == 0 && 47 Tok.isNot(tok::coloncolon) && 48 (Tok.isNot(tok::identifier) || NextToken().isNot(tok::coloncolon))) 49 return false; 50 51 // ::new and ::delete aren't nested-name-specifiers, so parsing the :: as 52 // a scope specifier only makes things more complicated. 53 if (GlobalQualifier == 0 && Tok.is(tok::coloncolon)) { 54 Token Next = NextToken(); 55 if (Next.is(tok::kw_new) || Next.is(tok::kw_delete)) 56 return false; 57 } 58 59 if (GlobalQualifier) { 60 // Pre-parsed '::'. 61 SS.setBeginLoc(GlobalQualifier->getLocation()); 62 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, 63 GlobalQualifier->getLocation())); 64 SS.setEndLoc(GlobalQualifier->getLocation()); 65 } else { 66 SS.setBeginLoc(Tok.getLocation()); 67 68 // '::' 69 if (Tok.is(tok::coloncolon)) { 70 // Global scope. 71 SourceLocation CCLoc = ConsumeToken(); 72 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc)); 73 SS.setEndLoc(CCLoc); 74 } 75 } 76 77 // nested-name-specifier: 78 // type-name '::' 79 // namespace-name '::' 80 // nested-name-specifier identifier '::' 81 // nested-name-specifier 'template'[opt] simple-template-id '::' [TODO] 82 while (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) { 83 IdentifierInfo *II = Tok.getIdentifierInfo(); 84 SourceLocation IdLoc = ConsumeToken(); 85 assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); 86 SourceLocation CCLoc = ConsumeToken(); 87 if (SS.isInvalid()) 88 continue; 89 90 SS.setScopeRep( 91 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II)); 92 SS.setEndLoc(CCLoc); 93 } 94 95 return true; 96} 97 98/// ParseCXXIdExpression - Handle id-expression. 99/// 100/// id-expression: 101/// unqualified-id 102/// qualified-id 103/// 104/// unqualified-id: 105/// identifier 106/// operator-function-id 107/// conversion-function-id [TODO] 108/// '~' class-name [TODO] 109/// template-id [TODO] 110/// 111/// qualified-id: 112/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id 113/// '::' identifier 114/// '::' operator-function-id 115/// '::' template-id [TODO] 116/// 117/// nested-name-specifier: 118/// type-name '::' 119/// namespace-name '::' 120/// nested-name-specifier identifier '::' 121/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO] 122/// 123/// NOTE: The standard specifies that, for qualified-id, the parser does not 124/// expect: 125/// 126/// '::' conversion-function-id 127/// '::' '~' class-name 128/// 129/// This may cause a slight inconsistency on diagnostics: 130/// 131/// class C {}; 132/// namespace A {} 133/// void f() { 134/// :: A :: ~ C(); // Some Sema error about using destructor with a 135/// // namespace. 136/// :: ~ C(); // Some Parser error like 'unexpected ~'. 137/// } 138/// 139/// We simplify the parser a bit and make it work like: 140/// 141/// qualified-id: 142/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id 143/// '::' unqualified-id 144/// 145/// That way Sema can handle and report similar errors for namespaces and the 146/// global scope. 147/// 148Parser::OwningExprResult Parser::ParseCXXIdExpression() { 149 // qualified-id: 150 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id 151 // '::' unqualified-id 152 // 153 CXXScopeSpec SS; 154 MaybeParseCXXScopeSpecifier(SS); 155 156 // unqualified-id: 157 // identifier 158 // operator-function-id 159 // conversion-function-id 160 // '~' class-name [TODO] 161 // template-id [TODO] 162 // 163 switch (Tok.getKind()) { 164 default: 165 return ExprError(Diag(Tok, diag::err_expected_unqualified_id)); 166 167 case tok::identifier: { 168 // Consume the identifier so that we can see if it is followed by a '('. 169 IdentifierInfo &II = *Tok.getIdentifierInfo(); 170 SourceLocation L = ConsumeToken(); 171 return Owned(Actions.ActOnIdentifierExpr(CurScope, L, II, 172 Tok.is(tok::l_paren), &SS)); 173 } 174 175 case tok::kw_operator: { 176 SourceLocation OperatorLoc = Tok.getLocation(); 177 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) { 178 return Owned(Actions.ActOnCXXOperatorFunctionIdExpr( 179 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS)); 180 } else if (TypeTy *Type = ParseConversionFunctionId()) { 181 return Owned(Actions.ActOnCXXConversionFunctionExpr( 182 CurScope, OperatorLoc, Type, Tok.is(tok::l_paren),SS)); 183 } 184 185 // We already complained about a bad conversion-function-id, 186 // above. 187 return ExprError(); 188 } 189 190 } // switch. 191 192 assert(0 && "The switch was supposed to take care everything."); 193} 194 195/// ParseCXXCasts - This handles the various ways to cast expressions to another 196/// type. 197/// 198/// postfix-expression: [C++ 5.2p1] 199/// 'dynamic_cast' '<' type-name '>' '(' expression ')' 200/// 'static_cast' '<' type-name '>' '(' expression ')' 201/// 'reinterpret_cast' '<' type-name '>' '(' expression ')' 202/// 'const_cast' '<' type-name '>' '(' expression ')' 203/// 204Parser::OwningExprResult Parser::ParseCXXCasts() { 205 tok::TokenKind Kind = Tok.getKind(); 206 const char *CastName = 0; // For error messages 207 208 switch (Kind) { 209 default: assert(0 && "Unknown C++ cast!"); abort(); 210 case tok::kw_const_cast: CastName = "const_cast"; break; 211 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break; 212 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break; 213 case tok::kw_static_cast: CastName = "static_cast"; break; 214 } 215 216 SourceLocation OpLoc = ConsumeToken(); 217 SourceLocation LAngleBracketLoc = Tok.getLocation(); 218 219 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName)) 220 return ExprError(); 221 222 TypeTy *CastTy = ParseTypeName(); 223 SourceLocation RAngleBracketLoc = Tok.getLocation(); 224 225 if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) 226 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<"); 227 228 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc; 229 230 if (Tok.isNot(tok::l_paren)) 231 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << CastName); 232 233 OwningExprResult Result(ParseSimpleParenExpression(RParenLoc)); 234 235 if (!Result.isInvalid()) 236 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind, 237 LAngleBracketLoc, CastTy, RAngleBracketLoc, 238 LParenLoc, Result.release(), RParenLoc); 239 240 return move(Result); 241} 242 243/// ParseCXXTypeid - This handles the C++ typeid expression. 244/// 245/// postfix-expression: [C++ 5.2p1] 246/// 'typeid' '(' expression ')' 247/// 'typeid' '(' type-id ')' 248/// 249Parser::OwningExprResult Parser::ParseCXXTypeid() { 250 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!"); 251 252 SourceLocation OpLoc = ConsumeToken(); 253 SourceLocation LParenLoc = Tok.getLocation(); 254 SourceLocation RParenLoc; 255 256 // typeid expressions are always parenthesized. 257 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, 258 "typeid")) 259 return ExprError(); 260 261 OwningExprResult Result(Actions); 262 263 if (isTypeIdInParens()) { 264 TypeTy *Ty = ParseTypeName(); 265 266 // Match the ')'. 267 MatchRHSPunctuation(tok::r_paren, LParenLoc); 268 269 if (!Ty) 270 return ExprError(); 271 272 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true, 273 Ty, RParenLoc); 274 } else { 275 Result = ParseExpression(); 276 277 // Match the ')'. 278 if (Result.isInvalid()) 279 SkipUntil(tok::r_paren); 280 else { 281 MatchRHSPunctuation(tok::r_paren, LParenLoc); 282 283 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false, 284 Result.release(), RParenLoc); 285 } 286 } 287 288 return move(Result); 289} 290 291/// ParseCXXBoolLiteral - This handles the C++ Boolean literals. 292/// 293/// boolean-literal: [C++ 2.13.5] 294/// 'true' 295/// 'false' 296Parser::OwningExprResult Parser::ParseCXXBoolLiteral() { 297 tok::TokenKind Kind = Tok.getKind(); 298 return Owned(Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind)); 299} 300 301/// ParseThrowExpression - This handles the C++ throw expression. 302/// 303/// throw-expression: [C++ 15] 304/// 'throw' assignment-expression[opt] 305Parser::OwningExprResult Parser::ParseThrowExpression() { 306 assert(Tok.is(tok::kw_throw) && "Not throw!"); 307 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token. 308 309 // If the current token isn't the start of an assignment-expression, 310 // then the expression is not present. This handles things like: 311 // "C ? throw : (void)42", which is crazy but legal. 312 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common. 313 case tok::semi: 314 case tok::r_paren: 315 case tok::r_square: 316 case tok::r_brace: 317 case tok::colon: 318 case tok::comma: 319 return Owned(Actions.ActOnCXXThrow(ThrowLoc)); 320 321 default: 322 OwningExprResult Expr(ParseAssignmentExpression()); 323 if (Expr.isInvalid()) return move(Expr); 324 return Owned(Actions.ActOnCXXThrow(ThrowLoc, Expr.release())); 325 } 326} 327 328/// ParseCXXThis - This handles the C++ 'this' pointer. 329/// 330/// C++ 9.3.2: In the body of a non-static member function, the keyword this is 331/// a non-lvalue expression whose value is the address of the object for which 332/// the function is called. 333Parser::OwningExprResult Parser::ParseCXXThis() { 334 assert(Tok.is(tok::kw_this) && "Not 'this'!"); 335 SourceLocation ThisLoc = ConsumeToken(); 336 return Owned(Actions.ActOnCXXThis(ThisLoc)); 337} 338 339/// ParseCXXTypeConstructExpression - Parse construction of a specified type. 340/// Can be interpreted either as function-style casting ("int(x)") 341/// or class type construction ("ClassType(x,y,z)") 342/// or creation of a value-initialized type ("int()"). 343/// 344/// postfix-expression: [C++ 5.2p1] 345/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] 346/// typename-specifier '(' expression-list[opt] ')' [TODO] 347/// 348Parser::OwningExprResult 349Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { 350 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); 351 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val; 352 353 assert(Tok.is(tok::l_paren) && "Expected '('!"); 354 SourceLocation LParenLoc = ConsumeParen(); 355 356 ExprVector Exprs(Actions); 357 CommaLocsTy CommaLocs; 358 359 if (Tok.isNot(tok::r_paren)) { 360 if (ParseExpressionList(Exprs, CommaLocs)) { 361 SkipUntil(tok::r_paren); 362 return ExprError(); 363 } 364 } 365 366 // Match the ')'. 367 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); 368 369 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& 370 "Unexpected number of commas!"); 371 return Owned(Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep, 372 LParenLoc, 373 Exprs.take(), Exprs.size(), 374 &CommaLocs[0], RParenLoc)); 375} 376 377/// ParseCXXCondition - if/switch/while/for condition expression. 378/// 379/// condition: 380/// expression 381/// type-specifier-seq declarator '=' assignment-expression 382/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] 383/// '=' assignment-expression 384/// 385Parser::OwningExprResult Parser::ParseCXXCondition() { 386 if (!isCXXConditionDeclaration()) 387 return ParseExpression(); // expression 388 389 SourceLocation StartLoc = Tok.getLocation(); 390 391 // type-specifier-seq 392 DeclSpec DS; 393 ParseSpecifierQualifierList(DS); 394 395 // declarator 396 Declarator DeclaratorInfo(DS, Declarator::ConditionContext); 397 ParseDeclarator(DeclaratorInfo); 398 399 // simple-asm-expr[opt] 400 if (Tok.is(tok::kw_asm)) { 401 OwningExprResult AsmLabel(ParseSimpleAsm()); 402 if (AsmLabel.isInvalid()) { 403 SkipUntil(tok::semi); 404 return ExprError(); 405 } 406 DeclaratorInfo.setAsmLabel(AsmLabel.release()); 407 } 408 409 // If attributes are present, parse them. 410 if (Tok.is(tok::kw___attribute)) 411 DeclaratorInfo.AddAttributes(ParseAttributes()); 412 413 // '=' assignment-expression 414 if (Tok.isNot(tok::equal)) 415 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator)); 416 SourceLocation EqualLoc = ConsumeToken(); 417 OwningExprResult AssignExpr(ParseAssignmentExpression()); 418 if (AssignExpr.isInvalid()) 419 return ExprError(); 420 421 return Owned(Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc, 422 DeclaratorInfo,EqualLoc, 423 AssignExpr.release())); 424} 425 426/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. 427/// This should only be called when the current token is known to be part of 428/// simple-type-specifier. 429/// 430/// simple-type-specifier: 431/// '::'[opt] nested-name-specifier[opt] type-name 432/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO] 433/// char 434/// wchar_t 435/// bool 436/// short 437/// int 438/// long 439/// signed 440/// unsigned 441/// float 442/// double 443/// void 444/// [GNU] typeof-specifier 445/// [C++0x] auto [TODO] 446/// 447/// type-name: 448/// class-name 449/// enum-name 450/// typedef-name 451/// 452void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { 453 // Annotate typenames and C++ scope specifiers. 454 TryAnnotateTypeOrScopeToken(); 455 456 DS.SetRangeStart(Tok.getLocation()); 457 const char *PrevSpec; 458 SourceLocation Loc = Tok.getLocation(); 459 460 switch (Tok.getKind()) { 461 default: 462 assert(0 && "Not a simple-type-specifier token!"); 463 abort(); 464 465 // type-name 466 case tok::annot_qualtypename: { 467 DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec, 468 Tok.getAnnotationValue()); 469 break; 470 } 471 472 // builtin types 473 case tok::kw_short: 474 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec); 475 break; 476 case tok::kw_long: 477 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec); 478 break; 479 case tok::kw_signed: 480 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec); 481 break; 482 case tok::kw_unsigned: 483 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec); 484 break; 485 case tok::kw_void: 486 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec); 487 break; 488 case tok::kw_char: 489 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec); 490 break; 491 case tok::kw_int: 492 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec); 493 break; 494 case tok::kw_float: 495 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec); 496 break; 497 case tok::kw_double: 498 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec); 499 break; 500 case tok::kw_wchar_t: 501 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec); 502 break; 503 case tok::kw_bool: 504 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec); 505 break; 506 507 // GNU typeof support. 508 case tok::kw_typeof: 509 ParseTypeofSpecifier(DS); 510 DS.Finish(Diags, PP.getSourceManager(), getLang()); 511 return; 512 } 513 if (Tok.is(tok::annot_qualtypename)) 514 DS.SetRangeEnd(Tok.getAnnotationEndLoc()); 515 else 516 DS.SetRangeEnd(Tok.getLocation()); 517 ConsumeToken(); 518 DS.Finish(Diags, PP.getSourceManager(), getLang()); 519} 520 521/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++ 522/// [dcl.name]), which is a non-empty sequence of type-specifiers, 523/// e.g., "const short int". Note that the DeclSpec is *not* finished 524/// by parsing the type-specifier-seq, because these sequences are 525/// typically followed by some form of declarator. Returns true and 526/// emits diagnostics if this is not a type-specifier-seq, false 527/// otherwise. 528/// 529/// type-specifier-seq: [C++ 8.1] 530/// type-specifier type-specifier-seq[opt] 531/// 532bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { 533 DS.SetRangeStart(Tok.getLocation()); 534 const char *PrevSpec = 0; 535 int isInvalid = 0; 536 537 // Parse one or more of the type specifiers. 538 if (!MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) { 539 Diag(Tok, diag::err_operator_missing_type_specifier); 540 return true; 541 } 542 while (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) ; 543 544 return false; 545} 546 547/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded 548/// operator name (C++ [over.oper]). If successful, returns the 549/// predefined identifier that corresponds to that overloaded 550/// operator. Otherwise, returns NULL and does not consume any tokens. 551/// 552/// operator-function-id: [C++ 13.5] 553/// 'operator' operator 554/// 555/// operator: one of 556/// new delete new[] delete[] 557/// + - * / % ^ & | ~ 558/// ! = < > += -= *= /= %= 559/// ^= &= |= << >> >>= <<= == != 560/// <= >= && || ++ -- , ->* -> 561/// () [] 562OverloadedOperatorKind Parser::TryParseOperatorFunctionId() { 563 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); 564 565 OverloadedOperatorKind Op = OO_None; 566 switch (NextToken().getKind()) { 567 case tok::kw_new: 568 ConsumeToken(); // 'operator' 569 ConsumeToken(); // 'new' 570 if (Tok.is(tok::l_square)) { 571 ConsumeBracket(); // '[' 572 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 573 Op = OO_Array_New; 574 } else { 575 Op = OO_New; 576 } 577 return Op; 578 579 case tok::kw_delete: 580 ConsumeToken(); // 'operator' 581 ConsumeToken(); // 'delete' 582 if (Tok.is(tok::l_square)) { 583 ConsumeBracket(); // '[' 584 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 585 Op = OO_Array_Delete; 586 } else { 587 Op = OO_Delete; 588 } 589 return Op; 590 591#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ 592 case tok::Token: Op = OO_##Name; break; 593#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) 594#include "clang/Basic/OperatorKinds.def" 595 596 case tok::l_paren: 597 ConsumeToken(); // 'operator' 598 ConsumeParen(); // '(' 599 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')' 600 return OO_Call; 601 602 case tok::l_square: 603 ConsumeToken(); // 'operator' 604 ConsumeBracket(); // '[' 605 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 606 return OO_Subscript; 607 608 default: 609 return OO_None; 610 } 611 612 ConsumeToken(); // 'operator' 613 ConsumeAnyToken(); // the operator itself 614 return Op; 615} 616 617/// ParseConversionFunctionId - Parse a C++ conversion-function-id, 618/// which expresses the name of a user-defined conversion operator 619/// (C++ [class.conv.fct]p1). Returns the type that this operator is 620/// specifying a conversion for, or NULL if there was an error. 621/// 622/// conversion-function-id: [C++ 12.3.2] 623/// operator conversion-type-id 624/// 625/// conversion-type-id: 626/// type-specifier-seq conversion-declarator[opt] 627/// 628/// conversion-declarator: 629/// ptr-operator conversion-declarator[opt] 630Parser::TypeTy *Parser::ParseConversionFunctionId() { 631 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); 632 ConsumeToken(); // 'operator' 633 634 // Parse the type-specifier-seq. 635 DeclSpec DS; 636 if (ParseCXXTypeSpecifierSeq(DS)) 637 return 0; 638 639 // Parse the conversion-declarator, which is merely a sequence of 640 // ptr-operators. 641 Declarator D(DS, Declarator::TypeNameContext); 642 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0); 643 644 // Finish up the type. 645 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D); 646 if (Result.isInvalid) 647 return 0; 648 else 649 return Result.Val; 650} 651 652/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate 653/// memory in a typesafe manner and call constructors. 654/// 655/// This method is called to parse the new expression after the optional :: has 656/// been already parsed. If the :: was present, "UseGlobal" is true and "Start" 657/// is its location. Otherwise, "Start" is the location of the 'new' token. 658/// 659/// new-expression: 660/// '::'[opt] 'new' new-placement[opt] new-type-id 661/// new-initializer[opt] 662/// '::'[opt] 'new' new-placement[opt] '(' type-id ')' 663/// new-initializer[opt] 664/// 665/// new-placement: 666/// '(' expression-list ')' 667/// 668/// new-type-id: 669/// type-specifier-seq new-declarator[opt] 670/// 671/// new-declarator: 672/// ptr-operator new-declarator[opt] 673/// direct-new-declarator 674/// 675/// new-initializer: 676/// '(' expression-list[opt] ')' 677/// [C++0x] braced-init-list [TODO] 678/// 679Parser::OwningExprResult 680Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { 681 assert(Tok.is(tok::kw_new) && "expected 'new' token"); 682 ConsumeToken(); // Consume 'new' 683 684 // A '(' now can be a new-placement or the '(' wrapping the type-id in the 685 // second form of new-expression. It can't be a new-type-id. 686 687 ExprVector PlacementArgs(Actions); 688 SourceLocation PlacementLParen, PlacementRParen; 689 690 bool ParenTypeId; 691 DeclSpec DS; 692 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); 693 if (Tok.is(tok::l_paren)) { 694 // If it turns out to be a placement, we change the type location. 695 PlacementLParen = ConsumeParen(); 696 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) { 697 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 698 return ExprError(); 699 } 700 701 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen); 702 if (PlacementRParen.isInvalid()) { 703 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 704 return ExprError(); 705 } 706 707 if (PlacementArgs.empty()) { 708 // Reset the placement locations. There was no placement. 709 PlacementLParen = PlacementRParen = SourceLocation(); 710 ParenTypeId = true; 711 } else { 712 // We still need the type. 713 if (Tok.is(tok::l_paren)) { 714 SourceLocation LParen = ConsumeParen(); 715 ParseSpecifierQualifierList(DS); 716 ParseDeclarator(DeclaratorInfo); 717 MatchRHSPunctuation(tok::r_paren, LParen); 718 ParenTypeId = true; 719 } else { 720 if (ParseCXXTypeSpecifierSeq(DS)) 721 DeclaratorInfo.setInvalidType(true); 722 else 723 ParseDeclaratorInternal(DeclaratorInfo, 724 &Parser::ParseDirectNewDeclarator); 725 ParenTypeId = false; 726 } 727 } 728 } else { 729 // A new-type-id is a simplified type-id, where essentially the 730 // direct-declarator is replaced by a direct-new-declarator. 731 if (ParseCXXTypeSpecifierSeq(DS)) 732 DeclaratorInfo.setInvalidType(true); 733 else 734 ParseDeclaratorInternal(DeclaratorInfo, 735 &Parser::ParseDirectNewDeclarator); 736 ParenTypeId = false; 737 } 738 if (DeclaratorInfo.getInvalidType()) { 739 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 740 return ExprError(); 741 } 742 743 ExprVector ConstructorArgs(Actions); 744 SourceLocation ConstructorLParen, ConstructorRParen; 745 746 if (Tok.is(tok::l_paren)) { 747 ConstructorLParen = ConsumeParen(); 748 if (Tok.isNot(tok::r_paren)) { 749 CommaLocsTy CommaLocs; 750 if (ParseExpressionList(ConstructorArgs, CommaLocs)) { 751 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 752 return ExprError(); 753 } 754 } 755 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen); 756 if (ConstructorRParen.isInvalid()) { 757 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 758 return ExprError(); 759 } 760 } 761 762 return Owned(Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, 763 PlacementArgs.take(), PlacementArgs.size(), 764 PlacementRParen, ParenTypeId, DeclaratorInfo, 765 ConstructorLParen, ConstructorArgs.take(), 766 ConstructorArgs.size(), ConstructorRParen)); 767} 768 769/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be 770/// passed to ParseDeclaratorInternal. 771/// 772/// direct-new-declarator: 773/// '[' expression ']' 774/// direct-new-declarator '[' constant-expression ']' 775/// 776void Parser::ParseDirectNewDeclarator(Declarator &D) { 777 // Parse the array dimensions. 778 bool first = true; 779 while (Tok.is(tok::l_square)) { 780 SourceLocation LLoc = ConsumeBracket(); 781 OwningExprResult Size(first ? ParseExpression() 782 : ParseConstantExpression()); 783 if (Size.isInvalid()) { 784 // Recover 785 SkipUntil(tok::r_square); 786 return; 787 } 788 first = false; 789 790 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, 791 Size.release(), LLoc)); 792 793 if (MatchRHSPunctuation(tok::r_square, LLoc).isInvalid()) 794 return; 795 } 796} 797 798/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id. 799/// This ambiguity appears in the syntax of the C++ new operator. 800/// 801/// new-expression: 802/// '::'[opt] 'new' new-placement[opt] '(' type-id ')' 803/// new-initializer[opt] 804/// 805/// new-placement: 806/// '(' expression-list ')' 807/// 808bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs, 809 Declarator &D) { 810 // The '(' was already consumed. 811 if (isTypeIdInParens()) { 812 ParseSpecifierQualifierList(D.getMutableDeclSpec()); 813 ParseDeclarator(D); 814 return D.getInvalidType(); 815 } 816 817 // It's not a type, it has to be an expression list. 818 // Discard the comma locations - ActOnCXXNew has enough parameters. 819 CommaLocsTy CommaLocs; 820 return ParseExpressionList(PlacementArgs, CommaLocs); 821} 822 823/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used 824/// to free memory allocated by new. 825/// 826/// This method is called to parse the 'delete' expression after the optional 827/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true 828/// and "Start" is its location. Otherwise, "Start" is the location of the 829/// 'delete' token. 830/// 831/// delete-expression: 832/// '::'[opt] 'delete' cast-expression 833/// '::'[opt] 'delete' '[' ']' cast-expression 834Parser::OwningExprResult 835Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { 836 assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword"); 837 ConsumeToken(); // Consume 'delete' 838 839 // Array delete? 840 bool ArrayDelete = false; 841 if (Tok.is(tok::l_square)) { 842 ArrayDelete = true; 843 SourceLocation LHS = ConsumeBracket(); 844 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS); 845 if (RHS.isInvalid()) 846 return ExprError(); 847 } 848 849 OwningExprResult Operand(ParseCastExpression(false)); 850 if (Operand.isInvalid()) 851 return move(Operand); 852 853 return Owned(Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, 854 Operand.release())); 855} 856