ParseExprCXX.cpp revision 02bcd4cd1a19121da12884aa4943226f72a81e6c
1//===--- ParseExprCXX.cpp - C++ Expression Parsing ------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements the Expression parsing implementation for C++. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/Basic/Diagnostic.h" 15#include "clang/Parse/Parser.h" 16#include "clang/Parse/DeclSpec.h" 17using namespace clang; 18 19/// ParseCXXScopeSpecifier - Parse global scope or nested-name-specifier. 20/// 21/// '::'[opt] nested-name-specifier 22/// '::' 23/// 24/// nested-name-specifier: 25/// type-name '::' 26/// namespace-name '::' 27/// nested-name-specifier identifier '::' 28/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO] 29/// 30void Parser::ParseCXXScopeSpecifier(CXXScopeSpec &SS) { 31 assert(isTokenCXXScopeSpecifier() && "Not scope specifier!"); 32 33 if (Tok.is(tok::annot_cxxscope)) { 34 SS.setScopeRep(Tok.getAnnotationValue()); 35 SS.setRange(Tok.getAnnotationRange()); 36 ConsumeToken(); 37 return; 38 } 39 40 SS.setBeginLoc(Tok.getLocation()); 41 42 // '::' 43 44 if (Tok.is(tok::coloncolon)) { 45 // Global scope. 46 SourceLocation CCLoc = ConsumeToken(); 47 SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc)); 48 SS.setEndLoc(CCLoc); 49 } 50 51 // nested-name-specifier: 52 // type-name '::' 53 // namespace-name '::' 54 // nested-name-specifier identifier '::' 55 // nested-name-specifier 'template'[opt] simple-template-id '::' [TODO] 56 57 while (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) { 58 IdentifierInfo *II = Tok.getIdentifierInfo(); 59 SourceLocation IdLoc = ConsumeToken(); 60 assert(Tok.is(tok::coloncolon) && 61 "NextToken() not working properly!"); 62 SourceLocation CCLoc = ConsumeToken(); 63 if (SS.isInvalid()) 64 continue; 65 66 SS.setScopeRep( 67 Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II) ); 68 SS.setEndLoc(CCLoc); 69 } 70} 71 72/// ParseCXXIdExpression - Handle id-expression. 73/// 74/// id-expression: 75/// unqualified-id 76/// qualified-id 77/// 78/// unqualified-id: 79/// identifier 80/// operator-function-id 81/// conversion-function-id [TODO] 82/// '~' class-name [TODO] 83/// template-id [TODO] 84/// 85/// qualified-id: 86/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id 87/// '::' identifier 88/// '::' operator-function-id 89/// '::' template-id [TODO] 90/// 91/// nested-name-specifier: 92/// type-name '::' 93/// namespace-name '::' 94/// nested-name-specifier identifier '::' 95/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO] 96/// 97/// NOTE: The standard specifies that, for qualified-id, the parser does not 98/// expect: 99/// 100/// '::' conversion-function-id 101/// '::' '~' class-name 102/// 103/// This may cause a slight inconsistency on diagnostics: 104/// 105/// class C {}; 106/// namespace A {} 107/// void f() { 108/// :: A :: ~ C(); // Some Sema error about using destructor with a 109/// // namespace. 110/// :: ~ C(); // Some Parser error like 'unexpected ~'. 111/// } 112/// 113/// We simplify the parser a bit and make it work like: 114/// 115/// qualified-id: 116/// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id 117/// '::' unqualified-id 118/// 119/// That way Sema can handle and report similar errors for namespaces and the 120/// global scope. 121/// 122Parser::ExprResult Parser::ParseCXXIdExpression() { 123 // qualified-id: 124 // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id 125 // '::' unqualified-id 126 // 127 CXXScopeSpec SS; 128 if (isTokenCXXScopeSpecifier()) 129 ParseCXXScopeSpecifier(SS); 130 131 // unqualified-id: 132 // identifier 133 // operator-function-id 134 // conversion-function-id [TODO] 135 // '~' class-name [TODO] 136 // template-id [TODO] 137 // 138 switch (Tok.getKind()) { 139 default: 140 return Diag(Tok, diag::err_expected_unqualified_id); 141 142 case tok::identifier: { 143 // Consume the identifier so that we can see if it is followed by a '('. 144 IdentifierInfo &II = *Tok.getIdentifierInfo(); 145 SourceLocation L = ConsumeToken(); 146 return Actions.ActOnIdentifierExpr(CurScope, L, II, 147 Tok.is(tok::l_paren), &SS); 148 } 149 150 case tok::kw_operator: { 151 SourceLocation OperatorLoc = Tok.getLocation(); 152 if (IdentifierInfo *II = MaybeParseOperatorFunctionId()) { 153 return Actions.ActOnIdentifierExpr(CurScope, OperatorLoc, *II, 154 Tok.is(tok::l_paren), &SS); 155 } 156 // FIXME: Handle conversion-function-id. 157 unsigned DiagID = PP.getDiagnostics().getCustomDiagID(Diagnostic::Error, 158 "expected operator-function-id"); 159 return Diag(Tok, DiagID); 160 } 161 162 } // switch. 163 164 assert(0 && "The switch was supposed to take care everything."); 165} 166 167/// ParseCXXCasts - This handles the various ways to cast expressions to another 168/// type. 169/// 170/// postfix-expression: [C++ 5.2p1] 171/// 'dynamic_cast' '<' type-name '>' '(' expression ')' 172/// 'static_cast' '<' type-name '>' '(' expression ')' 173/// 'reinterpret_cast' '<' type-name '>' '(' expression ')' 174/// 'const_cast' '<' type-name '>' '(' expression ')' 175/// 176Parser::ExprResult Parser::ParseCXXCasts() { 177 tok::TokenKind Kind = Tok.getKind(); 178 const char *CastName = 0; // For error messages 179 180 switch (Kind) { 181 default: assert(0 && "Unknown C++ cast!"); abort(); 182 case tok::kw_const_cast: CastName = "const_cast"; break; 183 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break; 184 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break; 185 case tok::kw_static_cast: CastName = "static_cast"; break; 186 } 187 188 SourceLocation OpLoc = ConsumeToken(); 189 SourceLocation LAngleBracketLoc = Tok.getLocation(); 190 191 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName)) 192 return ExprResult(true); 193 194 TypeTy *CastTy = ParseTypeName(); 195 SourceLocation RAngleBracketLoc = Tok.getLocation(); 196 197 if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) { 198 Diag(LAngleBracketLoc, diag::err_matching, "<"); 199 return ExprResult(true); 200 } 201 202 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc; 203 204 if (Tok.isNot(tok::l_paren)) { 205 Diag(Tok, diag::err_expected_lparen_after, CastName); 206 return ExprResult(true); 207 } 208 209 ExprResult Result = ParseSimpleParenExpression(RParenLoc); 210 211 if (!Result.isInvalid) 212 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind, 213 LAngleBracketLoc, CastTy, RAngleBracketLoc, 214 LParenLoc, Result.Val, RParenLoc); 215 216 return Result; 217} 218 219/// ParseCXXBoolLiteral - This handles the C++ Boolean literals. 220/// 221/// boolean-literal: [C++ 2.13.5] 222/// 'true' 223/// 'false' 224Parser::ExprResult Parser::ParseCXXBoolLiteral() { 225 tok::TokenKind Kind = Tok.getKind(); 226 return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind); 227} 228 229/// ParseThrowExpression - This handles the C++ throw expression. 230/// 231/// throw-expression: [C++ 15] 232/// 'throw' assignment-expression[opt] 233Parser::ExprResult Parser::ParseThrowExpression() { 234 assert(Tok.is(tok::kw_throw) && "Not throw!"); 235 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token. 236 237 // If the current token isn't the start of an assignment-expression, 238 // then the expression is not present. This handles things like: 239 // "C ? throw : (void)42", which is crazy but legal. 240 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common. 241 case tok::semi: 242 case tok::r_paren: 243 case tok::r_square: 244 case tok::r_brace: 245 case tok::colon: 246 case tok::comma: 247 return Actions.ActOnCXXThrow(ThrowLoc); 248 249 default: 250 ExprResult Expr = ParseAssignmentExpression(); 251 if (Expr.isInvalid) return Expr; 252 return Actions.ActOnCXXThrow(ThrowLoc, Expr.Val); 253 } 254} 255 256/// ParseCXXThis - This handles the C++ 'this' pointer. 257/// 258/// C++ 9.3.2: In the body of a non-static member function, the keyword this is 259/// a non-lvalue expression whose value is the address of the object for which 260/// the function is called. 261Parser::ExprResult Parser::ParseCXXThis() { 262 assert(Tok.is(tok::kw_this) && "Not 'this'!"); 263 SourceLocation ThisLoc = ConsumeToken(); 264 return Actions.ActOnCXXThis(ThisLoc); 265} 266 267/// ParseCXXTypeConstructExpression - Parse construction of a specified type. 268/// Can be interpreted either as function-style casting ("int(x)") 269/// or class type construction ("ClassType(x,y,z)") 270/// or creation of a value-initialized type ("int()"). 271/// 272/// postfix-expression: [C++ 5.2p1] 273/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] 274/// typename-specifier '(' expression-list[opt] ')' [TODO] 275/// 276Parser::ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { 277 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); 278 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val; 279 280 assert(Tok.is(tok::l_paren) && "Expected '('!"); 281 SourceLocation LParenLoc = ConsumeParen(); 282 283 ExprListTy Exprs; 284 CommaLocsTy CommaLocs; 285 286 if (Tok.isNot(tok::r_paren)) { 287 if (ParseExpressionList(Exprs, CommaLocs)) { 288 SkipUntil(tok::r_paren); 289 return ExprResult(true); 290 } 291 } 292 293 // Match the ')'. 294 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); 295 296 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& 297 "Unexpected number of commas!"); 298 return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep, 299 LParenLoc, 300 &Exprs[0], Exprs.size(), 301 &CommaLocs[0], RParenLoc); 302} 303 304/// ParseCXXCondition - if/switch/while/for condition expression. 305/// 306/// condition: 307/// expression 308/// type-specifier-seq declarator '=' assignment-expression 309/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] 310/// '=' assignment-expression 311/// 312Parser::ExprResult Parser::ParseCXXCondition() { 313 if (!isCXXConditionDeclaration()) 314 return ParseExpression(); // expression 315 316 SourceLocation StartLoc = Tok.getLocation(); 317 318 // type-specifier-seq 319 DeclSpec DS; 320 ParseSpecifierQualifierList(DS); 321 322 // declarator 323 Declarator DeclaratorInfo(DS, Declarator::ConditionContext); 324 ParseDeclarator(DeclaratorInfo); 325 326 // simple-asm-expr[opt] 327 if (Tok.is(tok::kw_asm)) { 328 ExprResult AsmLabel = ParseSimpleAsm(); 329 if (AsmLabel.isInvalid) { 330 SkipUntil(tok::semi); 331 return true; 332 } 333 DeclaratorInfo.setAsmLabel(AsmLabel.Val); 334 } 335 336 // If attributes are present, parse them. 337 if (Tok.is(tok::kw___attribute)) 338 DeclaratorInfo.AddAttributes(ParseAttributes()); 339 340 // '=' assignment-expression 341 if (Tok.isNot(tok::equal)) 342 return Diag(Tok, diag::err_expected_equal_after_declarator); 343 SourceLocation EqualLoc = ConsumeToken(); 344 ExprResult AssignExpr = ParseAssignmentExpression(); 345 if (AssignExpr.isInvalid) 346 return true; 347 348 return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc, 349 DeclaratorInfo, 350 EqualLoc, AssignExpr.Val); 351} 352 353/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. 354/// This should only be called when the current token is known to be part of 355/// simple-type-specifier. 356/// 357/// simple-type-specifier: 358/// '::'[opt] nested-name-specifier[opt] type-name 359/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO] 360/// char 361/// wchar_t 362/// bool 363/// short 364/// int 365/// long 366/// signed 367/// unsigned 368/// float 369/// double 370/// void 371/// [GNU] typeof-specifier 372/// [C++0x] auto [TODO] 373/// 374/// type-name: 375/// class-name 376/// enum-name 377/// typedef-name 378/// 379void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { 380 // Annotate typenames and C++ scope specifiers. 381 TryAnnotateTypeOrScopeToken(); 382 383 DS.SetRangeStart(Tok.getLocation()); 384 const char *PrevSpec; 385 SourceLocation Loc = Tok.getLocation(); 386 387 switch (Tok.getKind()) { 388 default: 389 assert(0 && "Not a simple-type-specifier token!"); 390 abort(); 391 392 // type-name 393 case tok::annot_qualtypename: { 394 DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec, 395 Tok.getAnnotationValue()); 396 break; 397 } 398 399 // builtin types 400 case tok::kw_short: 401 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec); 402 break; 403 case tok::kw_long: 404 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec); 405 break; 406 case tok::kw_signed: 407 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec); 408 break; 409 case tok::kw_unsigned: 410 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec); 411 break; 412 case tok::kw_void: 413 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec); 414 break; 415 case tok::kw_char: 416 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec); 417 break; 418 case tok::kw_int: 419 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec); 420 break; 421 case tok::kw_float: 422 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec); 423 break; 424 case tok::kw_double: 425 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec); 426 break; 427 case tok::kw_wchar_t: 428 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec); 429 break; 430 case tok::kw_bool: 431 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec); 432 break; 433 434 // GNU typeof support. 435 case tok::kw_typeof: 436 ParseTypeofSpecifier(DS); 437 DS.Finish(Diags, PP.getSourceManager(), getLang()); 438 return; 439 } 440 if (Tok.is(tok::annot_qualtypename)) 441 DS.SetRangeEnd(Tok.getAnnotationEndLoc()); 442 else 443 DS.SetRangeEnd(Tok.getLocation()); 444 ConsumeToken(); 445 DS.Finish(Diags, PP.getSourceManager(), getLang()); 446} 447 448/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++ 449/// [dcl.name]), which is a non-empty sequence of type-specifiers, 450/// e.g., "const short int". Note that the DeclSpec is *not* finished 451/// by parsing the type-specifier-seq, because these sequences are 452/// typically followed by some form of declarator. Returns true and 453/// emits diagnostics if this is not a type-specifier-seq, false 454/// otherwise. 455/// 456/// type-specifier-seq: [C++ 8.1] 457/// type-specifier type-specifier-seq[opt] 458/// 459bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { 460 DS.SetRangeStart(Tok.getLocation()); 461 const char *PrevSpec = 0; 462 int isInvalid = 0; 463 464 // Parse one or more of the type specifiers. 465 if (!MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) { 466 Diag(Tok.getLocation(), diag::err_operator_missing_type_specifier); 467 return true; 468 } 469 while (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) ; 470 471 return false; 472} 473 474/// MaybeParseOperatorFunctionId - Attempts to parse a C++ overloaded 475/// operator name (C++ [over.oper]). If successful, returns the 476/// predefined identifier that corresponds to that overloaded 477/// operator. Otherwise, returns NULL and does not consume any tokens. 478/// 479/// operator-function-id: [C++ 13.5] 480/// 'operator' operator 481/// 482/// operator: one of 483/// new delete new[] delete[] 484/// + - * / % ^ & | ~ 485/// ! = < > += -= *= /= %= 486/// ^= &= |= << >> >>= <<= == != 487/// <= >= && || ++ -- , ->* -> 488/// () [] 489IdentifierInfo *Parser::MaybeParseOperatorFunctionId() { 490 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); 491 492 OverloadedOperatorKind Op = OO_None; 493 switch (NextToken().getKind()) { 494 case tok::kw_new: 495 ConsumeToken(); // 'operator' 496 ConsumeToken(); // 'new' 497 if (Tok.is(tok::l_square)) { 498 ConsumeBracket(); // '[' 499 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 500 Op = OO_Array_New; 501 } else { 502 Op = OO_New; 503 } 504 return &PP.getIdentifierTable().getOverloadedOperator(Op); 505 506 case tok::kw_delete: 507 ConsumeToken(); // 'operator' 508 ConsumeToken(); // 'delete' 509 if (Tok.is(tok::l_square)) { 510 ConsumeBracket(); // '[' 511 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 512 Op = OO_Array_Delete; 513 } else { 514 Op = OO_Delete; 515 } 516 return &PP.getIdentifierTable().getOverloadedOperator(Op); 517 518#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ 519 case tok::Token: Op = OO_##Name; break; 520#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) 521#include "clang/Basic/OperatorKinds.def" 522 523 case tok::l_paren: 524 ConsumeToken(); // 'operator' 525 ConsumeParen(); // '(' 526 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')' 527 return &PP.getIdentifierTable().getOverloadedOperator(OO_Call); 528 529 case tok::l_square: 530 ConsumeToken(); // 'operator' 531 ConsumeBracket(); // '[' 532 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 533 return &PP.getIdentifierTable().getOverloadedOperator(OO_Subscript); 534 535 default: 536 break; 537 } 538 539 if (Op == OO_None) 540 return 0; 541 else { 542 ConsumeToken(); // 'operator' 543 ConsumeAnyToken(); // the operator itself 544 return &PP.getIdentifierTable().getOverloadedOperator(Op); 545 } 546} 547 548/// ParseConversionFunctionId - Parse a C++ conversion-function-id, 549/// which expresses the name of a user-defined conversion operator 550/// (C++ [class.conv.fct]p1). Returns the type that this operator is 551/// specifying a conversion for, or NULL if there was an error. 552/// 553/// conversion-function-id: [C++ 12.3.2] 554/// operator conversion-type-id 555/// 556/// conversion-type-id: 557/// type-specifier-seq conversion-declarator[opt] 558/// 559/// conversion-declarator: 560/// ptr-operator conversion-declarator[opt] 561Parser::TypeTy *Parser::ParseConversionFunctionId() { 562 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); 563 ConsumeToken(); // 'operator' 564 565 // Parse the type-specifier-seq. 566 DeclSpec DS; 567 if (ParseCXXTypeSpecifierSeq(DS)) 568 return 0; 569 570 // Parse the conversion-declarator, which is merely a sequence of 571 // ptr-operators. 572 Declarator D(DS, Declarator::TypeNameContext); 573 ParseDeclaratorInternal(D, /*PtrOperator=*/true); 574 575 // Finish up the type. 576 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D); 577 if (Result.isInvalid) 578 return 0; 579 else 580 return Result.Val; 581} 582