ParseExprCXX.cpp revision 809070a886684cb5b92eb0e00a6581ab1fa6b17a
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/// 134/// The isAddressOfOperand parameter indicates that this id-expression is a 135/// direct operand of the address-of operator. This is, besides member contexts, 136/// the only place where a qualified-id naming a non-static class member may 137/// appear. 138/// 139Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { 140 // qualified-id: 141 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id 142 // '::' unqualified-id 143 // 144 CXXScopeSpec SS; 145 ParseOptionalCXXScopeSpecifier(SS); 146 147 // unqualified-id: 148 // identifier 149 // operator-function-id 150 // conversion-function-id 151 // '~' class-name [TODO] 152 // template-id [TODO] 153 // 154 switch (Tok.getKind()) { 155 default: 156 return ExprError(Diag(Tok, diag::err_expected_unqualified_id)); 157 158 case tok::identifier: { 159 // Consume the identifier so that we can see if it is followed by a '('. 160 IdentifierInfo &II = *Tok.getIdentifierInfo(); 161 SourceLocation L = ConsumeToken(); 162 return Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren), 163 &SS, isAddressOfOperand); 164 } 165 166 case tok::kw_operator: { 167 SourceLocation OperatorLoc = Tok.getLocation(); 168 if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) 169 return Actions.ActOnCXXOperatorFunctionIdExpr( 170 CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS, 171 isAddressOfOperand); 172 if (TypeTy *Type = ParseConversionFunctionId()) 173 return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type, 174 Tok.is(tok::l_paren), SS, 175 isAddressOfOperand); 176 177 // We already complained about a bad conversion-function-id, 178 // above. 179 return ExprError(); 180 } 181 182 } // switch. 183 184 assert(0 && "The switch was supposed to take care everything."); 185} 186 187/// ParseCXXCasts - This handles the various ways to cast expressions to another 188/// type. 189/// 190/// postfix-expression: [C++ 5.2p1] 191/// 'dynamic_cast' '<' type-name '>' '(' expression ')' 192/// 'static_cast' '<' type-name '>' '(' expression ')' 193/// 'reinterpret_cast' '<' type-name '>' '(' expression ')' 194/// 'const_cast' '<' type-name '>' '(' expression ')' 195/// 196Parser::OwningExprResult Parser::ParseCXXCasts() { 197 tok::TokenKind Kind = Tok.getKind(); 198 const char *CastName = 0; // For error messages 199 200 switch (Kind) { 201 default: assert(0 && "Unknown C++ cast!"); abort(); 202 case tok::kw_const_cast: CastName = "const_cast"; break; 203 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break; 204 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break; 205 case tok::kw_static_cast: CastName = "static_cast"; break; 206 } 207 208 SourceLocation OpLoc = ConsumeToken(); 209 SourceLocation LAngleBracketLoc = Tok.getLocation(); 210 211 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName)) 212 return ExprError(); 213 214 TypeResult CastTy = ParseTypeName(); 215 SourceLocation RAngleBracketLoc = Tok.getLocation(); 216 217 if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) 218 return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<"); 219 220 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc; 221 222 if (Tok.isNot(tok::l_paren)) 223 return ExprError(Diag(Tok, diag::err_expected_lparen_after) << CastName); 224 225 OwningExprResult Result(ParseSimpleParenExpression(RParenLoc)); 226 227 if (!Result.isInvalid() && !CastTy.isInvalid()) 228 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind, 229 LAngleBracketLoc, CastTy.get(), 230 RAngleBracketLoc, 231 LParenLoc, Result.release(), RParenLoc); 232 233 return move(Result); 234} 235 236/// ParseCXXTypeid - This handles the C++ typeid expression. 237/// 238/// postfix-expression: [C++ 5.2p1] 239/// 'typeid' '(' expression ')' 240/// 'typeid' '(' type-id ')' 241/// 242Parser::OwningExprResult Parser::ParseCXXTypeid() { 243 assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!"); 244 245 SourceLocation OpLoc = ConsumeToken(); 246 SourceLocation LParenLoc = Tok.getLocation(); 247 SourceLocation RParenLoc; 248 249 // typeid expressions are always parenthesized. 250 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, 251 "typeid")) 252 return ExprError(); 253 254 OwningExprResult Result(Actions); 255 256 if (isTypeIdInParens()) { 257 TypeResult Ty = ParseTypeName(); 258 259 // Match the ')'. 260 MatchRHSPunctuation(tok::r_paren, LParenLoc); 261 262 if (Ty.isInvalid()) 263 return ExprError(); 264 265 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true, 266 Ty.get(), RParenLoc); 267 } else { 268 Result = ParseExpression(); 269 270 // Match the ')'. 271 if (Result.isInvalid()) 272 SkipUntil(tok::r_paren); 273 else { 274 MatchRHSPunctuation(tok::r_paren, LParenLoc); 275 276 Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false, 277 Result.release(), RParenLoc); 278 } 279 } 280 281 return move(Result); 282} 283 284/// ParseCXXBoolLiteral - This handles the C++ Boolean literals. 285/// 286/// boolean-literal: [C++ 2.13.5] 287/// 'true' 288/// 'false' 289Parser::OwningExprResult Parser::ParseCXXBoolLiteral() { 290 tok::TokenKind Kind = Tok.getKind(); 291 return Owned(Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind)); 292} 293 294/// ParseThrowExpression - This handles the C++ throw expression. 295/// 296/// throw-expression: [C++ 15] 297/// 'throw' assignment-expression[opt] 298Parser::OwningExprResult Parser::ParseThrowExpression() { 299 assert(Tok.is(tok::kw_throw) && "Not throw!"); 300 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token. 301 302 // If the current token isn't the start of an assignment-expression, 303 // then the expression is not present. This handles things like: 304 // "C ? throw : (void)42", which is crazy but legal. 305 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common. 306 case tok::semi: 307 case tok::r_paren: 308 case tok::r_square: 309 case tok::r_brace: 310 case tok::colon: 311 case tok::comma: 312 return Owned(Actions.ActOnCXXThrow(ThrowLoc)); 313 314 default: 315 OwningExprResult Expr(ParseAssignmentExpression()); 316 if (Expr.isInvalid()) return move(Expr); 317 return Owned(Actions.ActOnCXXThrow(ThrowLoc, Expr.release())); 318 } 319} 320 321/// ParseCXXThis - This handles the C++ 'this' pointer. 322/// 323/// C++ 9.3.2: In the body of a non-static member function, the keyword this is 324/// a non-lvalue expression whose value is the address of the object for which 325/// the function is called. 326Parser::OwningExprResult Parser::ParseCXXThis() { 327 assert(Tok.is(tok::kw_this) && "Not 'this'!"); 328 SourceLocation ThisLoc = ConsumeToken(); 329 return Owned(Actions.ActOnCXXThis(ThisLoc)); 330} 331 332/// ParseCXXTypeConstructExpression - Parse construction of a specified type. 333/// Can be interpreted either as function-style casting ("int(x)") 334/// or class type construction ("ClassType(x,y,z)") 335/// or creation of a value-initialized type ("int()"). 336/// 337/// postfix-expression: [C++ 5.2p1] 338/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] 339/// typename-specifier '(' expression-list[opt] ')' [TODO] 340/// 341Parser::OwningExprResult 342Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { 343 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); 344 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get(); 345 346 assert(Tok.is(tok::l_paren) && "Expected '('!"); 347 SourceLocation LParenLoc = ConsumeParen(); 348 349 ExprVector Exprs(Actions); 350 CommaLocsTy CommaLocs; 351 352 if (Tok.isNot(tok::r_paren)) { 353 if (ParseExpressionList(Exprs, CommaLocs)) { 354 SkipUntil(tok::r_paren); 355 return ExprError(); 356 } 357 } 358 359 // Match the ')'. 360 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); 361 362 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& 363 "Unexpected number of commas!"); 364 return Owned(Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep, 365 LParenLoc, 366 Exprs.take(), Exprs.size(), 367 &CommaLocs[0], RParenLoc)); 368} 369 370/// ParseCXXCondition - if/switch/while/for condition expression. 371/// 372/// condition: 373/// expression 374/// type-specifier-seq declarator '=' assignment-expression 375/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] 376/// '=' assignment-expression 377/// 378Parser::OwningExprResult Parser::ParseCXXCondition() { 379 if (!isCXXConditionDeclaration()) 380 return ParseExpression(); // expression 381 382 SourceLocation StartLoc = Tok.getLocation(); 383 384 // type-specifier-seq 385 DeclSpec DS; 386 ParseSpecifierQualifierList(DS); 387 388 // declarator 389 Declarator DeclaratorInfo(DS, Declarator::ConditionContext); 390 ParseDeclarator(DeclaratorInfo); 391 392 // simple-asm-expr[opt] 393 if (Tok.is(tok::kw_asm)) { 394 SourceLocation Loc; 395 OwningExprResult AsmLabel(ParseSimpleAsm(&Loc)); 396 if (AsmLabel.isInvalid()) { 397 SkipUntil(tok::semi); 398 return ExprError(); 399 } 400 DeclaratorInfo.setAsmLabel(AsmLabel.release()); 401 DeclaratorInfo.SetRangeEnd(Loc); 402 } 403 404 // If attributes are present, parse them. 405 if (Tok.is(tok::kw___attribute)) { 406 SourceLocation Loc; 407 AttributeList *AttrList = ParseAttributes(&Loc); 408 DeclaratorInfo.AddAttributes(AttrList, Loc); 409 } 410 411 // '=' assignment-expression 412 if (Tok.isNot(tok::equal)) 413 return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator)); 414 SourceLocation EqualLoc = ConsumeToken(); 415 OwningExprResult AssignExpr(ParseAssignmentExpression()); 416 if (AssignExpr.isInvalid()) 417 return ExprError(); 418 419 return Owned(Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc, 420 DeclaratorInfo,EqualLoc, 421 AssignExpr.release())); 422} 423 424/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. 425/// This should only be called when the current token is known to be part of 426/// simple-type-specifier. 427/// 428/// simple-type-specifier: 429/// '::'[opt] nested-name-specifier[opt] type-name 430/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO] 431/// char 432/// wchar_t 433/// bool 434/// short 435/// int 436/// long 437/// signed 438/// unsigned 439/// float 440/// double 441/// void 442/// [GNU] typeof-specifier 443/// [C++0x] auto [TODO] 444/// 445/// type-name: 446/// class-name 447/// enum-name 448/// typedef-name 449/// 450void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { 451 DS.SetRangeStart(Tok.getLocation()); 452 const char *PrevSpec; 453 SourceLocation Loc = Tok.getLocation(); 454 455 switch (Tok.getKind()) { 456 case tok::identifier: // foo::bar 457 case tok::coloncolon: // ::foo::bar 458 assert(0 && "Annotation token should already be formed!"); 459 default: 460 assert(0 && "Not a simple-type-specifier token!"); 461 abort(); 462 463 // type-name 464 case tok::annot_typename: { 465 DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, 466 Tok.getAnnotationValue()); 467 break; 468 } 469 470 // builtin types 471 case tok::kw_short: 472 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec); 473 break; 474 case tok::kw_long: 475 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec); 476 break; 477 case tok::kw_signed: 478 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec); 479 break; 480 case tok::kw_unsigned: 481 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec); 482 break; 483 case tok::kw_void: 484 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec); 485 break; 486 case tok::kw_char: 487 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec); 488 break; 489 case tok::kw_int: 490 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec); 491 break; 492 case tok::kw_float: 493 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec); 494 break; 495 case tok::kw_double: 496 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec); 497 break; 498 case tok::kw_wchar_t: 499 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec); 500 break; 501 case tok::kw_bool: 502 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec); 503 break; 504 505 // GNU typeof support. 506 case tok::kw_typeof: 507 ParseTypeofSpecifier(DS); 508 DS.Finish(Diags, PP.getSourceManager(), getLang()); 509 return; 510 } 511 if (Tok.is(tok::annot_typename)) 512 DS.SetRangeEnd(Tok.getAnnotationEndLoc()); 513 else 514 DS.SetRangeEnd(Tok.getLocation()); 515 ConsumeToken(); 516 DS.Finish(Diags, PP.getSourceManager(), getLang()); 517} 518 519/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++ 520/// [dcl.name]), which is a non-empty sequence of type-specifiers, 521/// e.g., "const short int". Note that the DeclSpec is *not* finished 522/// by parsing the type-specifier-seq, because these sequences are 523/// typically followed by some form of declarator. Returns true and 524/// emits diagnostics if this is not a type-specifier-seq, false 525/// otherwise. 526/// 527/// type-specifier-seq: [C++ 8.1] 528/// type-specifier type-specifier-seq[opt] 529/// 530bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { 531 DS.SetRangeStart(Tok.getLocation()); 532 const char *PrevSpec = 0; 533 int isInvalid = 0; 534 535 // Parse one or more of the type specifiers. 536 if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) { 537 Diag(Tok, diag::err_operator_missing_type_specifier); 538 return true; 539 } 540 541 while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) ; 542 543 return false; 544} 545 546/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded 547/// operator name (C++ [over.oper]). If successful, returns the 548/// predefined identifier that corresponds to that overloaded 549/// operator. Otherwise, returns NULL and does not consume any tokens. 550/// 551/// operator-function-id: [C++ 13.5] 552/// 'operator' operator 553/// 554/// operator: one of 555/// new delete new[] delete[] 556/// + - * / % ^ & | ~ 557/// ! = < > += -= *= /= %= 558/// ^= &= |= << >> >>= <<= == != 559/// <= >= && || ++ -- , ->* -> 560/// () [] 561OverloadedOperatorKind 562Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) { 563 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); 564 SourceLocation Loc; 565 566 OverloadedOperatorKind Op = OO_None; 567 switch (NextToken().getKind()) { 568 case tok::kw_new: 569 ConsumeToken(); // 'operator' 570 Loc = ConsumeToken(); // 'new' 571 if (Tok.is(tok::l_square)) { 572 ConsumeBracket(); // '[' 573 Loc = Tok.getLocation(); 574 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 575 Op = OO_Array_New; 576 } else { 577 Op = OO_New; 578 } 579 if (EndLoc) 580 *EndLoc = Loc; 581 return Op; 582 583 case tok::kw_delete: 584 ConsumeToken(); // 'operator' 585 Loc = ConsumeToken(); // 'delete' 586 if (Tok.is(tok::l_square)) { 587 ConsumeBracket(); // '[' 588 Loc = Tok.getLocation(); 589 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 590 Op = OO_Array_Delete; 591 } else { 592 Op = OO_Delete; 593 } 594 if (EndLoc) 595 *EndLoc = Loc; 596 return Op; 597 598#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ 599 case tok::Token: Op = OO_##Name; break; 600#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) 601#include "clang/Basic/OperatorKinds.def" 602 603 case tok::l_paren: 604 ConsumeToken(); // 'operator' 605 ConsumeParen(); // '(' 606 Loc = Tok.getLocation(); 607 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')' 608 if (EndLoc) 609 *EndLoc = Loc; 610 return OO_Call; 611 612 case tok::l_square: 613 ConsumeToken(); // 'operator' 614 ConsumeBracket(); // '[' 615 Loc = Tok.getLocation(); 616 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 617 if (EndLoc) 618 *EndLoc = Loc; 619 return OO_Subscript; 620 621 default: 622 return OO_None; 623 } 624 625 ConsumeToken(); // 'operator' 626 Loc = ConsumeAnyToken(); // the operator itself 627 if (EndLoc) 628 *EndLoc = Loc; 629 return Op; 630} 631 632/// ParseConversionFunctionId - Parse a C++ conversion-function-id, 633/// which expresses the name of a user-defined conversion operator 634/// (C++ [class.conv.fct]p1). Returns the type that this operator is 635/// specifying a conversion for, or NULL if there was an error. 636/// 637/// conversion-function-id: [C++ 12.3.2] 638/// operator conversion-type-id 639/// 640/// conversion-type-id: 641/// type-specifier-seq conversion-declarator[opt] 642/// 643/// conversion-declarator: 644/// ptr-operator conversion-declarator[opt] 645Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) { 646 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); 647 ConsumeToken(); // 'operator' 648 649 // Parse the type-specifier-seq. 650 DeclSpec DS; 651 if (ParseCXXTypeSpecifierSeq(DS)) 652 return 0; 653 654 // Parse the conversion-declarator, which is merely a sequence of 655 // ptr-operators. 656 Declarator D(DS, Declarator::TypeNameContext); 657 ParseDeclaratorInternal(D, /*DirectDeclParser=*/0); 658 if (EndLoc) 659 *EndLoc = D.getSourceRange().getEnd(); 660 661 // Finish up the type. 662 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D); 663 if (Result.isInvalid()) 664 return 0; 665 else 666 return Result.get(); 667} 668 669/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate 670/// memory in a typesafe manner and call constructors. 671/// 672/// This method is called to parse the new expression after the optional :: has 673/// been already parsed. If the :: was present, "UseGlobal" is true and "Start" 674/// is its location. Otherwise, "Start" is the location of the 'new' token. 675/// 676/// new-expression: 677/// '::'[opt] 'new' new-placement[opt] new-type-id 678/// new-initializer[opt] 679/// '::'[opt] 'new' new-placement[opt] '(' type-id ')' 680/// new-initializer[opt] 681/// 682/// new-placement: 683/// '(' expression-list ')' 684/// 685/// new-type-id: 686/// type-specifier-seq new-declarator[opt] 687/// 688/// new-declarator: 689/// ptr-operator new-declarator[opt] 690/// direct-new-declarator 691/// 692/// new-initializer: 693/// '(' expression-list[opt] ')' 694/// [C++0x] braced-init-list [TODO] 695/// 696Parser::OwningExprResult 697Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { 698 assert(Tok.is(tok::kw_new) && "expected 'new' token"); 699 ConsumeToken(); // Consume 'new' 700 701 // A '(' now can be a new-placement or the '(' wrapping the type-id in the 702 // second form of new-expression. It can't be a new-type-id. 703 704 ExprVector PlacementArgs(Actions); 705 SourceLocation PlacementLParen, PlacementRParen; 706 707 bool ParenTypeId; 708 DeclSpec DS; 709 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); 710 if (Tok.is(tok::l_paren)) { 711 // If it turns out to be a placement, we change the type location. 712 PlacementLParen = ConsumeParen(); 713 if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) { 714 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 715 return ExprError(); 716 } 717 718 PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen); 719 if (PlacementRParen.isInvalid()) { 720 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 721 return ExprError(); 722 } 723 724 if (PlacementArgs.empty()) { 725 // Reset the placement locations. There was no placement. 726 PlacementLParen = PlacementRParen = SourceLocation(); 727 ParenTypeId = true; 728 } else { 729 // We still need the type. 730 if (Tok.is(tok::l_paren)) { 731 SourceLocation LParen = ConsumeParen(); 732 ParseSpecifierQualifierList(DS); 733 DeclaratorInfo.SetSourceRange(DS.getSourceRange()); 734 ParseDeclarator(DeclaratorInfo); 735 MatchRHSPunctuation(tok::r_paren, LParen); 736 ParenTypeId = true; 737 } else { 738 if (ParseCXXTypeSpecifierSeq(DS)) 739 DeclaratorInfo.setInvalidType(true); 740 else { 741 DeclaratorInfo.SetSourceRange(DS.getSourceRange()); 742 ParseDeclaratorInternal(DeclaratorInfo, 743 &Parser::ParseDirectNewDeclarator); 744 } 745 ParenTypeId = false; 746 } 747 } 748 } else { 749 // A new-type-id is a simplified type-id, where essentially the 750 // direct-declarator is replaced by a direct-new-declarator. 751 if (ParseCXXTypeSpecifierSeq(DS)) 752 DeclaratorInfo.setInvalidType(true); 753 else { 754 DeclaratorInfo.SetSourceRange(DS.getSourceRange()); 755 ParseDeclaratorInternal(DeclaratorInfo, 756 &Parser::ParseDirectNewDeclarator); 757 } 758 ParenTypeId = false; 759 } 760 if (DeclaratorInfo.getInvalidType()) { 761 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 762 return ExprError(); 763 } 764 765 ExprVector ConstructorArgs(Actions); 766 SourceLocation ConstructorLParen, ConstructorRParen; 767 768 if (Tok.is(tok::l_paren)) { 769 ConstructorLParen = ConsumeParen(); 770 if (Tok.isNot(tok::r_paren)) { 771 CommaLocsTy CommaLocs; 772 if (ParseExpressionList(ConstructorArgs, CommaLocs)) { 773 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 774 return ExprError(); 775 } 776 } 777 ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen); 778 if (ConstructorRParen.isInvalid()) { 779 SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); 780 return ExprError(); 781 } 782 } 783 784 return Owned(Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, 785 PlacementArgs.take(), PlacementArgs.size(), 786 PlacementRParen, ParenTypeId, DeclaratorInfo, 787 ConstructorLParen, ConstructorArgs.take(), 788 ConstructorArgs.size(), ConstructorRParen)); 789} 790 791/// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be 792/// passed to ParseDeclaratorInternal. 793/// 794/// direct-new-declarator: 795/// '[' expression ']' 796/// direct-new-declarator '[' constant-expression ']' 797/// 798void Parser::ParseDirectNewDeclarator(Declarator &D) { 799 // Parse the array dimensions. 800 bool first = true; 801 while (Tok.is(tok::l_square)) { 802 SourceLocation LLoc = ConsumeBracket(); 803 OwningExprResult Size(first ? ParseExpression() 804 : ParseConstantExpression()); 805 if (Size.isInvalid()) { 806 // Recover 807 SkipUntil(tok::r_square); 808 return; 809 } 810 first = false; 811 812 SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc); 813 D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, 814 Size.release(), LLoc), 815 RLoc); 816 817 if (RLoc.isInvalid()) 818 return; 819 } 820} 821 822/// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id. 823/// This ambiguity appears in the syntax of the C++ new operator. 824/// 825/// new-expression: 826/// '::'[opt] 'new' new-placement[opt] '(' type-id ')' 827/// new-initializer[opt] 828/// 829/// new-placement: 830/// '(' expression-list ')' 831/// 832bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs, 833 Declarator &D) { 834 // The '(' was already consumed. 835 if (isTypeIdInParens()) { 836 ParseSpecifierQualifierList(D.getMutableDeclSpec()); 837 D.SetSourceRange(D.getDeclSpec().getSourceRange()); 838 ParseDeclarator(D); 839 return D.getInvalidType(); 840 } 841 842 // It's not a type, it has to be an expression list. 843 // Discard the comma locations - ActOnCXXNew has enough parameters. 844 CommaLocsTy CommaLocs; 845 return ParseExpressionList(PlacementArgs, CommaLocs); 846} 847 848/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used 849/// to free memory allocated by new. 850/// 851/// This method is called to parse the 'delete' expression after the optional 852/// '::' has been already parsed. If the '::' was present, "UseGlobal" is true 853/// and "Start" is its location. Otherwise, "Start" is the location of the 854/// 'delete' token. 855/// 856/// delete-expression: 857/// '::'[opt] 'delete' cast-expression 858/// '::'[opt] 'delete' '[' ']' cast-expression 859Parser::OwningExprResult 860Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { 861 assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword"); 862 ConsumeToken(); // Consume 'delete' 863 864 // Array delete? 865 bool ArrayDelete = false; 866 if (Tok.is(tok::l_square)) { 867 ArrayDelete = true; 868 SourceLocation LHS = ConsumeBracket(); 869 SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS); 870 if (RHS.isInvalid()) 871 return ExprError(); 872 } 873 874 OwningExprResult Operand(ParseCastExpression(false)); 875 if (Operand.isInvalid()) 876 return move(Operand); 877 878 return Owned(Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, 879 Operand.release())); 880} 881 882static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) 883{ 884 switch(kind) { 885 default: assert(false && "Not a known unary type trait."); 886 case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign; 887 case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy; 888 case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor; 889 case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign; 890 case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy; 891 case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor; 892 case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor; 893 case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor; 894 case tok::kw___is_abstract: return UTT_IsAbstract; 895 case tok::kw___is_class: return UTT_IsClass; 896 case tok::kw___is_empty: return UTT_IsEmpty; 897 case tok::kw___is_enum: return UTT_IsEnum; 898 case tok::kw___is_pod: return UTT_IsPOD; 899 case tok::kw___is_polymorphic: return UTT_IsPolymorphic; 900 case tok::kw___is_union: return UTT_IsUnion; 901 } 902} 903 904/// ParseUnaryTypeTrait - Parse the built-in unary type-trait 905/// pseudo-functions that allow implementation of the TR1/C++0x type traits 906/// templates. 907/// 908/// primary-expression: 909/// [GNU] unary-type-trait '(' type-id ')' 910/// 911Parser::OwningExprResult Parser::ParseUnaryTypeTrait() 912{ 913 UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind()); 914 SourceLocation Loc = ConsumeToken(); 915 916 SourceLocation LParen = Tok.getLocation(); 917 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) 918 return ExprError(); 919 920 // FIXME: Error reporting absolutely sucks! If the this fails to parse a type 921 // there will be cryptic errors about mismatched parentheses and missing 922 // specifiers. 923 TypeResult Ty = ParseTypeName(); 924 925 SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); 926 927 if (Ty.isInvalid()) 928 return ExprError(); 929 930 return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen); 931} 932