ExprCXX.cpp revision 1d954f6a0057cb55a3a5d483904a3c57d03c996f
1//===--- ExprCXX.cpp - (C++) Expression AST Node Implementation -----------===// 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 subclesses of Expr class declared in ExprCXX.h 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/Basic/IdentifierTable.h" 15#include "clang/AST/DeclCXX.h" 16#include "clang/AST/DeclTemplate.h" 17#include "clang/AST/ExprCXX.h" 18using namespace clang; 19 20//===----------------------------------------------------------------------===// 21// Child Iterators for iterating over subexpressions/substatements 22//===----------------------------------------------------------------------===// 23 24// CXXTypeidExpr - has child iterators if the operand is an expression 25Stmt::child_iterator CXXTypeidExpr::child_begin() { 26 return isTypeOperand() ? child_iterator() : &Operand.Ex; 27} 28Stmt::child_iterator CXXTypeidExpr::child_end() { 29 return isTypeOperand() ? child_iterator() : &Operand.Ex+1; 30} 31 32// CXXBoolLiteralExpr 33Stmt::child_iterator CXXBoolLiteralExpr::child_begin() { 34 return child_iterator(); 35} 36Stmt::child_iterator CXXBoolLiteralExpr::child_end() { 37 return child_iterator(); 38} 39 40// CXXNullPtrLiteralExpr 41Stmt::child_iterator CXXNullPtrLiteralExpr::child_begin() { 42 return child_iterator(); 43} 44Stmt::child_iterator CXXNullPtrLiteralExpr::child_end() { 45 return child_iterator(); 46} 47 48// CXXThisExpr 49Stmt::child_iterator CXXThisExpr::child_begin() { return child_iterator(); } 50Stmt::child_iterator CXXThisExpr::child_end() { return child_iterator(); } 51 52// CXXThrowExpr 53Stmt::child_iterator CXXThrowExpr::child_begin() { return &Op; } 54Stmt::child_iterator CXXThrowExpr::child_end() { 55 // If Op is 0, we are processing throw; which has no children. 56 return Op ? &Op+1 : &Op; 57} 58 59// CXXDefaultArgExpr 60Stmt::child_iterator CXXDefaultArgExpr::child_begin() { 61 return child_iterator(); 62} 63Stmt::child_iterator CXXDefaultArgExpr::child_end() { 64 return child_iterator(); 65} 66 67// CXXZeroInitValueExpr 68Stmt::child_iterator CXXZeroInitValueExpr::child_begin() { 69 return child_iterator(); 70} 71Stmt::child_iterator CXXZeroInitValueExpr::child_end() { 72 return child_iterator(); 73} 74 75// CXXConditionDeclExpr 76Stmt::child_iterator CXXConditionDeclExpr::child_begin() { 77 return getVarDecl(); 78} 79Stmt::child_iterator CXXConditionDeclExpr::child_end() { 80 return child_iterator(); 81} 82 83// CXXNewExpr 84CXXNewExpr::CXXNewExpr(bool globalNew, FunctionDecl *operatorNew, 85 Expr **placementArgs, unsigned numPlaceArgs, 86 bool parenTypeId, Expr *arraySize, 87 CXXConstructorDecl *constructor, bool initializer, 88 Expr **constructorArgs, unsigned numConsArgs, 89 FunctionDecl *operatorDelete, QualType ty, 90 SourceLocation startLoc, SourceLocation endLoc) 91 : Expr(CXXNewExprClass, ty, ty->isDependentType(), ty->isDependentType()), 92 GlobalNew(globalNew), ParenTypeId(parenTypeId), 93 Initializer(initializer), Array(arraySize), NumPlacementArgs(numPlaceArgs), 94 NumConstructorArgs(numConsArgs), OperatorNew(operatorNew), 95 OperatorDelete(operatorDelete), Constructor(constructor), 96 StartLoc(startLoc), EndLoc(endLoc) 97{ 98 unsigned TotalSize = Array + NumPlacementArgs + NumConstructorArgs; 99 SubExprs = new Stmt*[TotalSize]; 100 unsigned i = 0; 101 if (Array) 102 SubExprs[i++] = arraySize; 103 for (unsigned j = 0; j < NumPlacementArgs; ++j) 104 SubExprs[i++] = placementArgs[j]; 105 for (unsigned j = 0; j < NumConstructorArgs; ++j) 106 SubExprs[i++] = constructorArgs[j]; 107 assert(i == TotalSize); 108} 109 110Stmt::child_iterator CXXNewExpr::child_begin() { return &SubExprs[0]; } 111Stmt::child_iterator CXXNewExpr::child_end() { 112 return &SubExprs[0] + Array + getNumPlacementArgs() + getNumConstructorArgs(); 113} 114 115// CXXDeleteExpr 116Stmt::child_iterator CXXDeleteExpr::child_begin() { return &Argument; } 117Stmt::child_iterator CXXDeleteExpr::child_end() { return &Argument+1; } 118 119// UnresolvedFunctionNameExpr 120Stmt::child_iterator UnresolvedFunctionNameExpr::child_begin() { 121 return child_iterator(); 122} 123Stmt::child_iterator UnresolvedFunctionNameExpr::child_end() { 124 return child_iterator(); 125} 126// UnaryTypeTraitExpr 127Stmt::child_iterator UnaryTypeTraitExpr::child_begin() { 128 return child_iterator(); 129} 130Stmt::child_iterator UnaryTypeTraitExpr::child_end() { 131 return child_iterator(); 132} 133 134// UnresolvedDeclRefExpr 135StmtIterator UnresolvedDeclRefExpr::child_begin() { 136 return child_iterator(); 137} 138 139StmtIterator UnresolvedDeclRefExpr::child_end() { 140 return child_iterator(); 141} 142 143TemplateIdRefExpr::TemplateIdRefExpr(QualType T, 144 NestedNameSpecifier *Qualifier, 145 SourceRange QualifierRange, 146 TemplateName Template, 147 SourceLocation TemplateNameLoc, 148 SourceLocation LAngleLoc, 149 const TemplateArgument *TemplateArgs, 150 unsigned NumTemplateArgs, 151 SourceLocation RAngleLoc) 152 : Expr(TemplateIdRefExprClass, T, 153 (Template.isDependent() || 154 TemplateSpecializationType::anyDependentTemplateArguments( 155 TemplateArgs, NumTemplateArgs)), 156 (Template.isDependent() || 157 TemplateSpecializationType::anyDependentTemplateArguments( 158 TemplateArgs, NumTemplateArgs))), 159 Qualifier(Qualifier), QualifierRange(QualifierRange), Template(Template), 160 TemplateNameLoc(TemplateNameLoc), LAngleLoc(LAngleLoc), 161 RAngleLoc(RAngleLoc), NumTemplateArgs(NumTemplateArgs) 162 163{ 164 TemplateArgument *StoredTemplateArgs 165 = reinterpret_cast<TemplateArgument *> (this+1); 166 for (unsigned I = 0; I != NumTemplateArgs; ++I) 167 new (StoredTemplateArgs + I) TemplateArgument(TemplateArgs[I]); 168} 169 170TemplateIdRefExpr * 171TemplateIdRefExpr::Create(ASTContext &Context, QualType T, 172 NestedNameSpecifier *Qualifier, 173 SourceRange QualifierRange, 174 TemplateName Template, SourceLocation TemplateNameLoc, 175 SourceLocation LAngleLoc, 176 const TemplateArgument *TemplateArgs, 177 unsigned NumTemplateArgs, SourceLocation RAngleLoc) { 178 void *Mem = Context.Allocate(sizeof(TemplateIdRefExpr) + 179 sizeof(TemplateArgument) * NumTemplateArgs); 180 return new (Mem) TemplateIdRefExpr(T, Qualifier, QualifierRange, Template, 181 TemplateNameLoc, LAngleLoc, TemplateArgs, 182 NumTemplateArgs, RAngleLoc); 183} 184 185void TemplateIdRefExpr::DoDestroy(ASTContext &Context) { 186 const TemplateArgument *TemplateArgs = getTemplateArgs(); 187 for (unsigned I = 0; I != NumTemplateArgs; ++I) 188 if (Expr *E = TemplateArgs[I].getAsExpr()) 189 E->Destroy(Context); 190 this->~TemplateIdRefExpr(); 191 Context.Deallocate(this); 192} 193 194Stmt::child_iterator TemplateIdRefExpr::child_begin() { 195 // FIXME: Walk the expressions in the template arguments (?) 196 return Stmt::child_iterator(); 197} 198 199Stmt::child_iterator TemplateIdRefExpr::child_end() { 200 // FIXME: Walk the expressions in the template arguments (?) 201 return Stmt::child_iterator(); 202} 203 204bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const { 205 switch(UTT) { 206 default: assert(false && "Unknown type trait or not implemented"); 207 case UTT_IsPOD: return QueriedType->isPODType(); 208 case UTT_IsClass: // Fallthrough 209 case UTT_IsUnion: 210 if (const RecordType *Record = QueriedType->getAs<RecordType>()) { 211 bool Union = Record->getDecl()->isUnion(); 212 return UTT == UTT_IsUnion ? Union : !Union; 213 } 214 return false; 215 case UTT_IsEnum: return QueriedType->isEnumeralType(); 216 case UTT_IsPolymorphic: 217 if (const RecordType *Record = QueriedType->getAs<RecordType>()) { 218 // Type traits are only parsed in C++, so we've got CXXRecords. 219 return cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic(); 220 } 221 return false; 222 case UTT_IsAbstract: 223 if (const RecordType *RT = QueriedType->getAs<RecordType>()) 224 return cast<CXXRecordDecl>(RT->getDecl())->isAbstract(); 225 return false; 226 case UTT_IsEmpty: 227 if (const RecordType *Record = QueriedType->getAs<RecordType>()) { 228 return !Record->getDecl()->isUnion() 229 && cast<CXXRecordDecl>(Record->getDecl())->isEmpty(); 230 } 231 return false; 232 case UTT_HasTrivialConstructor: 233 // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: 234 // If __is_pod (type) is true then the trait is true, else if type is 235 // a cv class or union type (or array thereof) with a trivial default 236 // constructor ([class.ctor]) then the trait is true, else it is false. 237 if (QueriedType->isPODType()) 238 return true; 239 if (const RecordType *RT = 240 C.getBaseElementType(QueriedType)->getAs<RecordType>()) 241 return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialConstructor(); 242 return false; 243 case UTT_HasTrivialCopy: 244 // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: 245 // If __is_pod (type) is true or type is a reference type then 246 // the trait is true, else if type is a cv class or union type 247 // with a trivial copy constructor ([class.copy]) then the trait 248 // is true, else it is false. 249 if (QueriedType->isPODType() || QueriedType->isReferenceType()) 250 return true; 251 if (const RecordType *RT = QueriedType->getAs<RecordType>()) 252 return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyConstructor(); 253 return false; 254 case UTT_HasTrivialAssign: 255 // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: 256 // If type is const qualified or is a reference type then the 257 // trait is false. Otherwise if __is_pod (type) is true then the 258 // trait is true, else if type is a cv class or union type with 259 // a trivial copy assignment ([class.copy]) then the trait is 260 // true, else it is false. 261 // Note: the const and reference restrictions are interesting, 262 // given that const and reference members don't prevent a class 263 // from having a trivial copy assignment operator (but do cause 264 // errors if the copy assignment operator is actually used, q.v. 265 // [class.copy]p12). 266 267 if (C.getBaseElementType(QueriedType).isConstQualified()) 268 return false; 269 if (QueriedType->isPODType()) 270 return true; 271 if (const RecordType *RT = QueriedType->getAs<RecordType>()) 272 return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyAssignment(); 273 return false; 274 case UTT_HasTrivialDestructor: 275 // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: 276 // If __is_pod (type) is true or type is a reference type 277 // then the trait is true, else if type is a cv class or union 278 // type (or array thereof) with a trivial destructor 279 // ([class.dtor]) then the trait is true, else it is 280 // false. 281 if (QueriedType->isPODType() || QueriedType->isReferenceType()) 282 return true; 283 if (const RecordType *RT = 284 C.getBaseElementType(QueriedType)->getAs<RecordType>()) 285 return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor(); 286 return false; 287 } 288} 289 290SourceRange CXXOperatorCallExpr::getSourceRange() const { 291 OverloadedOperatorKind Kind = getOperator(); 292 if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) { 293 if (getNumArgs() == 1) 294 // Prefix operator 295 return SourceRange(getOperatorLoc(), 296 getArg(0)->getSourceRange().getEnd()); 297 else 298 // Postfix operator 299 return SourceRange(getArg(0)->getSourceRange().getEnd(), 300 getOperatorLoc()); 301 } else if (Kind == OO_Call) { 302 return SourceRange(getArg(0)->getSourceRange().getBegin(), getRParenLoc()); 303 } else if (Kind == OO_Subscript) { 304 return SourceRange(getArg(0)->getSourceRange().getBegin(), getRParenLoc()); 305 } else if (getNumArgs() == 1) { 306 return SourceRange(getOperatorLoc(), getArg(0)->getSourceRange().getEnd()); 307 } else if (getNumArgs() == 2) { 308 return SourceRange(getArg(0)->getSourceRange().getBegin(), 309 getArg(1)->getSourceRange().getEnd()); 310 } else { 311 return SourceRange(); 312 } 313} 314 315Expr *CXXMemberCallExpr::getImplicitObjectArgument() { 316 if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(getCallee()->IgnoreParens())) 317 return MemExpr->getBase(); 318 319 // FIXME: Will eventually need to cope with member pointers. 320 return 0; 321} 322 323//===----------------------------------------------------------------------===// 324// Named casts 325//===----------------------------------------------------------------------===// 326 327/// getCastName - Get the name of the C++ cast being used, e.g., 328/// "static_cast", "dynamic_cast", "reinterpret_cast", or 329/// "const_cast". The returned pointer must not be freed. 330const char *CXXNamedCastExpr::getCastName() const { 331 switch (getStmtClass()) { 332 case CXXStaticCastExprClass: return "static_cast"; 333 case CXXDynamicCastExprClass: return "dynamic_cast"; 334 case CXXReinterpretCastExprClass: return "reinterpret_cast"; 335 case CXXConstCastExprClass: return "const_cast"; 336 default: return "<invalid cast>"; 337 } 338} 339 340CXXTemporary *CXXTemporary::Create(ASTContext &C, 341 const CXXDestructorDecl *Destructor) { 342 return new (C) CXXTemporary(Destructor); 343} 344 345void CXXTemporary::Destroy(ASTContext &Ctx) { 346 this->~CXXTemporary(); 347 Ctx.Deallocate(this); 348} 349 350CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(ASTContext &C, 351 CXXTemporary *Temp, 352 Expr* SubExpr) { 353 assert(SubExpr->getType()->isRecordType() && 354 "Expression bound to a temporary must have record type!"); 355 356 return new (C) CXXBindTemporaryExpr(Temp, SubExpr); 357} 358 359void CXXBindTemporaryExpr::DoDestroy(ASTContext &C) { 360 Temp->Destroy(C); 361 this->~CXXBindTemporaryExpr(); 362 C.Deallocate(this); 363} 364 365CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C, 366 CXXConstructorDecl *Cons, 367 QualType writtenTy, 368 SourceLocation tyBeginLoc, 369 Expr **Args, 370 unsigned NumArgs, 371 SourceLocation rParenLoc) 372 : CXXConstructExpr(C, CXXTemporaryObjectExprClass, writtenTy, Cons, 373 false, Args, NumArgs), 374 TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) { 375} 376 377CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T, 378 CXXConstructorDecl *D, bool Elidable, 379 Expr **Args, unsigned NumArgs) { 380 return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, D, Elidable, 381 Args, NumArgs); 382} 383 384CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, 385 CXXConstructorDecl *D, bool elidable, 386 Expr **args, unsigned numargs) 387: Expr(SC, T, 388 T->isDependentType(), 389 (T->isDependentType() || 390 CallExpr::hasAnyValueDependentArguments(args, numargs))), 391 Constructor(D), Elidable(elidable), Args(0), NumArgs(numargs) { 392 // leave room for default arguments; 393 FunctionDecl *FDecl = cast<FunctionDecl>(D); 394 unsigned NumArgsInProto = FDecl->param_size(); 395 NumArgs += (NumArgsInProto - numargs); 396 if (NumArgs > 0) { 397 Args = new (C) Stmt*[NumArgs]; 398 for (unsigned i = 0; i < numargs; ++i) 399 Args[i] = args[i]; 400 } 401} 402 403void CXXConstructExpr::DoDestroy(ASTContext &C) { 404 DestroyChildren(C); 405 if (Args) 406 C.Deallocate(Args); 407 this->~CXXConstructExpr(); 408 C.Deallocate(this); 409} 410 411CXXExprWithTemporaries::CXXExprWithTemporaries(Expr *subexpr, 412 CXXTemporary **temps, 413 unsigned numtemps, 414 bool shoulddestroytemps) 415: Expr(CXXExprWithTemporariesClass, subexpr->getType(), 416 subexpr->isTypeDependent(), subexpr->isValueDependent()), 417 SubExpr(subexpr), Temps(0), NumTemps(numtemps), 418 ShouldDestroyTemps(shoulddestroytemps) { 419 if (NumTemps > 0) { 420 Temps = new CXXTemporary*[NumTemps]; 421 for (unsigned i = 0; i < NumTemps; ++i) 422 Temps[i] = temps[i]; 423 } 424} 425 426CXXExprWithTemporaries *CXXExprWithTemporaries::Create(ASTContext &C, 427 Expr *SubExpr, 428 CXXTemporary **Temps, 429 unsigned NumTemps, 430 bool ShouldDestroyTemps){ 431 return new (C) CXXExprWithTemporaries(SubExpr, Temps, NumTemps, 432 ShouldDestroyTemps); 433} 434 435void CXXExprWithTemporaries::DoDestroy(ASTContext &C) { 436 DestroyChildren(C); 437 this->~CXXExprWithTemporaries(); 438 C.Deallocate(this); 439} 440 441CXXExprWithTemporaries::~CXXExprWithTemporaries() { 442 delete[] Temps; 443} 444 445// CXXBindTemporaryExpr 446Stmt::child_iterator CXXBindTemporaryExpr::child_begin() { 447 return &SubExpr; 448} 449 450Stmt::child_iterator CXXBindTemporaryExpr::child_end() { 451 return &SubExpr + 1; 452} 453 454// CXXConstructExpr 455Stmt::child_iterator CXXConstructExpr::child_begin() { 456 return &Args[0]; 457} 458Stmt::child_iterator CXXConstructExpr::child_end() { 459 return &Args[0]+NumArgs; 460} 461 462// CXXExprWithTemporaries 463Stmt::child_iterator CXXExprWithTemporaries::child_begin() { 464 return &SubExpr; 465} 466 467Stmt::child_iterator CXXExprWithTemporaries::child_end() { 468 return &SubExpr + 1; 469} 470 471CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr( 472 SourceLocation TyBeginLoc, 473 QualType T, 474 SourceLocation LParenLoc, 475 Expr **Args, 476 unsigned NumArgs, 477 SourceLocation RParenLoc) 478 : Expr(CXXUnresolvedConstructExprClass, T.getNonReferenceType(), 479 T->isDependentType(), true), 480 TyBeginLoc(TyBeginLoc), 481 Type(T), 482 LParenLoc(LParenLoc), 483 RParenLoc(RParenLoc), 484 NumArgs(NumArgs) { 485 Stmt **StoredArgs = reinterpret_cast<Stmt **>(this + 1); 486 memcpy(StoredArgs, Args, sizeof(Expr *) * NumArgs); 487} 488 489CXXUnresolvedConstructExpr * 490CXXUnresolvedConstructExpr::Create(ASTContext &C, 491 SourceLocation TyBegin, 492 QualType T, 493 SourceLocation LParenLoc, 494 Expr **Args, 495 unsigned NumArgs, 496 SourceLocation RParenLoc) { 497 void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) + 498 sizeof(Expr *) * NumArgs); 499 return new (Mem) CXXUnresolvedConstructExpr(TyBegin, T, LParenLoc, 500 Args, NumArgs, RParenLoc); 501} 502 503Stmt::child_iterator CXXUnresolvedConstructExpr::child_begin() { 504 return child_iterator(reinterpret_cast<Stmt **>(this + 1)); 505} 506 507Stmt::child_iterator CXXUnresolvedConstructExpr::child_end() { 508 return child_iterator(reinterpret_cast<Stmt **>(this + 1) + NumArgs); 509} 510 511Stmt::child_iterator CXXUnresolvedMemberExpr::child_begin() { 512 return child_iterator(&Base); 513} 514 515Stmt::child_iterator CXXUnresolvedMemberExpr::child_end() { 516 return child_iterator(&Base + 1); 517} 518