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