summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2012-09-25 10:10:39 +0000
committerJohn McCall <rjmccall@apple.com>2012-09-25 10:10:39 +0000
commit82fb892019bd1784153587a69d5bdfc72736d0ee (patch)
treec4f9f3b9512d8f2b045d115e43066a5985c499e2 /clang/lib/CodeGen
parent8b907e8acbacc4485b0c5cc4777d5d5844ece52d (diff)
downloadbcm5719-llvm-82fb892019bd1784153587a69d5bdfc72736d0ee.tar.gz
bcm5719-llvm-82fb892019bd1784153587a69d5bdfc72736d0ee.zip
When performing a ::delete of an object with a virtual destructor,
be sure to delete the complete object pointer, not the original pointer. This is necessary if the base being deleted is at a non-zero offset in the complete object. This is only required for objects with virtual destructors because deleting an object via a base-class subobject when the base does not have a virtual destructor is undefined behavior. Noticed while reviewing the last four years of cxx-abi-dev activity. llvm-svn: 164597
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGCXXABI.h9
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp8
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp23
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp11
4 files changed, 50 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h
index a0dcdfdcc68..ffe70be2ca5 100644
--- a/clang/lib/CodeGen/CGCXXABI.h
+++ b/clang/lib/CodeGen/CGCXXABI.h
@@ -154,6 +154,15 @@ protected:
llvm::Constant *getMemberPointerAdjustment(const CastExpr *E);
public:
+ /// Adjust the given non-null pointer to an object of polymorphic
+ /// type to point to the complete object.
+ ///
+ /// The IR type of the result should be a pointer but is otherwise
+ /// irrelevant.
+ virtual llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
+ llvm::Value *ptr,
+ QualType type) = 0;
+
/// Build the signature of the given constructor variant by adding
/// any required parameters. For convenience, ResTy has been
/// initialized to 'void', and ArgTys has been initialized with the
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 3aa5e747812..7276440a47a 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1382,8 +1382,14 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
if (UseGlobalDelete) {
// If we're supposed to call the global delete, make sure we do so
// even if the destructor throws.
+
+ // Derive the complete-object pointer, which is what we need
+ // to pass to the deallocation function.
+ llvm::Value *completePtr =
+ CGF.CGM.getCXXABI().adjustToCompleteObject(CGF, Ptr, ElementType);
+
CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup,
- Ptr, OperatorDelete,
+ completePtr, OperatorDelete,
ElementType);
}
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 5fbff3c253d..877d0d4ae21 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -92,6 +92,10 @@ public:
llvm::Value *Addr,
const MemberPointerType *MPT);
+ llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
+ llvm::Value *ptr,
+ QualType type);
+
void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType T,
CanQualType &ResTy,
@@ -677,6 +681,25 @@ bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
return MPT->getPointeeType()->isFunctionType();
}
+/// The Itanium ABI always places an offset to the complete object
+/// at entry -2 in the vtable.
+llvm::Value *ItaniumCXXABI::adjustToCompleteObject(CodeGenFunction &CGF,
+ llvm::Value *ptr,
+ QualType type) {
+ // Grab the vtable pointer as an intptr_t*.
+ llvm::Value *vtable = CGF.GetVTablePtr(ptr, CGF.IntPtrTy->getPointerTo());
+
+ // Track back to entry -2 and pull out the offset there.
+ llvm::Value *offsetPtr =
+ CGF.Builder.CreateConstInBoundsGEP1_64(vtable, -2, "complete-offset.ptr");
+ llvm::LoadInst *offset = CGF.Builder.CreateLoad(offsetPtr);
+ offset->setAlignment(CGF.PointerAlignInBytes);
+
+ // Apply the offset.
+ ptr = CGF.Builder.CreateBitCast(ptr, CGF.Int8PtrTy);
+ return CGF.Builder.CreateInBoundsGEP(ptr, offset);
+}
+
/// The generic ABI passes 'this', plus a VTT if it's initializing a
/// base subobject.
void ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index b000c68a952..2c8173ba384 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -30,6 +30,10 @@ public:
StringRef GetPureVirtualCallName() { return "_purecall"; }
+ llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
+ llvm::Value *ptr,
+ QualType type);
+
void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
CXXCtorType Type,
CanQualType &ResTy,
@@ -95,6 +99,13 @@ public:
}
+llvm::Value *MicrosoftCXXABI::adjustToCompleteObject(CodeGenFunction &CGF,
+ llvm::Value *ptr,
+ QualType type) {
+ // FIXME: implement
+ return ptr;
+}
+
bool MicrosoftCXXABI::needThisReturn(GlobalDecl GD) {
const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
return isa<CXXConstructorDecl>(MD);
OpenPOWER on IntegriCloud