diff options
author | John McCall <rjmccall@apple.com> | 2012-09-25 10:10:39 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2012-09-25 10:10:39 +0000 |
commit | 82fb892019bd1784153587a69d5bdfc72736d0ee (patch) | |
tree | c4f9f3b9512d8f2b045d115e43066a5985c499e2 /clang/lib/CodeGen/ItaniumCXXABI.cpp | |
parent | 8b907e8acbacc4485b0c5cc4777d5d5844ece52d (diff) | |
download | bcm5719-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/ItaniumCXXABI.cpp')
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 23 |
1 files changed, 23 insertions, 0 deletions
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, |