]> granicus.if.org Git - clang/commitdiff
MS ABI: Don't ICE for pointers to pointers to members of incomplete classes
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 18 Sep 2014 22:05:54 +0000 (22:05 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 18 Sep 2014 22:05:54 +0000 (22:05 +0000)
CodeGen would try to come up with an LLVM IR type for a pointer to
member type on the way to forming an LLVM IR type for a pointer to
pointer to member type.

However, if the pointer to member representation has not been locked in yet,
we would not be able to come up with a pointer to member IR type.

In these cases, make the pointer to member type an incomplete type.
This will make the pointer to pointer to member type a pointer to an
incomplete type.  If the class eventually obtains an inheritance model,
we will make the pointer to member type represent the actual inheritance
model.

Differential Revision: http://reviews.llvm.org/D5373

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218084 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXXABI.h
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h
lib/CodeGen/CodeGenTypes.cpp
lib/CodeGen/MicrosoftCXXABI.cpp
test/CodeGenCXX/microsoft-abi-member-pointers.cpp

index b7ce0b07e575f6e698c046bc62b4cdafb22e8856..f021e886c024550c85fbdb8351b99f83572cff0b 100644 (file)
@@ -161,6 +161,10 @@ public:
     return true;
   }
 
+  virtual bool isTypeInfoCalculable(QualType Ty) const {
+    return !Ty->isIncompleteType();
+  }
+
   /// Create a null member pointer of the given type.
   virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
 
index f49e9ec1267b2acf0c1bd133444231bdaa9bb433..9f359185381715de075a2b64f12d1f778fc5716e 100644 (file)
@@ -79,6 +79,17 @@ CodeGenFunction::~CodeGenFunction() {
   }
 }
 
+LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) {
+  CharUnits Alignment;
+  if (CGM.getCXXABI().isTypeInfoCalculable(T)) {
+    Alignment = getContext().getTypeAlignInChars(T);
+    unsigned MaxAlign = getContext().getLangOpts().MaxTypeAlign;
+    if (MaxAlign && Alignment.getQuantity() > MaxAlign &&
+        !getContext().isAlignmentRequired(T))
+      Alignment = CharUnits::fromQuantity(MaxAlign);
+  }
+  return LValue::MakeAddr(V, T, Alignment, getContext(), CGM.getTBAAInfo(T));
+}
 
 llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) {
   return CGM.getTypes().ConvertTypeForMem(T);
index b67860cab1811ae655d3940d6e27e3256eccce95..eebdbf34a8eefb3cae8dbc8bab64ba67b53eaeea 100644 (file)
@@ -1401,18 +1401,7 @@ public:
                             CGM.getTBAAInfo(T));
   }
 
-  LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) {
-    CharUnits Alignment;
-    if (!T->isIncompleteType()) {
-      Alignment = getContext().getTypeAlignInChars(T);
-      unsigned MaxAlign = getContext().getLangOpts().MaxTypeAlign;
-      if (MaxAlign && Alignment.getQuantity() > MaxAlign &&
-          !getContext().isAlignmentRequired(T))
-        Alignment = CharUnits::fromQuantity(MaxAlign);
-    }
-    return LValue::MakeAddr(V, T, Alignment, getContext(),
-                            CGM.getTBAAInfo(T));
-  }
+  LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T);
 
   /// CreateTempAlloca - This creates a alloca and inserts it into the entry
   /// block. The caller is responsible for setting an appropriate alignment on
index 1f39eb88c01f88b1359f27002570a59ef5e37e71..1404dfd7a9dae62a6beb0862e28abe4de13254f9 100644 (file)
@@ -81,7 +81,7 @@ void CodeGenTypes::addRecordTypeName(const RecordDecl *RD,
 /// ConvertType in that it is used to convert to the memory representation for
 /// a type.  For example, the scalar representation for _Bool is i1, but the
 /// memory representation is usually i8 or i32, depending on the target.
-llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T){
+llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T) {
   llvm::Type *R = ConvertType(T);
 
   // If this is a non-bool type, don't map it.
@@ -587,6 +587,8 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
   }
 
   case Type::MemberPointer: {
+    if (!getCXXABI().isMemberPointerConvertible(cast<MemberPointerType>(Ty)))
+      return llvm::StructType::create(getLLVMContext());
     ResultType = 
       getCXXABI().ConvertMemberPointerType(cast<MemberPointerType>(Ty));
     break;
index 36392bc5ed0cf0d39c62aa3b378ed90b2c6695ae..dd6a4580d493445526b0e6cc944aa881c4340b17 100644 (file)
@@ -488,7 +488,18 @@ public:
 
   bool isMemberPointerConvertible(const MemberPointerType *MPT) const override {
     const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
-    return RD->getAttr<MSInheritanceAttr>() != nullptr;
+    return RD->hasAttr<MSInheritanceAttr>();
+  }
+
+  virtual bool isTypeInfoCalculable(QualType Ty) const {
+    if (!CGCXXABI::isTypeInfoCalculable(Ty))
+      return false;
+    if (const auto *MPT = Ty->getAs<MemberPointerType>()) {
+      const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
+      if (!RD->hasAttr<MSInheritanceAttr>())
+        return false;
+    }
+    return true;
   }
 
   llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override;
index 04665c93ce618bfc42636a80004a9b50405a089a..c574bf7c3f1a65c7cd60418f95778e5204f6c314 100644 (file)
@@ -1,9 +1,19 @@
-// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s
-// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64
-// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify
-// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify
-// FIXME: Test x86_64 member pointers when codegen no longer asserts on records
-// with virtual bases.
+// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64
+// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify
+// RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify
+
+namespace PR20947 {
+struct A;
+int A::**a = nullptr;
+// CHECK: %[[opaque0:.*]] = type opaque
+// CHECK: %[[opaque1:.*]] = type opaque
+// CHECK: @"\01?a@PR20947@@3PAPQA@1@HA" = global %[[opaque0]]* null, align 4
+
+struct B;
+int B::*&b = b;
+// CHECK: @"\01?b@PR20947@@3AAPQB@1@HA" = global %[[opaque1]]* null, align 4
+}
 
 #ifndef INCOMPLETE_VIRTUAL
 struct B1 {