]> granicus.if.org Git - clang/commitdiff
MS ABI: Tweak pointer-to-member mangling/inheritance model selection
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 6 Feb 2014 10:59:19 +0000 (10:59 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 6 Feb 2014 10:59:19 +0000 (10:59 +0000)
Properly determine the inheritance model when dealing with nullptr:
- If a nullptr template argument is being checked against
  pointer-to-member parameter, nail down an inheritance model.
  N.B. We will chose an inheritance model even if we won't ultimately
  choose the template to instantiate!  Cooky, right?
- Null pointer-to-datamembers have a virtual base table offset of -1,
  not zero. Previously, we chose an offset of 0.

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

lib/AST/MicrosoftMangle.cpp
lib/Sema/SemaCast.cpp
lib/Sema/SemaTemplate.cpp
test/CodeGenCXX/mangle-ms-templates-memptrs.cpp

index 8563f2e29116044723668c459871d0108064b14e..f02dfc72ee90661ba0055868c0e620c99433c71c 100644 (file)
@@ -383,43 +383,38 @@ void MicrosoftCXXNameMangler::mangleMemberDataPointer(const CXXRecordDecl *RD,
   //                       ::= $F <number> <number>
   //                       ::= $G <number> <number> <number>
 
-  int64_t FO = 0;
+  int64_t FieldOffset;
+  int64_t VBTableOffset;
   MSInheritanceAttr::Spelling IM = RD->getMSInheritanceModel();
   if (FD) {
-    FO = getASTContext().getFieldOffset(FD);
-    assert(FO % getASTContext().getCharWidth() == 0 &&
+    FieldOffset = getASTContext().getFieldOffset(FD);
+    assert(FieldOffset % getASTContext().getCharWidth() == 0 &&
            "cannot take address of bitfield");
-    FO /= getASTContext().getCharWidth();
-  } else if (!RD->nullFieldOffsetIsZero()) {
-    FO = -1;
+    FieldOffset /= getASTContext().getCharWidth();
+
+    VBTableOffset = 0;
+  } else {
+    FieldOffset = RD->nullFieldOffsetIsZero() ? 0 : -1;
+
+    VBTableOffset = -1;
   }
 
+  char Code = '\0';
   switch (IM) {
-  case MSInheritanceAttr::Keyword_single_inheritance:
-  case MSInheritanceAttr::Keyword_multiple_inheritance: {
-    // If we only have a single field, it's just an integer literal.
-    llvm::APSInt Val(64, /*isUnsigned=*/false);
-    Val = FO;
-    mangleIntegerLiteral(Val, /*IsBoolean=*/false);
-    break;
+  case MSInheritanceAttr::Keyword_single_inheritance:      Code = '0'; break;
+  case MSInheritanceAttr::Keyword_multiple_inheritance:    Code = '0'; break;
+  case MSInheritanceAttr::Keyword_virtual_inheritance:     Code = 'F'; break;
+  case MSInheritanceAttr::Keyword_unspecified_inheritance: Code = 'G'; break;
   }
 
-  // Otherwise, we have an aggregate, but all adjusting fields should be zero,
-  // because we don't allow casts (even implicit) in the context of a template
-  // argument.
-  case MSInheritanceAttr::Keyword_virtual_inheritance:
-    Out << "$F";
-    mangleNumber(FO);
-    mangleNumber(0);
-    break;
+  Out << '$' << Code;
 
-  case MSInheritanceAttr::Keyword_unspecified_inheritance:
-    Out << "$G";
-    mangleNumber(FO);
-    mangleNumber(0);
+  mangleNumber(FieldOffset);
+
+  if (MSInheritanceAttr::hasVBPtrOffsetField(IM))
     mangleNumber(0);
-    break;
-  }
+  if (MSInheritanceAttr::hasVBTableOffsetField(IM))
+    mangleNumber(VBTableOffset);
 }
 
 void
@@ -455,9 +450,7 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD,
   // thunk.
   uint64_t NVOffset = 0;
   uint64_t VBTableOffset = 0;
-  if (!MD) {
-    mangleNumber(0);
-  } else if (MD->isVirtual()) {
+  if (MD->isVirtual()) {
     MicrosoftVTableContext *VTContext =
         cast<MicrosoftVTableContext>(getASTContext().getVTableContext());
     const MicrosoftVTableContext::MethodVFTableLocation &ML =
@@ -1110,7 +1103,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
   case TemplateArgument::NullPtr: {
     QualType T = TA.getNullPtrType();
     if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) {
-      const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+      const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
       if (MPT->isMemberFunctionPointerType())
         mangleMemberFunctionPointer(RD, 0);
       else
index 499e8b18be8182c942aeb2eb89c5aef7a52efdad..5d49225ac4c96ef73c78c0c4e61f8176e9235be7 100644 (file)
@@ -1433,6 +1433,10 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
       msg = 0;
       return TC_Failed;
     }
+  } else if (DestType->isMemberPointerType()) {
+    if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+      Self.RequireCompleteType(OpRange.getBegin(), DestType, 0);
+    }
   }
 
   InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
index a6a3535d68d0f07de240ced92b171a1e9074feef..d24f7f01b818dcb83a59818b18d773d2b175b3e1 100644 (file)
@@ -20,6 +20,7 @@
 #include "clang/AST/TypeVisitor.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/TargetInfo.h"
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/ParsedTemplate.h"
@@ -4529,6 +4530,8 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
   case NPV_NullPointer:
     S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
     Converted = TemplateArgument(ParamType, /*isNullPtr*/true);
+    if (S.Context.getTargetInfo().getCXXABI().isMicrosoft())
+      S.RequireCompleteType(Arg->getExprLoc(), ParamType, 0);
     return false;
   case NPV_NotNullPointer:
     break;
index c9ed62924ec6f03f86dd651e47ab00588f42cd9b..32fcbd3d6bf0d398e116a0b6c7bc174fe7453570 100644 (file)
@@ -59,8 +59,8 @@ void ReadFields() {
 // them right in class templates.
 // CHECK: call {{.*}} @"\01??$ReadField@US@@$0A@@@YAHAAUS@@@Z"
 // CHECK: call {{.*}} @"\01??$ReadField@UM@@$0A@@@YAHAAUM@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UV@@$FA@A@@@YAHAAUV@@@Z"
-// CHECK: call {{.*}} @"\01??$ReadField@UU@@$GA@A@A@@@YAHAAUU@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UV@@$FA@?0@@YAHAAUV@@@Z"
+// CHECK: call {{.*}} @"\01??$ReadField@UU@@$GA@A@?0@@YAHAAUU@@@Z"
 
 // Non-polymorphic null data memptr vs first field memptr.  MSVC mangles these
 // the same.