aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGCXX.cpp
diff options
context:
space:
mode:
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(),