diff options
author | John McCall <rjmccall@apple.com> | 2011-01-27 09:37:56 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-01-27 09:37:56 +0000 |
commit | 6ec278d1a354517e20f13a877481453ee7940c78 (patch) | |
tree | fad4d032592f9dbebc24c2fb8de1aed6149b950e /lib/CodeGen | |
parent | d0370f59e79702ac908c81bf556519f91e9ca297 (diff) |
Do a proper recursive lookup when deciding whether a class's usual
deallocation function has a two-argument form. Store the result of this
check in new[] and delete[] nodes.
Fixes rdar://problem/8913519
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124373 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXXABI.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CGCXXABI.h | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 11 | ||||
-rw-r--r-- | lib/CodeGen/ItaniumCXXABI.cpp | 101 |
4 files changed, 59 insertions, 63 deletions
diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp index 627df43a28..7fb1ffde2d 100644 --- a/lib/CodeGen/CGCXXABI.cpp +++ b/lib/CodeGen/CGCXXABI.cpp @@ -142,13 +142,14 @@ void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, CGF.EmitReturnOfRValue(RV, ResultType); } -CharUnits CGCXXABI::GetArrayCookieSize(QualType ElementType) { +CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { return CharUnits::Zero(); } llvm::Value *CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, llvm::Value *NewPtr, llvm::Value *NumElements, + const CXXNewExpr *expr, QualType ElementType) { // Should never be called. ErrorUnsupportedABI(CGF, "array cookie initialization"); @@ -156,7 +157,8 @@ llvm::Value *CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, } void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, - QualType ElementType, llvm::Value *&NumElements, + const CXXDeleteExpr *expr, QualType ElementType, + llvm::Value *&NumElements, llvm::Value *&AllocPtr, CharUnits &CookieSize) { ErrorUnsupportedABI(CGF, "array cookie reading"); diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index 8bc1385d7f..547f98ac21 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -189,7 +189,7 @@ public: /// /// \param ElementType - the allocated type of the expression, /// i.e. the pointee type of the expression result type - virtual CharUnits GetArrayCookieSize(QualType ElementType); + virtual CharUnits GetArrayCookieSize(const CXXNewExpr *expr); /// Initialize the array cookie for the given allocation. /// @@ -202,6 +202,7 @@ public: virtual llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, llvm::Value *NewPtr, llvm::Value *NumElements, + const CXXNewExpr *expr, QualType ElementType); /// Reads the array cookie associated with the given pointer, @@ -218,6 +219,7 @@ public: /// \param CookieSize - an out parameter which will be initialized /// with the size of the cookie, or zero if there is no cookie virtual void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, + const CXXDeleteExpr *expr, QualType ElementType, llvm::Value *&NumElements, llvm::Value *&AllocPtr, CharUnits &CookieSize); diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 7177a64e74..4f1d1764dc 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -395,7 +395,7 @@ static CharUnits CalculateCookiePadding(CodeGenFunction &CGF, if (IsPlacementOperatorNewArray(CGF.getContext(), OperatorNew)) return CharUnits::Zero(); - return CGF.CGM.getCXXABI().GetArrayCookieSize(E->getAllocatedType()); + return CGF.CGM.getCXXABI().GetArrayCookieSize(E); } static llvm::Value *EmitCXXNewAllocSize(ASTContext &Context, @@ -1065,7 +1065,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { if (AllocSize != AllocSizeWithoutCookie) { assert(E->isArray()); NewPtr = CGM.getCXXABI().InitializeArrayCookie(CGF, NewPtr, NumElements, - AllocType); + E, AllocType); } // If there's an operator delete, enter a cleanup to call it if an @@ -1271,18 +1271,19 @@ namespace { /// Emit the code for deleting an array of objects. static void EmitArrayDelete(CodeGenFunction &CGF, - const FunctionDecl *OperatorDelete, + const CXXDeleteExpr *E, llvm::Value *Ptr, QualType ElementType) { llvm::Value *NumElements = 0; llvm::Value *AllocatedPtr = 0; CharUnits CookieSize; - CGF.CGM.getCXXABI().ReadArrayCookie(CGF, Ptr, ElementType, + CGF.CGM.getCXXABI().ReadArrayCookie(CGF, Ptr, E, ElementType, NumElements, AllocatedPtr, CookieSize); assert(AllocatedPtr && "ReadArrayCookie didn't set AllocatedPtr"); // Make sure that we call delete even if one of the dtors throws. + const FunctionDecl *OperatorDelete = E->getOperatorDelete(); CGF.EHStack.pushCleanup<CallArrayDelete>(NormalAndEHCleanup, AllocatedPtr, OperatorDelete, NumElements, ElementType, @@ -1352,7 +1353,7 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { cast<llvm::PointerType>(Ptr->getType())->getElementType()); if (E->isArrayForm()) { - EmitArrayDelete(*this, E->getOperatorDelete(), Ptr, DeleteTy); + EmitArrayDelete(*this, E, Ptr, DeleteTy); } else { EmitObjectDelete(*this, E->getOperatorDelete(), Ptr, DeleteTy); } diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index edc03b1bd1..ef5455c286 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -47,7 +47,9 @@ protected: return PtrDiffTy; } - bool NeedsArrayCookie(QualType ElementType); + bool NeedsArrayCookie(const CXXNewExpr *expr); + bool NeedsArrayCookie(const CXXDeleteExpr *expr, + QualType elementType); public: ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) : @@ -105,12 +107,14 @@ public: void EmitInstanceFunctionProlog(CodeGenFunction &CGF); - CharUnits GetArrayCookieSize(QualType ElementType); + CharUnits GetArrayCookieSize(const CXXNewExpr *expr); llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, llvm::Value *NewPtr, llvm::Value *NumElements, + const CXXNewExpr *expr, QualType ElementType); void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, + const CXXDeleteExpr *expr, QualType ElementType, llvm::Value *&NumElements, llvm::Value *&AllocPtr, CharUnits &CookieSize); @@ -140,12 +144,14 @@ public: void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy); - CharUnits GetArrayCookieSize(QualType ElementType); + CharUnits GetArrayCookieSize(const CXXNewExpr *expr); llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, llvm::Value *NewPtr, llvm::Value *NumElements, + const CXXNewExpr *expr, QualType ElementType); void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, + const CXXDeleteExpr *expr, QualType ElementType, llvm::Value *&NumElements, llvm::Value *&AllocPtr, CharUnits &CookieSize); @@ -794,67 +800,49 @@ void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, /************************** Array allocation cookies **************************/ -bool ItaniumCXXABI::NeedsArrayCookie(QualType ElementType) { - ElementType = getContext().getBaseElementType(ElementType); - const RecordType *RT = ElementType->getAs<RecordType>(); - if (!RT) return false; - - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - - // If the class has a non-trivial destructor, it always needs a cookie. - if (!RD->hasTrivialDestructor()) return true; +bool ItaniumCXXABI::NeedsArrayCookie(const CXXNewExpr *expr) { + // If the class's usual deallocation function takes two arguments, + // it needs a cookie. + if (expr->doesUsualArrayDeleteWantSize()) + return true; + + // Otherwise, if the class has a non-trivial destructor, it always + // needs a cookie. + const CXXRecordDecl *record = + expr->getAllocatedType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + return (record && !record->hasTrivialDestructor()); +} +bool ItaniumCXXABI::NeedsArrayCookie(const CXXDeleteExpr *expr, + QualType elementType) { // If the class's usual deallocation function takes two arguments, - // it needs a cookie. Otherwise we don't need a cookie. - const CXXMethodDecl *UsualDeallocationFunction = 0; - - // Usual deallocation functions of this form are always found on the - // class. - // - // FIXME: what exactly is this code supposed to do if there's an - // ambiguity? That's possible with using declarations. - DeclarationName OpName = - getContext().DeclarationNames.getCXXOperatorName(OO_Array_Delete); - DeclContext::lookup_const_iterator Op, OpEnd; - for (llvm::tie(Op, OpEnd) = RD->lookup(OpName); Op != OpEnd; ++Op) { - const CXXMethodDecl *Delete = - cast<CXXMethodDecl>((*Op)->getUnderlyingDecl()); - - if (Delete->isUsualDeallocationFunction()) { - UsualDeallocationFunction = Delete; - break; - } - } - - // No usual deallocation function, we don't need a cookie. - if (!UsualDeallocationFunction) - return false; - - // The usual deallocation function doesn't take a size_t argument, - // so we don't need a cookie. - if (UsualDeallocationFunction->getNumParams() == 1) - return false; - - assert(UsualDeallocationFunction->getNumParams() == 2 && - "Unexpected deallocation function type!"); - return true; + // it needs a cookie. + if (expr->doesUsualArrayDeleteWantSize()) + return true; + + // Otherwise, if the class has a non-trivial destructor, it always + // needs a cookie. + const CXXRecordDecl *record = + elementType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + return (record && !record->hasTrivialDestructor()); } -CharUnits ItaniumCXXABI::GetArrayCookieSize(QualType ElementType) { - if (!NeedsArrayCookie(ElementType)) +CharUnits ItaniumCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { + if (!NeedsArrayCookie(expr)) return CharUnits::Zero(); - // Padding is the maximum of sizeof(size_t) and alignof(ElementType) + // Padding is the maximum of sizeof(size_t) and alignof(elementType) ASTContext &Ctx = getContext(); return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()), - Ctx.getTypeAlignInChars(ElementType)); + Ctx.getTypeAlignInChars(expr->getAllocatedType())); } llvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, llvm::Value *NewPtr, llvm::Value *NumElements, + const CXXNewExpr *expr, QualType ElementType) { - assert(NeedsArrayCookie(ElementType)); + assert(NeedsArrayCookie(expr)); unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace(); @@ -887,6 +875,7 @@ llvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, void ItaniumCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, + const CXXDeleteExpr *expr, QualType ElementType, llvm::Value *&NumElements, llvm::Value *&AllocPtr, @@ -896,7 +885,7 @@ void ItaniumCXXABI::ReadArrayCookie(CodeGenFunction &CGF, const llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS); // If we don't need an array cookie, bail out early. - if (!NeedsArrayCookie(ElementType)) { + if (!NeedsArrayCookie(expr, ElementType)) { AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); NumElements = 0; CookieSize = CharUnits::Zero(); @@ -927,8 +916,8 @@ void ItaniumCXXABI::ReadArrayCookie(CodeGenFunction &CGF, NumElements = CGF.Builder.CreateLoad(NumElementsPtr); } -CharUnits ARMCXXABI::GetArrayCookieSize(QualType ElementType) { - if (!NeedsArrayCookie(ElementType)) +CharUnits ARMCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { + if (!NeedsArrayCookie(expr)) return CharUnits::Zero(); // On ARM, the cookie is always: @@ -944,8 +933,9 @@ CharUnits ARMCXXABI::GetArrayCookieSize(QualType ElementType) { llvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, llvm::Value *NewPtr, llvm::Value *NumElements, + const CXXNewExpr *expr, QualType ElementType) { - assert(NeedsArrayCookie(ElementType)); + assert(NeedsArrayCookie(expr)); // NewPtr is a char*. @@ -978,6 +968,7 @@ llvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, void ARMCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, + const CXXDeleteExpr *expr, QualType ElementType, llvm::Value *&NumElements, llvm::Value *&AllocPtr, @@ -987,7 +978,7 @@ void ARMCXXABI::ReadArrayCookie(CodeGenFunction &CGF, const llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS); // If we don't need an array cookie, bail out early. - if (!NeedsArrayCookie(ElementType)) { + if (!NeedsArrayCookie(expr, ElementType)) { AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); NumElements = 0; CookieSize = CharUnits::Zero(); |