From: David Majnemer Date: Thu, 6 Feb 2014 10:59:19 +0000 (+0000) Subject: MS ABI: Tweak pointer-to-member mangling/inheritance model selection X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=595bf5c17f5f395d14c801b884d8569424cc34d0;p=clang MS ABI: Tweak pointer-to-member mangling/inheritance model selection 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 --- diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 8563f2e291..f02dfc72ee 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -383,43 +383,38 @@ void MicrosoftCXXNameMangler::mangleMemberDataPointer(const CXXRecordDecl *RD, // ::= $F // ::= $G - 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(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()) { - const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); + const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); if (MPT->isMemberFunctionPointerType()) mangleMemberFunctionPointer(RD, 0); else diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 499e8b18be..5d49225ac4 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -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); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index a6a3535d68..d24f7f01b8 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -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; diff --git a/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp b/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp index c9ed62924e..32fcbd3d6b 100644 --- a/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp +++ b/test/CodeGenCXX/mangle-ms-templates-memptrs.cpp @@ -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.