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 | 303e45750ed06d8bf8fda559f4a3748eef6b2386 (patch) | |
| tree | 75d845a6cc91f6a3ebe48cb96c9e7c84645a3304 | |
| parent | 7db230f5c9c75e79aa4eb1f527bce68e380908b3 (diff) | |
| download | bcm5719-llvm-303e45750ed06d8bf8fda559f4a3748eef6b2386.tar.gz bcm5719-llvm-303e45750ed06d8bf8fda559f4a3748eef6b2386.zip | |
Fix for PR5830: fix the computation of the offset to a virtual base.
llvm-svn: 91724
| -rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 2d5b4315ada..e860c295a53 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/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(), |

