diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2009-12-18 23:27:44 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2009-12-18 23:27:44 +0000 |
commit | edd63718cce8eb3893a924b0b7d27e96b46001ad (patch) | |
tree | d51c6c01c891266ed7c04f4e2923e7f9448d2d1d /lib/CodeGen/CGCXX.cpp | |
parent | c3c90b25cf321d851314f0f19f67e9a00df0da0d (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.cpp | 39 |
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(), |