ParseExprCXX.cpp revision 500d3297d2a21edeac4d46cbcbe21bc2352c2a28
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" 17#include "AstGuard.h" 18using namespace clang; 19 20/// ParseOptionalCXXScopeSpecifier - Parse global scope or 21/// nested-name-specifier if present. Returns true if a nested-name-specifier 22/// was parsed from the token stream. Note that this routine will not parse 23/// ::new or ::delete, it will just leave them in the token stream. 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::ParseOptionalCXXScopeSpecifier(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 ParseOptionalCXXScopeSpecifier(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 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 Actions.ActOnCXXOperatorFunctionIdExpr( 165 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS); 166 if (TypeTy *Type = ParseConversionFunctionId()) 167 return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type, 168 Tok.is(tok::l_paren), SS); 169 170 // We already complained about a bad conversion-function-id, 171 // above. 172 return ExprError(); 173 } 174 175 } // switch. 176 177 assert(0 && "The switch was supposed to take care everything."); 178} 179 180/// ParseCXXCasts - This handles the various ways to cast expressions to another 181/// type. 182/// 183/// postfix-expression: [C++ 5.2p1] 184/// 'dynamic_cast' '<' type-name '>' '(' expression ')' 185/// 'static_cast' '<' type-name '>' '(' expression ')' 186/// 'reinterpret_cast' '<' type-name '>' '(' expression ')' 187/// 'const_cast' '<' type-name '>' '(' expression ')' 188/// 189Parser::OwningExprResult Parser::ParseCXXCasts() { 190 tok::TokenKind Kind = Tok.getKind(); 191 const char *CastName = 0; // For error messages 192 193 switch (Kind) { 194 default: assert(0 && "Unknown C++ cast!"); abort(); 195 case tok::kw_const_cast: CastName = "const_cast"; break; 196 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break; 197 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break; 198 case tok::kw_static_cast: CastName = "static_cast"; break; 199 } 200 201 SourceLocation OpLoc = ConsumeToken(); 202 SourceLocation LAngleBracketLoc = Tok.getLocation(); 203 204 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName)) 205 return ExprError(); 206 207 TypeTy *CastTy = ParseTypeName(); 208 SourceLocation RAngleBracketLoc = Tok.getLocation(); 209 210 if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) 211 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<"); 212 213 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc; 214 215 if (Tok.isNot(tok::l_paren)) 216 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << CastName); 217 218 OwningExprResult Result(ParseSimpleParenExpression(RParenLoc)); 219 220 if (!Result.isInvalid()) 221 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind, 222 LAngleBracketLoc, CastTy, RAngleBracketLoc, 223 LParenLoc, Result.release(), RParenLoc); 224 225 return move(Result); 226} 227 228/// ParseCXXTypeid - This handles the C++ typeid expression. 229/// 230/// postfix-expression: [C++ 5.2p1] 231/// 'typeid' '(' expression ')' 232/// 'typeid' '(' type-id ')' 233/// 234Parser::OwningExprResult Parser::ParseCXXTypeid() { 235 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!"); 236 237 SourceLocation OpLoc = ConsumeToken(); 238 SourceLocation LParenLoc = Tok.getLocation(); 239 SourceLocation RParenLoc; 240 241 // typeid expressions are always parenthesized. 242 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, 243 "typeid")) 244 return ExprError(); 245 246 OwningExprResult Result(Actions); 247 248 if (isTypeIdInParens()) { 249 TypeTy *Ty = ParseTypeName(); 250 251 // Match the ')'. 252 MatchRHSPunctuation(tok::r_paren, LParenLoc); 253 254 if (!Ty) 255 return ExprError(); 256 257 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true, 258 Ty, RParenLoc); 259 } else { 260 Result = ParseExpression(); 261 262 // Match the ')'. 263 if (Result.isInvalid()) 264 SkipUntil(tok::r_paren); 265 else { 266 MatchRHSPunctuation(tok::r_paren, LParenLoc); 267 268 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false, 269 Result.release(), RParenLoc); 270 } 271 } 272 273 return move(Result); 274} 275 276/// ParseCXXBoolLiteral - This handles the C++ Boolean literals. 277/// 278/// boolean-literal: [C++ 2.13.5] 279/// 'true' 280/// 'false' 281Parser::OwningExprResult Parser::ParseCXXBoolLiteral() { 282 tok::TokenKind Kind = Tok.getKind(); 283 return Owned(Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind)); 284} 285 286/// ParseThrowExpression - This handles the C++ throw expression. 287/// 288/// throw-expression: [C++ 15] 289/// 'throw' assignment-expression[opt] 290Parser::OwningExprResult Parser::ParseThrowExpression() { 291 assert(Tok.is(tok::kw_throw) && "Not throw!"); 292 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token. 293 294 // If the current token isn't the start of an assignment-expression, 295 // then the expression is not present. This handles things like: 296 // "C ? throw : (void)42", which is crazy but legal. 297 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common. 298 case tok::semi: 299 case tok::r_paren: 300 case tok::r_square: 301 case tok::r_brace: 302 case tok::colon: 303 case tok::comma: 304 return Owned(Actions.ActOnCXXThrow(ThrowLoc)); 305 306 default: 307 OwningExprResult Expr(ParseAssignmentExpression()); 308 if (Expr.isInvalid()) return move(Expr); 309 return Owned(Actions.ActOnCXXThrow(ThrowLoc, Expr.release())); 310 } 311} 312 313/// ParseCXXThis - This handles the C++ 'this' pointer. 314/// 315/// C++ 9.3.2: In the body of a non-static member function, the keyword this is 316/// a non-lvalue expression whose value is the address of the object for which 317/// the function is called. 318Parser::OwningExprResult Parser::ParseCXXThis() { 319 assert(Tok.is(tok::kw_this) && "Not 'this'!"); 320 SourceLocation ThisLoc = ConsumeToken(); 321 return Owned(Actions.ActOnCXXThis(ThisLoc)); 322} 323 324/// ParseCXXTypeConstructExpression - Parse construction of a specified type. 325/// Can be interpreted either as function-style casting ("int(x)") 326/// or class type construction ("ClassType(x,y,z)") 327/// or creation of a value-initialized type ("int()"). 328/// 329/// postfix-expression: [C++ 5.2p1] 330/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] 331/// typename-specifier '(' expression-list[opt] ')' [TODO] 332/// 333Parser::OwningExprResult 334Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { 335 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); 336 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get(); 337 338 assert(Tok.is(tok::l_paren) && "Expected '('!"); 339 SourceLocation LParenLoc = ConsumeParen(); 340 341 ExprVector Exprs(Actions); 342 CommaLocsTy CommaLocs; 343 344 if (Tok.isNot(tok::r_paren)) { 345 if (ParseExpressionList(Exprs, CommaLocs)) { 346 SkipUntil(tok::r_paren); 347 return ExprError(); 348 } 349 } 350 351 // Match the ')'. 352 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); 353 354 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& 355 "Unexpected number of commas!"); 356 return Owned(Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep, 357 LParenLoc, 358 Exprs.take(), Exprs.size(), 359 &CommaLocs[0], RParenLoc)); 360} 361 362/// ParseCXXCondition - if/switch/while/for condition expression. 363/// 364/// condition: 365/// expression 366/// type-specifier-seq declarator '=' assignment-expression 367/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] 368/// '=' assignment-expression 369/// 370Parser::OwningExprResult Parser::ParseCXXCondition() { 371 if (!isCXXConditionDeclaration()) 372 return ParseExpression(); // expression 373 374 SourceLocation StartLoc = Tok.getLocation(); 375 376 // type-specifier-seq 377 DeclSpec DS; 378 ParseSpecifierQualifierList(DS); 379 380 // declarator 381 Declarator DeclaratorInfo(DS, Declarator::ConditionContext); 382 ParseDeclarator(DeclaratorInfo); 383 384 // simple-asm-expr[opt] 385 if (Tok.is(tok::kw_asm)) { 386 OwningExprResult AsmLabel(ParseSimpleAsm()); 387 if (AsmLabel.isInvalid()) { 388 SkipUntil(tok::semi); 389 return ExprError(); 390 } 391 DeclaratorInfo.setAsmLabel(AsmLabel.release()); 392 } 393 394 // If attributes are present, parse them. 395 if (Tok.is(tok::kw___attribute)) 396 DeclaratorInfo.AddAttributes(ParseAttributes()); 397 398 // '=' assignment-expression 399 if (Tok.isNot(tok::equal)) 400 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator)); 401 SourceLocation EqualLoc = ConsumeToken(); 402 OwningExprResult AssignExpr(ParseAssignmentExpression()); 403 if (AssignExpr.isInvalid()) 404 return ExprError(); 405 406 return Owned(Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc, 407 DeclaratorInfo,EqualLoc, 408 AssignExpr.release())); 409} 410 411/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. 412/// This should only be called when the current token is known to be part of 413/// simple-type-specifier. 414/// 415/// simple-type-specifier: 416/// '::'[opt] nested-name-specifier[opt] type-name 417/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO] 418/// char 419/// wchar_t 420/// bool 421/// short 422/// int 423/// long 424/// signed 425/// unsigned 426/// float 427/// double 428/// void 429/// [GNU] typeof-specifier 430/// [C++0x] auto [TODO] 431/// 432/// type-name: 433/// class-name 434/// enum-name 435/// typedef-name 436/// 437void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { 438 DS.SetRangeStart(Tok.getLocation()); 439 const char *PrevSpec; 440 SourceLocation Loc = Tok.getLocation(); 441 442 switch (Tok.getKind()) { 443 case tok::identifier: // foo::bar 444 case tok::coloncolon: // ::foo::bar 445 assert(0 && "Annotation token should already be formed!"); 446 default: 447 assert(0 && "Not a simple-type-specifier token!"); 448 abort(); 449 450 // type-name 451 case tok::annot_typename: { 452 DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec, 453 Tok.getAnnotationValue()); 454 break; 455 } 456 457 // builtin types 458 case tok::kw_short: 459 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec); 460 break; 461 case tok::kw_long: 462 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec); 463 break; 464 case tok::kw_signed: 465 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec); 466 break; 467 case tok::kw_unsigned: 468 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec); 469 break; 470 case tok::kw_void: 471 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec); 472 break; 473 case tok::kw_char: 474 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec); 475 break; 476 case tok::kw_int: 477 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec); 478 break; 479 case tok::kw_float: 480 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec); 481 break; 482 case tok::kw_double: 483 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec); 484 break; 485 case tok::kw_wchar_t: 486 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec); 487 break; 488 case tok::kw_bool: 489 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec); 490 break; 491 492 // GNU typeof support. 493 case tok::kw_typeof: 494 ParseTypeofSpecifier(DS); 495 DS.Finish(Diags, PP.getSourceManager(), getLang()); 496 return; 497 } 498 if (Tok.is(tok::annot_typename)) 499 DS.SetRangeEnd(Tok.getAnnotationEndLoc()); 500 else 501 DS.SetRangeEnd(Tok.getLocation()); 502 ConsumeToken(); 503 DS.Finish(Diags, PP.getSourceManager(), getLang()); 504} 505 506/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++ 507/// [dcl.name]), which is a non-empty sequence of type-specifiers, 508/// e.g., "const short int". Note that the DeclSpec is *not* finished 509/// by parsing the type-specifier-seq, because these sequences are 510/// typically followed by some form of declarator. Returns true and 511/// emits diagnostics if this is not a type-specifier-seq, false 512/// otherwise. 513/// 514/// type-specifier-seq: [C++ 8.1] 515/// type-specifier type-specifier-seq[opt] 516/// 517bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { 518 DS.SetRangeStart(Tok.getLocation()); 519 const char *PrevSpec = 0; 520 int isInvalid = 0; 521 522 // Parse one or more of the type specifiers. 523 if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) { 524 Diag(Tok, diag::err_operator_missing_type_specifier); 525 return true; 526 } 527 528 while (ParseOptionalTypeSpecifier(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.get(); 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 843static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) 844{ 845 switch(kind) { 846 default: assert(false && "Not a known unary type trait."); 847 case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign; 848 case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy; 849 case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor; 850 case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign; 851 case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy; 852 case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor; 853 case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor; 854 case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor; 855 case tok::kw___is_abstract: return UTT_IsAbstract; 856 case tok::kw___is_class: return UTT_IsClass; 857 case tok::kw___is_empty: return UTT_IsEmpty; 858 case tok::kw___is_enum: return UTT_IsEnum; 859 case tok::kw___is_pod: return UTT_IsPOD; 860 case tok::kw___is_polymorphic: return UTT_IsPolymorphic; 861 case tok::kw___is_union: return UTT_IsUnion; 862 } 863} 864 865/// ParseUnaryTypeTrait - Parse the built-in unary type-trait 866/// pseudo-functions that allow implementation of the TR1/C++0x type traits 867/// templates. 868/// 869/// primary-expression: 870/// [GNU] unary-type-trait '(' type-id ')' 871/// 872Parser::OwningExprResult Parser::ParseUnaryTypeTrait() 873{ 874 UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind()); 875 SourceLocation Loc = ConsumeToken(); 876 877 SourceLocation LParen = Tok.getLocation(); 878 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) 879 return ExprError(); 880 881 // FIXME: Error reporting absolutely sucks! If the this fails to parse a type 882 // there will be cryptic errors about mismatched parentheses and missing 883 // specifiers. 884 TypeTy *Ty = ParseTypeName(); 885 886 SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); 887 888 return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty, RParen); 889} 890