diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp | 810 |
1 files changed, 810 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp new file mode 100644 index 0000000..d1a2b26 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/ExprCXX.cpp @@ -0,0 +1,810 @@ +//===--- ExprCXX.cpp - (C++) Expression AST Node Implementation -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the subclesses of Expr class declared in ExprCXX.h +// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/IdentifierTable.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/TypeLoc.h" +using namespace clang; + + +//===----------------------------------------------------------------------===// +// Child Iterators for iterating over subexpressions/substatements +//===----------------------------------------------------------------------===// + +QualType CXXTypeidExpr::getTypeOperand() const { + assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); + return Operand.get<TypeSourceInfo *>()->getType().getNonReferenceType() + .getUnqualifiedType(); +} + +// CXXTypeidExpr - has child iterators if the operand is an expression +Stmt::child_iterator CXXTypeidExpr::child_begin() { + return isTypeOperand() ? child_iterator() + : reinterpret_cast<Stmt **>(&Operand); +} +Stmt::child_iterator CXXTypeidExpr::child_end() { + return isTypeOperand() ? child_iterator() + : reinterpret_cast<Stmt **>(&Operand) + 1; +} + +// CXXBoolLiteralExpr +Stmt::child_iterator CXXBoolLiteralExpr::child_begin() { + return child_iterator(); +} +Stmt::child_iterator CXXBoolLiteralExpr::child_end() { + return child_iterator(); +} + +// CXXNullPtrLiteralExpr +Stmt::child_iterator CXXNullPtrLiteralExpr::child_begin() { + return child_iterator(); +} +Stmt::child_iterator CXXNullPtrLiteralExpr::child_end() { + return child_iterator(); +} + +// CXXThisExpr +Stmt::child_iterator CXXThisExpr::child_begin() { return child_iterator(); } +Stmt::child_iterator CXXThisExpr::child_end() { return child_iterator(); } + +// CXXThrowExpr +Stmt::child_iterator CXXThrowExpr::child_begin() { return &Op; } +Stmt::child_iterator CXXThrowExpr::child_end() { + // If Op is 0, we are processing throw; which has no children. + return Op ? &Op+1 : &Op; +} + +// CXXDefaultArgExpr +Stmt::child_iterator CXXDefaultArgExpr::child_begin() { + return child_iterator(); +} +Stmt::child_iterator CXXDefaultArgExpr::child_end() { + return child_iterator(); +} + +// CXXZeroInitValueExpr +Stmt::child_iterator CXXZeroInitValueExpr::child_begin() { + return child_iterator(); +} +Stmt::child_iterator CXXZeroInitValueExpr::child_end() { + return child_iterator(); +} + +// CXXNewExpr +CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, + Expr **placementArgs, unsigned numPlaceArgs, + bool parenTypeId, Expr *arraySize, + CXXConstructorDecl *constructor, bool initializer, + Expr **constructorArgs, unsigned numConsArgs, + FunctionDecl *operatorDelete, QualType ty, + SourceLocation startLoc, SourceLocation endLoc) + : Expr(CXXNewExprClass, ty, ty->isDependentType(), ty->isDependentType()), + GlobalNew(globalNew), ParenTypeId(parenTypeId), + Initializer(initializer), SubExprs(0), OperatorNew(operatorNew), + OperatorDelete(operatorDelete), Constructor(constructor), + StartLoc(startLoc), EndLoc(endLoc) { + + AllocateArgsArray(C, arraySize != 0, numPlaceArgs, numConsArgs); + unsigned i = 0; + if (Array) + SubExprs[i++] = arraySize; + for (unsigned j = 0; j < NumPlacementArgs; ++j) + SubExprs[i++] = placementArgs[j]; + for (unsigned j = 0; j < NumConstructorArgs; ++j) + SubExprs[i++] = constructorArgs[j]; +} + +void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray, + unsigned numPlaceArgs, unsigned numConsArgs){ + assert(SubExprs == 0 && "SubExprs already allocated"); + Array = isArray; + NumPlacementArgs = numPlaceArgs; + NumConstructorArgs = numConsArgs; + + unsigned TotalSize = Array + NumPlacementArgs + NumConstructorArgs; + SubExprs = new (C) Stmt*[TotalSize]; +} + + +void CXXNewExpr::DoDestroy(ASTContext &C) { + DestroyChildren(C); + if (SubExprs) + C.Deallocate(SubExprs); + this->~CXXNewExpr(); + C.Deallocate((void*)this); +} + +Stmt::child_iterator CXXNewExpr::child_begin() { return &SubExprs[0]; } +Stmt::child_iterator CXXNewExpr::child_end() { + return &SubExprs[0] + Array + getNumPlacementArgs() + getNumConstructorArgs(); +} + +// CXXDeleteExpr +Stmt::child_iterator CXXDeleteExpr::child_begin() { return &Argument; } +Stmt::child_iterator CXXDeleteExpr::child_end() { return &Argument+1; } + +// CXXPseudoDestructorExpr +Stmt::child_iterator CXXPseudoDestructorExpr::child_begin() { return &Base; } +Stmt::child_iterator CXXPseudoDestructorExpr::child_end() { + return &Base + 1; +} + +PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info) + : Type(Info) +{ + Location = Info->getTypeLoc().getLocalSourceRange().getBegin(); +} + +QualType CXXPseudoDestructorExpr::getDestroyedType() const { + if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo()) + return TInfo->getType(); + + return QualType(); +} + +SourceRange CXXPseudoDestructorExpr::getSourceRange() const { + SourceLocation End = DestroyedType.getLocation(); + if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo()) + End = TInfo->getTypeLoc().getLocalSourceRange().getEnd(); + return SourceRange(Base->getLocStart(), End); +} + + +// UnresolvedLookupExpr +UnresolvedLookupExpr * +UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent, + CXXRecordDecl *NamingClass, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, DeclarationName Name, + SourceLocation NameLoc, bool ADL, + const TemplateArgumentListInfo &Args, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) +{ + void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) + + ExplicitTemplateArgumentList::sizeFor(Args)); + UnresolvedLookupExpr *ULE + = new (Mem) UnresolvedLookupExpr(C, + Dependent ? C.DependentTy : C.OverloadTy, + Dependent, NamingClass, + Qualifier, QualifierRange, + Name, NameLoc, ADL, + /*Overload*/ true, + /*ExplicitTemplateArgs*/ true, + Begin, End); + + reinterpret_cast<ExplicitTemplateArgumentList*>(ULE+1)->initializeFrom(Args); + + return ULE; +} + +OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, QualType T, + bool Dependent, NestedNameSpecifier *Qualifier, + SourceRange QRange, DeclarationName Name, + SourceLocation NameLoc, bool HasTemplateArgs, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) + : Expr(K, T, Dependent, Dependent), + Results(0), NumResults(End - Begin), Name(Name), Qualifier(Qualifier), + QualifierRange(QRange), NameLoc(NameLoc), + HasExplicitTemplateArgs(HasTemplateArgs) +{ + if (NumResults) { + Results = static_cast<DeclAccessPair *>( + C.Allocate(sizeof(DeclAccessPair) * NumResults, + llvm::alignof<DeclAccessPair>())); + memcpy(Results, &*Begin.getIterator(), + (End - Begin) * sizeof(DeclAccessPair)); + } +} + +bool OverloadExpr::ComputeDependence(UnresolvedSetIterator Begin, + UnresolvedSetIterator End, + const TemplateArgumentListInfo *Args) { + for (UnresolvedSetImpl::const_iterator I = Begin; I != End; ++I) + if ((*I)->getDeclContext()->isDependentContext()) + return true; + + if (Args && TemplateSpecializationType::anyDependentTemplateArguments(*Args)) + return true; + + return false; +} + +CXXRecordDecl *OverloadExpr::getNamingClass() const { + if (isa<UnresolvedLookupExpr>(this)) + return cast<UnresolvedLookupExpr>(this)->getNamingClass(); + else + return cast<UnresolvedMemberExpr>(this)->getNamingClass(); +} + +Stmt::child_iterator UnresolvedLookupExpr::child_begin() { + return child_iterator(); +} +Stmt::child_iterator UnresolvedLookupExpr::child_end() { + return child_iterator(); +} +// UnaryTypeTraitExpr +Stmt::child_iterator UnaryTypeTraitExpr::child_begin() { + return child_iterator(); +} +Stmt::child_iterator UnaryTypeTraitExpr::child_end() { + return child_iterator(); +} + +// DependentScopeDeclRefExpr +DependentScopeDeclRefExpr * +DependentScopeDeclRefExpr::Create(ASTContext &C, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *Args) { + std::size_t size = sizeof(DependentScopeDeclRefExpr); + if (Args) size += ExplicitTemplateArgumentList::sizeFor(*Args); + void *Mem = C.Allocate(size); + + DependentScopeDeclRefExpr *DRE + = new (Mem) DependentScopeDeclRefExpr(C.DependentTy, + Qualifier, QualifierRange, + Name, NameLoc, + Args != 0); + + if (Args) + reinterpret_cast<ExplicitTemplateArgumentList*>(DRE+1) + ->initializeFrom(*Args); + + return DRE; +} + +StmtIterator DependentScopeDeclRefExpr::child_begin() { + return child_iterator(); +} + +StmtIterator DependentScopeDeclRefExpr::child_end() { + return child_iterator(); +} + +bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const { + switch(UTT) { + default: assert(false && "Unknown type trait or not implemented"); + case UTT_IsPOD: return QueriedType->isPODType(); + case UTT_IsLiteral: return QueriedType->isLiteralType(); + case UTT_IsClass: // Fallthrough + case UTT_IsUnion: + if (const RecordType *Record = QueriedType->getAs<RecordType>()) { + bool Union = Record->getDecl()->isUnion(); + return UTT == UTT_IsUnion ? Union : !Union; + } + return false; + case UTT_IsEnum: return QueriedType->isEnumeralType(); + case UTT_IsPolymorphic: + if (const RecordType *Record = QueriedType->getAs<RecordType>()) { + // Type traits are only parsed in C++, so we've got CXXRecords. + return cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic(); + } + return false; + case UTT_IsAbstract: + if (const RecordType *RT = QueriedType->getAs<RecordType>()) + return cast<CXXRecordDecl>(RT->getDecl())->isAbstract(); + return false; + case UTT_IsEmpty: + if (const RecordType *Record = QueriedType->getAs<RecordType>()) { + return !Record->getDecl()->isUnion() + && cast<CXXRecordDecl>(Record->getDecl())->isEmpty(); + } + return false; + case UTT_HasTrivialConstructor: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If __is_pod (type) is true then the trait is true, else if type is + // a cv class or union type (or array thereof) with a trivial default + // constructor ([class.ctor]) then the trait is true, else it is false. + if (QueriedType->isPODType()) + return true; + if (const RecordType *RT = + C.getBaseElementType(QueriedType)->getAs<RecordType>()) + return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialConstructor(); + return false; + case UTT_HasTrivialCopy: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If __is_pod (type) is true or type is a reference type then + // the trait is true, else if type is a cv class or union type + // with a trivial copy constructor ([class.copy]) then the trait + // is true, else it is false. + if (QueriedType->isPODType() || QueriedType->isReferenceType()) + return true; + if (const RecordType *RT = QueriedType->getAs<RecordType>()) + return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyConstructor(); + return false; + case UTT_HasTrivialAssign: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If type is const qualified or is a reference type then the + // trait is false. Otherwise if __is_pod (type) is true then the + // trait is true, else if type is a cv class or union type with + // a trivial copy assignment ([class.copy]) then the trait is + // true, else it is false. + // Note: the const and reference restrictions are interesting, + // given that const and reference members don't prevent a class + // from having a trivial copy assignment operator (but do cause + // errors if the copy assignment operator is actually used, q.v. + // [class.copy]p12). + + if (C.getBaseElementType(QueriedType).isConstQualified()) + return false; + if (QueriedType->isPODType()) + return true; + if (const RecordType *RT = QueriedType->getAs<RecordType>()) + return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyAssignment(); + return false; + case UTT_HasTrivialDestructor: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If __is_pod (type) is true or type is a reference type + // then the trait is true, else if type is a cv class or union + // type (or array thereof) with a trivial destructor + // ([class.dtor]) then the trait is true, else it is + // false. + if (QueriedType->isPODType() || QueriedType->isReferenceType()) + return true; + if (const RecordType *RT = + C.getBaseElementType(QueriedType)->getAs<RecordType>()) + return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor(); + return false; + } +} + +SourceRange CXXConstructExpr::getSourceRange() const { + // FIXME: Should we know where the parentheses are, if there are any? + for (std::reverse_iterator<Stmt**> I(&Args[NumArgs]), E(&Args[0]); I!=E;++I) { + // Ignore CXXDefaultExprs when computing the range, as they don't + // have a range. + if (!isa<CXXDefaultArgExpr>(*I)) + return SourceRange(Loc, (*I)->getLocEnd()); + } + + return SourceRange(Loc); +} + +SourceRange CXXOperatorCallExpr::getSourceRange() const { + OverloadedOperatorKind Kind = getOperator(); + if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) { + if (getNumArgs() == 1) + // Prefix operator + return SourceRange(getOperatorLoc(), + getArg(0)->getSourceRange().getEnd()); + else + // Postfix operator + return SourceRange(getArg(0)->getSourceRange().getEnd(), + getOperatorLoc()); + } else if (Kind == OO_Call) { + return SourceRange(getArg(0)->getSourceRange().getBegin(), getRParenLoc()); + } else if (Kind == OO_Subscript) { + return SourceRange(getArg(0)->getSourceRange().getBegin(), getRParenLoc()); + } else if (getNumArgs() == 1) { + return SourceRange(getOperatorLoc(), getArg(0)->getSourceRange().getEnd()); + } else if (getNumArgs() == 2) { + return SourceRange(getArg(0)->getSourceRange().getBegin(), + getArg(1)->getSourceRange().getEnd()); + } else { + return SourceRange(); + } +} + +Expr *CXXMemberCallExpr::getImplicitObjectArgument() { + if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(getCallee()->IgnoreParens())) + return MemExpr->getBase(); + + // FIXME: Will eventually need to cope with member pointers. + return 0; +} + +SourceRange CXXMemberCallExpr::getSourceRange() const { + SourceLocation LocStart = getCallee()->getLocStart(); + if (LocStart.isInvalid() && getNumArgs() > 0) + LocStart = getArg(0)->getLocStart(); + return SourceRange(LocStart, getRParenLoc()); +} + + +//===----------------------------------------------------------------------===// +// Named casts +//===----------------------------------------------------------------------===// + +/// getCastName - Get the name of the C++ cast being used, e.g., +/// "static_cast", "dynamic_cast", "reinterpret_cast", or +/// "const_cast". The returned pointer must not be freed. +const char *CXXNamedCastExpr::getCastName() const { + switch (getStmtClass()) { + case CXXStaticCastExprClass: return "static_cast"; + case CXXDynamicCastExprClass: return "dynamic_cast"; + case CXXReinterpretCastExprClass: return "reinterpret_cast"; + case CXXConstCastExprClass: return "const_cast"; + default: return "<invalid cast>"; + } +} + +CXXDefaultArgExpr * +CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc, + ParmVarDecl *Param, Expr *SubExpr) { + void *Mem = C.Allocate(sizeof(CXXDefaultArgExpr) + sizeof(Stmt *)); + return new (Mem) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param, + SubExpr); +} + +void CXXDefaultArgExpr::DoDestroy(ASTContext &C) { + if (Param.getInt()) + getExpr()->Destroy(C); + this->~CXXDefaultArgExpr(); + C.Deallocate(this); +} + +CXXTemporary *CXXTemporary::Create(ASTContext &C, + const CXXDestructorDecl *Destructor) { + return new (C) CXXTemporary(Destructor); +} + +void CXXTemporary::Destroy(ASTContext &Ctx) { + this->~CXXTemporary(); + Ctx.Deallocate(this); +} + +CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(ASTContext &C, + CXXTemporary *Temp, + Expr* SubExpr) { + assert(SubExpr->getType()->isRecordType() && + "Expression bound to a temporary must have record type!"); + + return new (C) CXXBindTemporaryExpr(Temp, SubExpr); +} + +void CXXBindTemporaryExpr::DoDestroy(ASTContext &C) { + Temp->Destroy(C); + this->~CXXBindTemporaryExpr(); + C.Deallocate(this); +} + +CXXBindReferenceExpr *CXXBindReferenceExpr::Create(ASTContext &C, Expr *SubExpr, + bool ExtendsLifetime, + bool RequiresTemporaryCopy) { + return new (C) CXXBindReferenceExpr(SubExpr, + ExtendsLifetime, + RequiresTemporaryCopy); +} + +void CXXBindReferenceExpr::DoDestroy(ASTContext &C) { + this->~CXXBindReferenceExpr(); + C.Deallocate(this); +} + +CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C, + CXXConstructorDecl *Cons, + QualType writtenTy, + SourceLocation tyBeginLoc, + Expr **Args, + unsigned NumArgs, + SourceLocation rParenLoc, + bool ZeroInitialization) + : CXXConstructExpr(C, CXXTemporaryObjectExprClass, writtenTy, tyBeginLoc, + Cons, false, Args, NumArgs, ZeroInitialization), + TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) { +} + +CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T, + SourceLocation Loc, + CXXConstructorDecl *D, bool Elidable, + Expr **Args, unsigned NumArgs, + bool ZeroInitialization, + ConstructionKind ConstructKind) { + return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, + Elidable, Args, NumArgs, ZeroInitialization, + ConstructKind); +} + +CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, + SourceLocation Loc, + CXXConstructorDecl *D, bool elidable, + Expr **args, unsigned numargs, + bool ZeroInitialization, + ConstructionKind ConstructKind) +: Expr(SC, T, + T->isDependentType(), + (T->isDependentType() || + CallExpr::hasAnyValueDependentArguments(args, numargs))), + Constructor(D), Loc(Loc), Elidable(elidable), + ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind), + Args(0), NumArgs(numargs) +{ + if (NumArgs) { + Args = new (C) Stmt*[NumArgs]; + + for (unsigned i = 0; i != NumArgs; ++i) { + assert(args[i] && "NULL argument in CXXConstructExpr"); + Args[i] = args[i]; + } + } +} + +CXXConstructExpr::CXXConstructExpr(EmptyShell Empty, ASTContext &C, + unsigned numargs) + : Expr(CXXConstructExprClass, Empty), Args(0), NumArgs(numargs) +{ + if (NumArgs) + Args = new (C) Stmt*[NumArgs]; +} + +void CXXConstructExpr::DoDestroy(ASTContext &C) { + DestroyChildren(C); + if (Args) + C.Deallocate(Args); + this->~CXXConstructExpr(); + C.Deallocate(this); +} + +CXXExprWithTemporaries::CXXExprWithTemporaries(ASTContext &C, + Expr *subexpr, + CXXTemporary **temps, + unsigned numtemps) + : Expr(CXXExprWithTemporariesClass, subexpr->getType(), + subexpr->isTypeDependent(), subexpr->isValueDependent()), + SubExpr(subexpr), Temps(0), NumTemps(0) { + if (numtemps) { + setNumTemporaries(C, numtemps); + for (unsigned i = 0; i != numtemps; ++i) + Temps[i] = temps[i]; + } +} + +void CXXExprWithTemporaries::setNumTemporaries(ASTContext &C, unsigned N) { + assert(Temps == 0 && "Cannot resize with this"); + NumTemps = N; + Temps = new (C) CXXTemporary*[NumTemps]; +} + + +CXXExprWithTemporaries *CXXExprWithTemporaries::Create(ASTContext &C, + Expr *SubExpr, + CXXTemporary **Temps, + unsigned NumTemps) { + return new (C) CXXExprWithTemporaries(C, SubExpr, Temps, NumTemps); +} + +void CXXExprWithTemporaries::DoDestroy(ASTContext &C) { + DestroyChildren(C); + if (Temps) + C.Deallocate(Temps); + this->~CXXExprWithTemporaries(); + C.Deallocate(this); +} + +CXXExprWithTemporaries::~CXXExprWithTemporaries() {} + +// CXXBindTemporaryExpr +Stmt::child_iterator CXXBindTemporaryExpr::child_begin() { + return &SubExpr; +} + +Stmt::child_iterator CXXBindTemporaryExpr::child_end() { + return &SubExpr + 1; +} + +// CXXBindReferenceExpr +Stmt::child_iterator CXXBindReferenceExpr::child_begin() { + return &SubExpr; +} + +Stmt::child_iterator CXXBindReferenceExpr::child_end() { + return &SubExpr + 1; +} + +// CXXConstructExpr +Stmt::child_iterator CXXConstructExpr::child_begin() { + return &Args[0]; +} +Stmt::child_iterator CXXConstructExpr::child_end() { + return &Args[0]+NumArgs; +} + +// CXXExprWithTemporaries +Stmt::child_iterator CXXExprWithTemporaries::child_begin() { + return &SubExpr; +} + +Stmt::child_iterator CXXExprWithTemporaries::child_end() { + return &SubExpr + 1; +} + +CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr( + SourceLocation TyBeginLoc, + QualType T, + SourceLocation LParenLoc, + Expr **Args, + unsigned NumArgs, + SourceLocation RParenLoc) + : Expr(CXXUnresolvedConstructExprClass, T.getNonReferenceType(), + T->isDependentType(), true), + TyBeginLoc(TyBeginLoc), + Type(T), + LParenLoc(LParenLoc), + RParenLoc(RParenLoc), + NumArgs(NumArgs) { + Stmt **StoredArgs = reinterpret_cast<Stmt **>(this + 1); + memcpy(StoredArgs, Args, sizeof(Expr *) * NumArgs); +} + +CXXUnresolvedConstructExpr * +CXXUnresolvedConstructExpr::Create(ASTContext &C, + SourceLocation TyBegin, + QualType T, + SourceLocation LParenLoc, + Expr **Args, + unsigned NumArgs, + SourceLocation RParenLoc) { + void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) + + sizeof(Expr *) * NumArgs); + return new (Mem) CXXUnresolvedConstructExpr(TyBegin, T, LParenLoc, + Args, NumArgs, RParenLoc); +} + +Stmt::child_iterator CXXUnresolvedConstructExpr::child_begin() { + return child_iterator(reinterpret_cast<Stmt **>(this + 1)); +} + +Stmt::child_iterator CXXUnresolvedConstructExpr::child_end() { + return child_iterator(reinterpret_cast<Stmt **>(this + 1) + NumArgs); +} + +CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, + Expr *Base, QualType BaseType, + bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *FirstQualifierFoundInScope, + DeclarationName Member, + SourceLocation MemberLoc, + const TemplateArgumentListInfo *TemplateArgs) + : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true), + Base(Base), BaseType(BaseType), IsArrow(IsArrow), + HasExplicitTemplateArgs(TemplateArgs != 0), + OperatorLoc(OperatorLoc), + Qualifier(Qualifier), QualifierRange(QualifierRange), + FirstQualifierFoundInScope(FirstQualifierFoundInScope), + Member(Member), MemberLoc(MemberLoc) { + if (TemplateArgs) + getExplicitTemplateArgumentList()->initializeFrom(*TemplateArgs); +} + +CXXDependentScopeMemberExpr * +CXXDependentScopeMemberExpr::Create(ASTContext &C, + Expr *Base, QualType BaseType, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *FirstQualifierFoundInScope, + DeclarationName Member, + SourceLocation MemberLoc, + const TemplateArgumentListInfo *TemplateArgs) { + if (!TemplateArgs) + return new (C) CXXDependentScopeMemberExpr(C, Base, BaseType, + IsArrow, OperatorLoc, + Qualifier, QualifierRange, + FirstQualifierFoundInScope, + Member, MemberLoc); + + std::size_t size = sizeof(CXXDependentScopeMemberExpr); + if (TemplateArgs) + size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); + + void *Mem = C.Allocate(size, llvm::alignof<CXXDependentScopeMemberExpr>()); + return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType, + IsArrow, OperatorLoc, + Qualifier, QualifierRange, + FirstQualifierFoundInScope, + Member, MemberLoc, TemplateArgs); +} + +Stmt::child_iterator CXXDependentScopeMemberExpr::child_begin() { + return child_iterator(&Base); +} + +Stmt::child_iterator CXXDependentScopeMemberExpr::child_end() { + if (isImplicitAccess()) + return child_iterator(&Base); + return child_iterator(&Base + 1); +} + +UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, QualType T, + bool Dependent, + bool HasUnresolvedUsing, + Expr *Base, QualType BaseType, + bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName MemberName, + SourceLocation MemberLoc, + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) + : OverloadExpr(UnresolvedMemberExprClass, C, T, Dependent, + Qualifier, QualifierRange, MemberName, MemberLoc, + TemplateArgs != 0, Begin, End), + IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing), + Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) { + if (TemplateArgs) + getExplicitTemplateArgs().initializeFrom(*TemplateArgs); +} + +UnresolvedMemberExpr * +UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent, + bool HasUnresolvedUsing, + Expr *Base, QualType BaseType, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + DeclarationName Member, + SourceLocation MemberLoc, + const TemplateArgumentListInfo *TemplateArgs, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) { + std::size_t size = sizeof(UnresolvedMemberExpr); + if (TemplateArgs) + size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); + + void *Mem = C.Allocate(size, llvm::alignof<UnresolvedMemberExpr>()); + return new (Mem) UnresolvedMemberExpr(C, + Dependent ? C.DependentTy : C.OverloadTy, + Dependent, HasUnresolvedUsing, Base, BaseType, + IsArrow, OperatorLoc, Qualifier, QualifierRange, + Member, MemberLoc, TemplateArgs, Begin, End); +} + +CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const { + // Unlike for UnresolvedLookupExpr, it is very easy to re-derive this. + + // If there was a nested name specifier, it names the naming class. + // It can't be dependent: after all, we were actually able to do the + // lookup. + CXXRecordDecl *Record = 0; + if (getQualifier()) { + Type *T = getQualifier()->getAsType(); + assert(T && "qualifier in member expression does not name type"); + Record = T->getAsCXXRecordDecl(); + assert(Record && "qualifier in member expression does not name record"); + } + // Otherwise the naming class must have been the base class. + else { + QualType BaseType = getBaseType().getNonReferenceType(); + if (isArrow()) { + const PointerType *PT = BaseType->getAs<PointerType>(); + assert(PT && "base of arrow member access is not pointer"); + BaseType = PT->getPointeeType(); + } + + Record = BaseType->getAsCXXRecordDecl(); + assert(Record && "base of member expression does not name record"); + } + + return Record; +} + +Stmt::child_iterator UnresolvedMemberExpr::child_begin() { + return child_iterator(&Base); +} + +Stmt::child_iterator UnresolvedMemberExpr::child_end() { + if (isImplicitAccess()) + return child_iterator(&Base); + return child_iterator(&Base + 1); +} |