aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGCXX.cpp
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2009-12-18 23:27:44 +0000
committerEli Friedman <eli.friedman@gmail.com>2009-12-18 23:27:44 +0000
commitedd63718cce8eb3893a924b0b7d27e96b46001ad (patch)
treed51c6c01c891266ed7c04f4e2923e7f9448d2d1d /lib/CodeGen/CGCXX.cpp
parentc3c90b25cf321d851314f0f19f67e9a00df0da0d (diff)
Fix for PR5830: fix the computation of the offset to a virtual base.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91724 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCXX.cpp')
-rw-r--r--lib/CodeGen/CGCXX.cpp39
1 files changed, 36 insertions, 3 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 2d5b4315ad..e860c295a5 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -1535,9 +1535,42 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
const Type *BaseType = BaseInit->getBaseClass();
CXXRecordDecl *BaseClassDecl =
cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
- llvm::Value *V = CGF.GetAddressOfBaseClass(ThisPtr, ClassDecl,
- BaseClassDecl,
- /*NullCheckValue=*/false);
+
+ // FIXME: This method of determining whether a base is virtual is ridiculous;
+ // it should be part of BaseInit.
+ bool isBaseVirtual = false;
+ for (CXXRecordDecl::base_class_const_iterator I = ClassDecl->vbases_begin(),
+ E = ClassDecl->vbases_end(); I != E; ++I)
+ if (I->getType()->getAs<RecordType>()->getDecl() == BaseClassDecl) {
+ isBaseVirtual = true;
+ break;
+ }
+
+ // The base constructor doesn't construct virtual bases.
+ if (CtorType == Ctor_Base && isBaseVirtual)
+ return;
+
+ // Compute the offset to the base; we do this directly instead of using
+ // GetAddressOfBaseClass because the class doesn't have a vtable pointer
+ // at this point.
+ // FIXME: This could be refactored back into GetAddressOfBaseClass if it took
+ // an extra parameter for whether the derived class is the complete object
+ // class.
+ const ASTRecordLayout &Layout =
+ CGF.getContext().getASTRecordLayout(ClassDecl);
+ uint64_t Offset;
+ if (isBaseVirtual)
+ Offset = Layout.getVBaseClassOffset(BaseClassDecl);
+ else
+ Offset = Layout.getBaseClassOffset(BaseClassDecl);
+ const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ const llvm::Type *BaseClassType = CGF.ConvertType(QualType(BaseType, 0));
+ llvm::Value *V = CGF.Builder.CreateBitCast(ThisPtr, Int8PtrTy);
+ V = CGF.Builder.CreateConstInBoundsGEP1_64(V, Offset/8);
+ V = CGF.Builder.CreateBitCast(V, BaseClassType->getPointerTo());
+
+ // FIXME: This should always use Ctor_Base as the ctor type! (But that
+ // causes crashes in tests.)
CGF.EmitCXXConstructorCall(BaseInit->getConstructor(),
CtorType, V,
BaseInit->const_arg_begin(),