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