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