ParseExprCXX.cpp revision 2f1bc5285ccd40f411af5f5993f013e27e74ab78
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/// ParseCXXCasts - This handles the various ways to cast expressions to another 20/// type. 21/// 22/// postfix-expression: [C++ 5.2p1] 23/// 'dynamic_cast' '<' type-name '>' '(' expression ')' 24/// 'static_cast' '<' type-name '>' '(' expression ')' 25/// 'reinterpret_cast' '<' type-name '>' '(' expression ')' 26/// 'const_cast' '<' type-name '>' '(' expression ')' 27/// 28Parser::ExprResult Parser::ParseCXXCasts() { 29 tok::TokenKind Kind = Tok.getKind(); 30 const char *CastName = 0; // For error messages 31 32 switch (Kind) { 33 default: assert(0 && "Unknown C++ cast!"); abort(); 34 case tok::kw_const_cast: CastName = "const_cast"; break; 35 case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break; 36 case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break; 37 case tok::kw_static_cast: CastName = "static_cast"; break; 38 } 39 40 SourceLocation OpLoc = ConsumeToken(); 41 SourceLocation LAngleBracketLoc = Tok.getLocation(); 42 43 if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName)) 44 return ExprResult(true); 45 46 TypeTy *CastTy = ParseTypeName(); 47 SourceLocation RAngleBracketLoc = Tok.getLocation(); 48 49 if (ExpectAndConsume(tok::greater, diag::err_expected_greater)) { 50 Diag(LAngleBracketLoc, diag::err_matching, "<"); 51 return ExprResult(true); 52 } 53 54 SourceLocation LParenLoc = Tok.getLocation(), RParenLoc; 55 56 if (Tok.isNot(tok::l_paren)) { 57 Diag(Tok, diag::err_expected_lparen_after, CastName); 58 return ExprResult(true); 59 } 60 61 ExprResult Result = ParseSimpleParenExpression(RParenLoc); 62 63 if (!Result.isInvalid) 64 Result = Actions.ActOnCXXNamedCast(OpLoc, Kind, 65 LAngleBracketLoc, CastTy, RAngleBracketLoc, 66 LParenLoc, Result.Val, RParenLoc); 67 68 return Result; 69} 70 71/// ParseCXXBoolLiteral - This handles the C++ Boolean literals. 72/// 73/// boolean-literal: [C++ 2.13.5] 74/// 'true' 75/// 'false' 76Parser::ExprResult Parser::ParseCXXBoolLiteral() { 77 tok::TokenKind Kind = Tok.getKind(); 78 return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind); 79} 80 81/// ParseThrowExpression - This handles the C++ throw expression. 82/// 83/// throw-expression: [C++ 15] 84/// 'throw' assignment-expression[opt] 85Parser::ExprResult Parser::ParseThrowExpression() { 86 assert(Tok.is(tok::kw_throw) && "Not throw!"); 87 SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token. 88 89 // If the current token isn't the start of an assignment-expression, 90 // then the expression is not present. This handles things like: 91 // "C ? throw : (void)42", which is crazy but legal. 92 switch (Tok.getKind()) { // FIXME: move this predicate somewhere common. 93 case tok::semi: 94 case tok::r_paren: 95 case tok::r_square: 96 case tok::r_brace: 97 case tok::colon: 98 case tok::comma: 99 return Actions.ActOnCXXThrow(ThrowLoc); 100 101 default: 102 ExprResult Expr = ParseAssignmentExpression(); 103 if (Expr.isInvalid) return Expr; 104 return Actions.ActOnCXXThrow(ThrowLoc, Expr.Val); 105 } 106} 107 108/// ParseCXXThis - This handles the C++ 'this' pointer. 109/// 110/// C++ 9.3.2: In the body of a non-static member function, the keyword this is 111/// a non-lvalue expression whose value is the address of the object for which 112/// the function is called. 113Parser::ExprResult Parser::ParseCXXThis() { 114 assert(Tok.is(tok::kw_this) && "Not 'this'!"); 115 SourceLocation ThisLoc = ConsumeToken(); 116 return Actions.ActOnCXXThis(ThisLoc); 117} 118 119/// ParseCXXTypeConstructExpression - Parse construction of a specified type. 120/// Can be interpreted either as function-style casting ("int(x)") 121/// or class type construction ("ClassType(x,y,z)") 122/// or creation of a value-initialized type ("int()"). 123/// 124/// postfix-expression: [C++ 5.2p1] 125/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] 126/// typename-specifier '(' expression-list[opt] ')' [TODO] 127/// 128Parser::ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { 129 Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); 130 TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).Val; 131 132 assert(Tok.is(tok::l_paren) && "Expected '('!"); 133 SourceLocation LParenLoc = ConsumeParen(); 134 135 ExprListTy Exprs; 136 CommaLocsTy CommaLocs; 137 138 if (Tok.isNot(tok::r_paren)) { 139 if (ParseExpressionList(Exprs, CommaLocs)) { 140 SkipUntil(tok::r_paren); 141 return ExprResult(true); 142 } 143 } 144 145 // Match the ')'. 146 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); 147 148 assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& 149 "Unexpected number of commas!"); 150 return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep, 151 LParenLoc, 152 &Exprs[0], Exprs.size(), 153 &CommaLocs[0], RParenLoc); 154} 155 156/// ParseCXXCondition - if/switch/while/for condition expression. 157/// 158/// condition: 159/// expression 160/// type-specifier-seq declarator '=' assignment-expression 161/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt] 162/// '=' assignment-expression 163/// 164Parser::ExprResult Parser::ParseCXXCondition() { 165 if (!isCXXConditionDeclaration()) 166 return ParseExpression(); // expression 167 168 SourceLocation StartLoc = Tok.getLocation(); 169 170 // type-specifier-seq 171 DeclSpec DS; 172 ParseSpecifierQualifierList(DS); 173 174 // declarator 175 Declarator DeclaratorInfo(DS, Declarator::ConditionContext); 176 ParseDeclarator(DeclaratorInfo); 177 178 // simple-asm-expr[opt] 179 if (Tok.is(tok::kw_asm)) { 180 ExprResult AsmLabel = ParseSimpleAsm(); 181 if (AsmLabel.isInvalid) { 182 SkipUntil(tok::semi); 183 return true; 184 } 185 DeclaratorInfo.setAsmLabel(AsmLabel.Val); 186 } 187 188 // If attributes are present, parse them. 189 if (Tok.is(tok::kw___attribute)) 190 DeclaratorInfo.AddAttributes(ParseAttributes()); 191 192 // '=' assignment-expression 193 if (Tok.isNot(tok::equal)) 194 return Diag(Tok, diag::err_expected_equal_after_declarator); 195 SourceLocation EqualLoc = ConsumeToken(); 196 ExprResult AssignExpr = ParseAssignmentExpression(); 197 if (AssignExpr.isInvalid) 198 return true; 199 200 return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc, 201 DeclaratorInfo, 202 EqualLoc, AssignExpr.Val); 203} 204 205/// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. 206/// This should only be called when the current token is known to be part of 207/// simple-type-specifier. 208/// 209/// simple-type-specifier: 210/// '::'[opt] nested-name-specifier[opt] type-name [TODO] 211/// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO] 212/// char 213/// wchar_t 214/// bool 215/// short 216/// int 217/// long 218/// signed 219/// unsigned 220/// float 221/// double 222/// void 223/// [GNU] typeof-specifier 224/// [C++0x] auto [TODO] 225/// 226/// type-name: 227/// class-name 228/// enum-name 229/// typedef-name 230/// 231void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { 232 DS.SetRangeStart(Tok.getLocation()); 233 const char *PrevSpec; 234 SourceLocation Loc = Tok.getLocation(); 235 236 switch (Tok.getKind()) { 237 default: 238 assert(0 && "Not a simple-type-specifier token!"); 239 abort(); 240 241 // type-name 242 case tok::identifier: { 243 TypeTy *TypeRep = Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope); 244 assert(TypeRep && "Identifier wasn't a type-name!"); 245 DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec, TypeRep); 246 break; 247 } 248 249 // builtin types 250 case tok::kw_short: 251 DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec); 252 break; 253 case tok::kw_long: 254 DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec); 255 break; 256 case tok::kw_signed: 257 DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec); 258 break; 259 case tok::kw_unsigned: 260 DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec); 261 break; 262 case tok::kw_void: 263 DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec); 264 break; 265 case tok::kw_char: 266 DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec); 267 break; 268 case tok::kw_int: 269 DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec); 270 break; 271 case tok::kw_float: 272 DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec); 273 break; 274 case tok::kw_double: 275 DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec); 276 break; 277 case tok::kw_wchar_t: 278 DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec); 279 break; 280 case tok::kw_bool: 281 DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec); 282 break; 283 284 // GNU typeof support. 285 case tok::kw_typeof: 286 ParseTypeofSpecifier(DS); 287 DS.Finish(Diags, PP.getSourceManager(), getLang()); 288 return; 289 } 290 DS.SetRangeEnd(Tok.getLocation()); 291 ConsumeToken(); 292 DS.Finish(Diags, PP.getSourceManager(), getLang()); 293} 294 295/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++ 296/// [dcl.name]), which is a non-empty sequence of type-specifiers, 297/// e.g., "const short int". Note that the DeclSpec is *not* finished 298/// by parsing the type-specifier-seq, because these sequences are 299/// typically followed by some form of declarator. Returns true and 300/// emits diagnostics if this is not a type-specifier-seq, false 301/// otherwise. 302/// 303/// type-specifier-seq: [C++ 8.1] 304/// type-specifier type-specifier-seq[opt] 305/// 306bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { 307 DS.SetRangeStart(Tok.getLocation()); 308 const char *PrevSpec = 0; 309 int isInvalid = 0; 310 311 // Parse one or more of the type specifiers. 312 if (!MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) { 313 Diag(Tok.getLocation(), diag::err_operator_missing_type_specifier); 314 return true; 315 } 316 while (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)); 317 318 return false; 319} 320 321/// MaybeParseOperatorFunctionId - Attempts to parse a C++ overloaded 322/// operator name (C++ [over.oper]). If successful, returns the 323/// predefined identifier that corresponds to that overloaded 324/// operator. Otherwise, returns NULL and does not consume any tokens. 325/// 326/// operator-function-id: [C++ 13.5] 327/// 'operator' operator 328/// 329/// operator: one of 330/// new delete new[] delete[] 331/// + - * / % ^ & | ~ 332/// ! = < > += -= *= /= %= 333/// ^= &= |= << >> >>= <<= == != 334/// <= >= && || ++ -- , ->* -> 335/// () [] 336IdentifierInfo *Parser::MaybeParseOperatorFunctionId() { 337 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); 338 339 OverloadedOperatorKind Op = OO_None; 340 switch (NextToken().getKind()) { 341 case tok::kw_new: 342 ConsumeToken(); // 'operator' 343 ConsumeToken(); // 'new' 344 if (Tok.is(tok::l_square)) { 345 ConsumeBracket(); // '[' 346 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 347 Op = OO_Array_New; 348 } else { 349 Op = OO_New; 350 } 351 return &PP.getIdentifierTable().getOverloadedOperator(Op); 352 353 case tok::kw_delete: 354 ConsumeToken(); // 'operator' 355 ConsumeToken(); // 'delete' 356 if (Tok.is(tok::l_square)) { 357 ConsumeBracket(); // '[' 358 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 359 Op = OO_Array_Delete; 360 } else { 361 Op = OO_Delete; 362 } 363 return &PP.getIdentifierTable().getOverloadedOperator(Op); 364 365#define OVERLOADED_OPERATOR(Name,Spelling,Token) \ 366 case tok::Token: Op = OO_##Name; break; 367#define OVERLOADED_OPERATOR_MULTI(Name,Spelling) 368#include "clang/Basic/OperatorKinds.def" 369 370 case tok::l_paren: 371 ConsumeToken(); // 'operator' 372 ConsumeParen(); // '(' 373 ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')' 374 return &PP.getIdentifierTable().getOverloadedOperator(OO_Call); 375 376 case tok::l_square: 377 ConsumeToken(); // 'operator' 378 ConsumeBracket(); // '[' 379 ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' 380 return &PP.getIdentifierTable().getOverloadedOperator(OO_Subscript); 381 382 default: 383 break; 384 } 385 386 if (Op == OO_None) 387 return 0; 388 else { 389 ConsumeToken(); // 'operator' 390 ConsumeAnyToken(); // the operator itself 391 return &PP.getIdentifierTable().getOverloadedOperator(Op); 392 } 393} 394 395/// ParseConversionFunctionId - Parse a C++ conversion-function-id, 396/// which expresses the name of a user-defined conversion operator 397/// (C++ [class.conv.fct]p1). Returns the type that this operator is 398/// specifying a conversion for, or NULL if there was an error. 399/// 400/// conversion-function-id: [C++ 12.3.2] 401/// operator conversion-type-id 402/// 403/// conversion-type-id: 404/// type-specifier-seq conversion-declarator[opt] 405/// 406/// conversion-declarator: 407/// ptr-operator conversion-declarator[opt] 408Parser::TypeTy *Parser::ParseConversionFunctionId() { 409 assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); 410 ConsumeToken(); // 'operator' 411 412 // Parse the type-specifier-seq. 413 DeclSpec DS; 414 if (ParseCXXTypeSpecifierSeq(DS)) 415 return 0; 416 417 // Parse the conversion-declarator, which is merely a sequence of 418 // ptr-operators. 419 Declarator D(DS, Declarator::TypeNameContext); 420 ParseDeclaratorInternal(D, /*PtrOperator=*/true); 421 422 // Finish up the type. 423 Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D); 424 if (Result.isInvalid) 425 return 0; 426 else 427 return Result.Val; 428} 429