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
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);
}
}
+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);
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
/// 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.
}
case Type::MemberPointer: {
+ if (!getCXXABI().isMemberPointerConvertible(cast<MemberPointerType>(Ty)))
+ return llvm::StructType::create(getLLVMContext());
ResultType =
getCXXABI().ConvertMemberPointerType(cast<MemberPointerType>(Ty));
break;
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;
-// 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 {