]> granicus.if.org Git - clang/commitdiff
Fix for PR5830: fix the computation of the offset to a virtual base.
authorEli Friedman <eli.friedman@gmail.com>
Fri, 18 Dec 2009 23:27:44 +0000 (23:27 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Fri, 18 Dec 2009 23:27:44 +0000 (23:27 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91724 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXX.cpp

index 2d5b4315ada91aa7474f2fc4b34aa47cf9b645f5..e860c295a53e38f8cea60a684fc8c6c03a5f93e5 100644 (file)
@@ -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(),