]> granicus.if.org Git - clang/commitdiff
Revert "Revert r199416, "MS ABI: Improve selection of an inheritance model""
authorDavid Majnemer <david.majnemer@gmail.com>
Fri, 17 Jan 2014 09:01:00 +0000 (09:01 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Fri, 17 Jan 2014 09:01:00 +0000 (09:01 +0000)
This reverts commit r199475 (which reverted r199416) with fixes for the
breakages.

We wouldn't lock an inheritance model if we saw a pointer-to-member
formed as a result of the address-of operator.

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

include/clang/AST/DeclCXX.h
include/clang/AST/Type.h
include/clang/Basic/Attr.td
lib/AST/MicrosoftCXXABI.cpp
lib/AST/Type.cpp
lib/CodeGen/MicrosoftCXXABI.cpp
lib/Sema/SemaCast.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaType.cpp

index 75f20e2462ce6389e8020fd82634ded05a53b6e5..aee2aad475db1001c8db8936b0bf0673e257ccae 100644 (file)
@@ -17,6 +17,7 @@
 #define LLVM_CLANG_AST_DECLCXX_H
 
 #include "clang/AST/ASTUnresolvedSet.h"
+#include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
@@ -258,16 +259,6 @@ public:
   TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; }
 };
 
-/// The inheritance model to use for member pointers of a given CXXRecordDecl.
-enum MSInheritanceModel {
-  MSIM_Single,
-  MSIM_SinglePolymorphic,
-  MSIM_Multiple,
-  MSIM_MultiplePolymorphic,
-  MSIM_Virtual,
-  MSIM_Unspecified
-};
-
 /// \brief Represents a C++ struct/union/class.
 ///
 /// FIXME: This class will disappear once we've properly taught RecordDecl
@@ -1608,7 +1599,9 @@ public:
   }
 
   /// \brief Returns the inheritance model used for this record.
-  MSInheritanceModel getMSInheritanceModel() const;
+  MSInheritanceAttr::Spelling getMSInheritanceModel() const;
+  /// \brief Locks-in the inheritance model for this class.
+  void setMSInheritanceModel();
 
   /// \brief Determine whether this lambda expression was known to be dependent
   /// at the time it was created, even if its context does not appear to be
index 6b11b5892c9d960190e9ca2520a8cadf45fbf735..3a14c01f43fcfeb0d0dceb2c86ed6857a70f6d1c 100644 (file)
@@ -2205,6 +2205,7 @@ public:
   }
 
   const Type *getClass() const { return Class; }
+  CXXRecordDecl *getMostRecentCXXRecordDecl() const;
 
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
index 73def038b86064b9799a5789184d8ad09243a1d0..cb739fb99f3f5c8334514d8614db6b005aa20cd8 100644 (file)
@@ -1378,16 +1378,11 @@ def MSInheritance : InheritableAttr {
   let Spellings = [Keyword<"__single_inheritance">,
                    Keyword<"__multiple_inheritance">,
                    Keyword<"__virtual_inheritance">,
-                   // We use an empty string to denote an unspecified
-                   // inheritance attribute.
-                   Keyword<"">];
+                   Keyword<"__unspecified_inheritance">];
   let Accessors = [Accessor<"IsSingle", [Keyword<"__single_inheritance">]>,
                    Accessor<"IsMultiple", [Keyword<"__multiple_inheritance">]>,
                    Accessor<"IsVirtual", [Keyword<"__virtual_inheritance">]>,
-                   Accessor<"IsUnspecified", [Keyword<"">]>];
-  // This index is based off the Spellings list and corresponds to the empty
-  // keyword "spelling."
-  let AdditionalMembers = [{static const int UnspecifiedSpellingIndex = 3;}];
+                   Accessor<"IsUnspecified", [Keyword<"__unspecified_inheritance">]>];
 }
 
 def Unaligned : IgnoredAttr {
index 26e967570a0b58e129995cb775450f2a3a43bccf..c3478747a69b9d562d5cbde9195b6c7d8a2d002f 100644 (file)
@@ -92,28 +92,43 @@ static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) {
   return false;
 }
 
-static MSInheritanceModel MSInheritanceAttrToModel(MSInheritanceAttr *Attr) {
+static MSInheritanceAttr::Spelling
+MSInheritanceAttrToModel(const MSInheritanceAttr *Attr) {
   if (Attr->IsSingle())
-    return MSIM_Single;
+    return MSInheritanceAttr::Keyword_single_inheritance;
   else if (Attr->IsMultiple())
-    return MSIM_Multiple;
+    return MSInheritanceAttr::Keyword_multiple_inheritance;
   else if (Attr->IsVirtual())
-    return MSIM_Virtual;
+    return MSInheritanceAttr::Keyword_virtual_inheritance;
   
   assert(Attr->IsUnspecified() && "Expected unspecified inheritance attr");
-  return MSIM_Unspecified;
+  return MSInheritanceAttr::Keyword_unspecified_inheritance;
 }
 
-MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const {
-  if (MSInheritanceAttr *IA = this->getAttr<MSInheritanceAttr>())
-    return MSInheritanceAttrToModel(IA);
-  // If there was no explicit attribute, the record must be defined already, and
-  // we can figure out the inheritance model from its other properties.
-  if (this->getNumVBases() > 0)
-    return MSIM_Virtual;
-  if (usesMultipleInheritanceModel(this))
-    return this->isPolymorphic() ? MSIM_MultiplePolymorphic : MSIM_Multiple;
-  return this->isPolymorphic() ? MSIM_SinglePolymorphic : MSIM_Single;
+static MSInheritanceAttr::Spelling
+calculateInheritanceModel(const CXXRecordDecl *RD) {
+  if (!RD->hasDefinition())
+    return MSInheritanceAttr::Keyword_unspecified_inheritance;
+  if (RD->getNumVBases() > 0)
+    return MSInheritanceAttr::Keyword_virtual_inheritance;
+  if (usesMultipleInheritanceModel(RD))
+    return MSInheritanceAttr::Keyword_multiple_inheritance;
+  return MSInheritanceAttr::Keyword_single_inheritance;
+}
+
+MSInheritanceAttr::Spelling
+CXXRecordDecl::getMSInheritanceModel() const {
+  MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>();
+  assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!");
+  return MSInheritanceAttrToModel(IA);
+}
+
+void CXXRecordDecl::setMSInheritanceModel() {
+  if (hasAttr<MSInheritanceAttr>())
+    return;
+
+  addAttr(MSInheritanceAttr::CreateImplicit(
+      getASTContext(), calculateInheritanceModel(this), getSourceRange()));
 }
 
 // Returns the number of pointer and integer slots used to represent a member
@@ -146,9 +161,9 @@ MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const {
 //   };
 static std::pair<unsigned, unsigned>
 getMSMemberPointerSlots(const MemberPointerType *MPT) {
-  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
-  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
-  unsigned Ptrs;
+  const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
+  MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
+  unsigned Ptrs = 0;
   unsigned Ints = 0;
   if (MPT->isMemberFunctionPointer()) {
     // Member function pointers are a struct of a function pointer followed by a
@@ -156,26 +171,29 @@ getMSMemberPointerSlots(const MemberPointerType *MPT) {
     // function pointer is a real function if it is non-virtual and a vftable
     // slot thunk if it is virtual.  The ints select the object base passed for
     // the 'this' pointer.
-    Ptrs = 1;  // First slot is always a function pointer.
+    Ptrs = 1; // First slot is always a function pointer.
     switch (Inheritance) {
-    case MSIM_Unspecified: ++Ints;  // VBTableOffset
-    case MSIM_Virtual:     ++Ints;  // VirtualBaseAdjustmentOffset
-    case MSIM_MultiplePolymorphic:
-    case MSIM_Multiple:    ++Ints;  // NonVirtualBaseAdjustment
-    case MSIM_SinglePolymorphic:
-    case MSIM_Single:      break;   // Nothing
+    case MSInheritanceAttr::Keyword_unspecified_inheritance:
+      ++Ints; // VBTableOffset
+    case MSInheritanceAttr::Keyword_virtual_inheritance:
+      ++Ints; // VirtualBaseAdjustmentOffset
+    case MSInheritanceAttr::Keyword_multiple_inheritance:
+      ++Ints; // NonVirtualBaseAdjustment
+    case MSInheritanceAttr::Keyword_single_inheritance:
+      break;  // Nothing
     }
   } else {
     // Data pointers are an aggregate of ints.  The first int is an offset
     // followed by vbtable-related offsets.
-    Ptrs = 0;
+    Ints = 1; // We always have a field offset.
     switch (Inheritance) {
-    case MSIM_Unspecified: ++Ints;  // VBTableOffset
-    case MSIM_Virtual:     ++Ints;  // VirtualBaseAdjustmentOffset
-    case MSIM_MultiplePolymorphic:
-    case MSIM_Multiple:             // Nothing
-    case MSIM_SinglePolymorphic:
-    case MSIM_Single:      ++Ints;  // Field offset
+    case MSInheritanceAttr::Keyword_unspecified_inheritance:
+      ++Ints; // VBTableOffset
+    case MSInheritanceAttr::Keyword_virtual_inheritance:
+      ++Ints; // VirtualBaseAdjustmentOffset
+    case MSInheritanceAttr::Keyword_multiple_inheritance:
+    case MSInheritanceAttr::Keyword_single_inheritance:
+      break;  // Nothing
     }
   }
   return std::make_pair(Ptrs, Ints);
index fac10768d566ed26586f3c87081dd11cd3124b9f..3d4a7454f77f91f432e7bcae2641b47917a2f657 100644 (file)
@@ -2469,3 +2469,7 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
 
   return DK_none;
 }
+
+CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const {
+  return getClass()->getAsCXXRecordDecl()->getMostRecentDecl();
+}
index 32f8ab2fb5da3bbb1395c7337a2eb6248165793e..875591d0df9c1ac1917a1bbfe8c848019beb61bc 100644 (file)
@@ -1322,25 +1322,29 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
 }
 
 // Member pointer helpers.
-static bool hasVBPtrOffsetField(MSInheritanceModel Inheritance) {
-  return Inheritance == MSIM_Unspecified;
+static bool hasVBPtrOffsetField(MSInheritanceAttr::Spelling Inheritance) {
+  return Inheritance == MSInheritanceAttr::Keyword_unspecified_inheritance;
 }
 
 static bool hasOnlyOneField(bool IsMemberFunction,
-                            MSInheritanceModel Inheritance) {
-  return Inheritance <= MSIM_SinglePolymorphic ||
-      (!IsMemberFunction && Inheritance <= MSIM_MultiplePolymorphic);
+                            MSInheritanceAttr::Spelling Inheritance) {
+  if (IsMemberFunction)
+    return Inheritance <= MSInheritanceAttr::Keyword_single_inheritance;
+  return Inheritance <= MSInheritanceAttr::Keyword_multiple_inheritance;
 }
 
 // Only member pointers to functions need a this adjustment, since it can be
 // combined with the field offset for data pointers.
-static bool hasNonVirtualBaseAdjustmentField(bool IsMemberFunction,
-                                             MSInheritanceModel Inheritance) {
-  return (IsMemberFunction && Inheritance >= MSIM_Multiple);
+static bool
+hasNonVirtualBaseAdjustmentField(bool IsMemberFunction,
+                                 MSInheritanceAttr::Spelling Inheritance) {
+  return IsMemberFunction &&
+         Inheritance >= MSInheritanceAttr::Keyword_multiple_inheritance;
 }
 
-static bool hasVirtualBaseAdjustmentField(MSInheritanceModel Inheritance) {
-  return Inheritance >= MSIM_Virtual;
+static bool
+hasVirtualBaseAdjustmentField(MSInheritanceAttr::Spelling Inheritance) {
+  return Inheritance >= MSInheritanceAttr::Keyword_virtual_inheritance;
 }
 
 // Use zero for the field offset of a null data member pointer if we can
@@ -1349,8 +1353,10 @@ static bool hasVirtualBaseAdjustmentField(MSInheritanceModel Inheritance) {
 // use zero for null.  If there are multiple fields, we can use zero even if it
 // is a valid field offset because null-ness testing will check the other
 // fields.
-static bool nullFieldOffsetIsZero(MSInheritanceModel Inheritance) {
-  return Inheritance != MSIM_Multiple && Inheritance != MSIM_Single;
+static bool nullFieldOffsetIsZero(const CXXRecordDecl *RD) {
+  return RD->getMSInheritanceModel() >=
+             MSInheritanceAttr::Keyword_virtual_inheritance ||
+         (RD->hasDefinition() && RD->isPolymorphic());
 }
 
 bool MicrosoftCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
@@ -1362,16 +1368,16 @@ bool MicrosoftCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
   // The virtual base adjustment field is always -1 for null, so if we have one
   // we can't zero initialize.  The field offset is sometimes also -1 if 0 is a
   // valid field offset.
-  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
-  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+  const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
+  MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
   return (!hasVirtualBaseAdjustmentField(Inheritance) &&
-          nullFieldOffsetIsZero(Inheritance));
+          nullFieldOffsetIsZero(RD));
 }
 
 llvm::Type *
 MicrosoftCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
-  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
-  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+  const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
+  MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
   llvm::SmallVector<llvm::Type *, 4> fields;
   if (MPT->isMemberFunctionPointer())
     fields.push_back(CGM.VoidPtrTy);  // FunctionPointerOrVirtualThunk
@@ -1395,13 +1401,13 @@ void MicrosoftCXXABI::
 GetNullMemberPointerFields(const MemberPointerType *MPT,
                            llvm::SmallVectorImpl<llvm::Constant *> &fields) {
   assert(fields.empty());
-  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
-  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+  const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
+  MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
   if (MPT->isMemberFunctionPointer()) {
     // FunctionPointerOrVirtualThunk
     fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy));
   } else {
-    if (nullFieldOffsetIsZero(Inheritance))
+    if (nullFieldOffsetIsZero(RD))
       fields.push_back(getZeroInt());  // FieldOffset
     else
       fields.push_back(getAllOnesInt());  // FieldOffset
@@ -1433,7 +1439,7 @@ MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
                                        const CXXRecordDecl *RD,
                                        CharUnits NonVirtualBaseAdjustment)
 {
-  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+  MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
 
   // Single inheritance class member pointer are represented as scalars instead
   // of aggregates.
@@ -1464,7 +1470,7 @@ MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
 llvm::Constant *
 MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
                                        CharUnits offset) {
-  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+  const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
   llvm::Constant *FirstField =
     llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity());
   return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD,
@@ -1487,8 +1493,8 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP,
   // FIXME PR15713: Support virtual inheritance paths.
 
   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD))
-    return BuildMemberPointer(MPT->getClass()->getAsCXXRecordDecl(),
-                              MD, ThisAdjustment);
+    return BuildMemberPointer(MPT->getMostRecentCXXRecordDecl(), MD,
+                              ThisAdjustment);
 
   CharUnits FieldOffset =
     getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
@@ -1501,6 +1507,7 @@ MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD,
                                     CharUnits NonVirtualBaseAdjustment) {
   assert(MD->isInstance() && "Member function must not be static!");
   MD = MD->getCanonicalDecl();
+  RD = RD->getMostRecentDecl();
   CodeGenTypes &Types = CGM.getTypes();
 
   llvm::Constant *FirstField;
@@ -1578,8 +1585,8 @@ MicrosoftCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
 
   // If this is a single field member pointer (single inheritance), this is a
   // single icmp.
-  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
-  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+  const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
+  MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
   if (hasOnlyOneField(MPT->isMemberFunctionPointer(), Inheritance))
     return Builder.CreateICmp(Eq, L, R);
 
@@ -1760,8 +1767,8 @@ MicrosoftCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
   llvm::Type *PType =
       CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS);
   CGBuilderTy &Builder = CGF.Builder;
-  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
-  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+  const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
+  MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
 
   // Extract the fields we need, regardless of model.  We'll apply them if we
   // have them.
@@ -1795,9 +1802,9 @@ MicrosoftCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
   return Builder.CreateBitCast(Addr, PType);
 }
 
-static MSInheritanceModel
+static MSInheritanceAttr::Spelling
 getInheritanceFromMemptr(const MemberPointerType *MPT) {
-  return MPT->getClass()->getAsCXXRecordDecl()->getMSInheritanceModel();
+  return MPT->getMostRecentCXXRecordDecl()->getMSInheritanceModel();
 }
 
 llvm::Value *
@@ -1817,15 +1824,17 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
   const MemberPointerType *SrcTy =
     E->getSubExpr()->getType()->castAs<MemberPointerType>();
   const MemberPointerType *DstTy = E->getType()->castAs<MemberPointerType>();
-  MSInheritanceModel SrcInheritance = getInheritanceFromMemptr(SrcTy);
-  MSInheritanceModel DstInheritance = getInheritanceFromMemptr(DstTy);
   bool IsFunc = SrcTy->isMemberFunctionPointer();
 
   // If the classes use the same null representation, reinterpret_cast is a nop.
   bool IsReinterpret = E->getCastKind() == CK_ReinterpretMemberPointer;
-  if (IsReinterpret && (IsFunc ||
-                        nullFieldOffsetIsZero(SrcInheritance) ==
-                        nullFieldOffsetIsZero(DstInheritance)))
+  if (IsReinterpret && IsFunc)
+    return Src;
+
+  CXXRecordDecl *SrcRD = SrcTy->getMostRecentCXXRecordDecl();
+  CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl();
+  if (IsReinterpret &&
+      nullFieldOffsetIsZero(SrcRD) == nullFieldOffsetIsZero(DstRD))
     return Src;
 
   CGBuilderTy &Builder = CGF.Builder;
@@ -1854,6 +1863,7 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
   llvm::Value *NonVirtualBaseAdjustment = 0;
   llvm::Value *VirtualBaseAdjustmentOffset = 0;
   llvm::Value *VBPtrOffset = 0;
+  MSInheritanceAttr::Spelling SrcInheritance = SrcRD->getMSInheritanceModel();
   if (!hasOnlyOneField(IsFunc, SrcInheritance)) {
     // We need to extract values.
     unsigned I = 0;
@@ -1884,6 +1894,7 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
   // FIXME PR15713: Support conversions through virtually derived classes.
 
   // Recompose dst from the null struct and the adjusted fields from src.
+  MSInheritanceAttr::Spelling DstInheritance = DstRD->getMSInheritanceModel();
   llvm::Value *Dst;
   if (hasOnlyOneField(IsFunc, DstInheritance)) {
     Dst = FirstField;
@@ -1929,8 +1940,8 @@ MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E,
   if (E->getCastKind() == CK_ReinterpretMemberPointer)
     return Src;
 
-  MSInheritanceModel SrcInheritance = getInheritanceFromMemptr(SrcTy);
-  MSInheritanceModel DstInheritance = getInheritanceFromMemptr(DstTy);
+  MSInheritanceAttr::Spelling SrcInheritance = getInheritanceFromMemptr(SrcTy);
+  MSInheritanceAttr::Spelling DstInheritance = getInheritanceFromMemptr(DstTy);
 
   // Decompose src.
   llvm::Constant *FirstField = Src;
@@ -1991,13 +2002,13 @@ MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
   assert(MPT->isMemberFunctionPointer());
   const FunctionProtoType *FPT =
     MPT->getPointeeType()->castAs<FunctionProtoType>();
-  const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+  const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
   llvm::FunctionType *FTy =
     CGM.getTypes().GetFunctionType(
       CGM.getTypes().arrangeCXXMethodType(RD, FPT));
   CGBuilderTy &Builder = CGF.Builder;
 
-  MSInheritanceModel Inheritance = RD->getMSInheritanceModel();
+  MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
 
   // Extract the fields we need, regardless of model.  We'll apply them if we
   // have them.
index 63cb15db52905a1c5a3cfbf2c3dd99ff10617756..499e8b18be8182c942aeb2eb89c5aef7a52efdad 100644 (file)
@@ -21,6 +21,7 @@
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
 #include "clang/Sema/Initialization.h"
 #include "llvm/ADT/SmallVector.h"
 #include <set>
@@ -1779,6 +1780,13 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
       return TC_Failed;
     }
 
+    if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+      // We need to determine the inheritance model that the class will use if
+      // haven't yet.
+      Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0);
+      Self.RequireCompleteType(OpRange.getBegin(), DestType, 0);
+    }
+
     // Don't allow casting between member pointers of different sizes.
     if (Self.Context.getTypeSize(DestMemPtr) !=
         Self.Context.getTypeSize(SrcMemPtr)) {
index 8531286a9c73a7b4550b70007757fb9d1eb98bdb..268087f506686a8a813c733c008b9479529e374d 100644 (file)
@@ -8855,8 +8855,11 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
     if (isa<CXXDestructorDecl>(MD))
       Diag(OpLoc, diag::err_typecheck_addrof_dtor) << op->getSourceRange();
 
-    return Context.getMemberPointerType(op->getType(),
-              Context.getTypeDeclType(MD->getParent()).getTypePtr());
+    QualType MPTy = Context.getMemberPointerType(
+        op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr());
+    if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+      RequireCompleteType(OpLoc, MPTy, 0);
+    return MPTy;
   } else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
     // C99 6.5.3.2p1
     // The operand must be either an l-value or a function designator
@@ -8904,8 +8907,13 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
 
           while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion())
             Ctx = Ctx->getParent();
-          return Context.getMemberPointerType(op->getType(),
-                Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+
+          QualType MPTy = Context.getMemberPointerType(
+              op->getType(),
+              Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+          if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+            RequireCompleteType(OpLoc, MPTy, 0);
+          return MPTy;
         }
       }
     } else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl))
index bc674d53d7fd4443ca5c0a587ff3907473d697a6..30edc48dd507bad11faacbd0331eee5e63c5149b 100644 (file)
@@ -1753,35 +1753,6 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
     return QualType();
   }
 
-  // C++ allows the class type in a member pointer to be an incomplete type.
-  // In the Microsoft ABI, the size of the member pointer can vary
-  // according to the class type, which means that we really need a
-  // complete type if possible, which means we need to instantiate templates.
-  //
-  // If template instantiation fails or the type is just incomplete, we have to
-  // add an extra slot to the member pointer.  Yes, this does cause problems
-  // when passing pointers between TUs that disagree about the size.
-  if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
-    CXXRecordDecl *RD = Class->getAsCXXRecordDecl();
-    if (RD && !RD->hasAttr<MSInheritanceAttr>()) {
-      // Lock in the inheritance model on the first use of a member pointer.
-      // Otherwise we may disagree about the size at different points in the TU.
-      // FIXME: MSVC picks a model on the first use that needs to know the size,
-      // rather than on the first mention of the type, e.g. typedefs.
-      if (RequireCompleteType(Loc, Class, 0) && !RD->isBeingDefined()) {
-        // We know it doesn't have an attribute and it's incomplete, so use the
-        // unspecified inheritance model.  If we're in the record body, we can
-        // figure out the inheritance model.
-        for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(),
-             E = RD->redecls_end(); I != E; ++I) {
-          I->addAttr(::new (Context) MSInheritanceAttr(RD->getSourceRange(),
-                                                       Context,
-                                 MSInheritanceAttr::UnspecifiedSpellingIndex));
-        }
-      }
-    }
-  }
-
   // Adjust the default free function calling convention to the default method
   // calling convention.
   if (T->isFunctionType())
@@ -5096,6 +5067,18 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
       }
     }
 
+    // We lock in the inheritance model once somebody has asked us to ensure
+    // that a pointer-to-member type is complete.
+    if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+      if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
+        if (!MPTy->getClass()->isDependentType()) {
+          RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0);
+
+          MPTy->getMostRecentCXXRecordDecl()->setMSInheritanceModel();
+        }
+      }
+    }
+
     return false;
   }