Index: clang/include/clang/Basic/LangOptions.h =================================================================== --- clang/include/clang/Basic/LangOptions.h +++ clang/include/clang/Basic/LangOptions.h @@ -119,6 +119,7 @@ MSVC2017 = 1910, MSVC2017_5 = 1912, MSVC2017_7 = 1914, + MSVC2019 = 1920, }; /// Clang versions with different platform ABI conformance. Index: clang/lib/AST/MicrosoftMangle.cpp =================================================================== --- clang/lib/AST/MicrosoftMangle.cpp +++ clang/lib/AST/MicrosoftMangle.cpp @@ -378,8 +378,10 @@ void mangleFunctionClass(const FunctionDecl *FD); void mangleCallingConvention(CallingConv CC); void mangleCallingConvention(const FunctionType *T); - void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean); - void mangleExpression(const Expr *E); + void mangleIntegerLiteral(const llvm::APSInt &Number, + const NonTypeTemplateParmDecl *PD = nullptr, + QualType *TemplateArgType = nullptr); + void mangleExpression(const Expr *E, const NonTypeTemplateParmDecl *PD); void mangleThrowSpecification(const FunctionProtoType *T); void mangleTemplateArgs(const TemplateDecl *TD, @@ -1357,24 +1359,35 @@ mangleUnqualifiedName(TD); } -void MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value, - bool IsBoolean) { - // ::= $0 - Out << "$0"; - // Make sure booleans are encoded as 0/1. - if (IsBoolean && Value.getBoolValue()) - mangleNumber(1); - else if (Value.isSigned()) +void MicrosoftCXXNameMangler::mangleIntegerLiteral( + const llvm::APSInt &Value, const NonTypeTemplateParmDecl *PD, + QualType *TemplateArgType) { + // ::= $ [] 0 + Out << "$"; + + // mangle argument type if parmeter is auto + if (getASTContext().getLangOpts().isCompatibleWithMSVC( + LangOptions::MSVC2019) && + PD && PD->getType()->getTypeClass() == Type::Auto && TemplateArgType) { + Out << "M"; + mangleType(*TemplateArgType, SourceRange(), QMM_Drop); + } + + Out << "0"; + + if (Value.isSigned()) mangleNumber(Value.getSExtValue()); else mangleNumber(Value.getZExtValue()); } -void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { +void MicrosoftCXXNameMangler::mangleExpression( + const Expr *E, const NonTypeTemplateParmDecl *PD) { // See if this is a constant expression. llvm::APSInt Value; if (E->isIntegerConstantExpr(Value, Context.getASTContext())) { - mangleIntegerLiteral(Value, E->getType()->isBooleanType()); + QualType T = E->getType(); + mangleIntegerLiteral(Value, PD, &T); return; } @@ -1448,10 +1461,12 @@ } break; } - case TemplateArgument::Integral: + case TemplateArgument::Integral: { + QualType T = TA.getIntegralType(); mangleIntegerLiteral(TA.getAsIntegral(), - TA.getIntegralType()->isBooleanType()); + cast(Parm), &T); break; + } case TemplateArgument::NullPtr: { QualType T = TA.getNullPtrType(); if (const MemberPointerType *MPT = T->getAs()) { @@ -1473,16 +1488,18 @@ // However, we are free to use 0 *if* we would use multiple fields for // non-nullptr member pointers. if (!RD->nullFieldOffsetIsZero()) { - mangleIntegerLiteral(llvm::APSInt::get(-1), /*IsBoolean=*/false); + mangleIntegerLiteral(llvm::APSInt::get(-1), + cast(Parm), &T); return; } } } - mangleIntegerLiteral(llvm::APSInt::getUnsigned(0), /*IsBoolean=*/false); + mangleIntegerLiteral(llvm::APSInt::getUnsigned(0), + cast(Parm), &T); break; } case TemplateArgument::Expression: - mangleExpression(TA.getAsExpr()); + mangleExpression(TA.getAsExpr(), cast(Parm)); break; case TemplateArgument::Pack: { ArrayRef TemplateArgs = TA.getPackAsArray(); @@ -1814,8 +1831,7 @@ if (Context.getASTContext().addressSpaceMapManglingFor(AS)) { unsigned TargetAS = Context.getASTContext().getTargetAddressSpace(AS); Extra.mangleSourceName("_AS"); - Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(TargetAS), - /*IsBoolean*/ false); + Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(TargetAS)); } else { switch (AS) { default: @@ -2700,8 +2716,7 @@ Stream << "?$"; Extra.mangleSourceName("__vector"); Extra.mangleType(QualType(ET, 0), Range, QMM_Escape); - Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumElements()), - /*IsBoolean=*/false); + Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumElements())); mangleArtificialTagType(TTK_Union, TemplateMangling, {"__clang"}); } @@ -2940,7 +2955,7 @@ Stream << "?$"; Extra.mangleSourceName("ocl_pipe"); Extra.mangleType(ElementType, Range, QMM_Escape); - Extra.mangleIntegerLiteral(llvm::APSInt::get(T->isReadOnly()), true); + Extra.mangleIntegerLiteral(llvm::APSInt::get(T->isReadOnly())); mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"}); } @@ -2980,8 +2995,7 @@ Extra.mangleSourceName("_UExtInt"); else Extra.mangleSourceName("_ExtInt"); - Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumBits()), - /*IsBoolean=*/false); + Extra.mangleIntegerLiteral(llvm::APSInt::getUnsigned(T->getNumBits())); mangleArtificialTagType(TTK_Struct, TemplateMangling, {"__clang"}); } Index: clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19.20 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-windows-msvc | FileCheck %s + +template +class AutoParmTemplate { +public: + AutoParmTemplate() {} +}; + +template +class AutoParmsTemplate { +public: + AutoParmsTemplate() {} +}; + +void template_mangling() { + AutoParmTemplate<0> auto_int; + // CHECK: call {{.*}} @"??0?$AutoParmTemplate@$MH0A@@@QEAA@XZ" + AutoParmTemplate auto_bool; + // CHECK: call {{.*}} @"??0?$AutoParmTemplate@$M_N0A@@@QEAA@XZ" + AutoParmTemplate<'a'> auto_char; + // CHECK: call {{.*}} @"??0?$AutoParmTemplate@$MD0GB@@@QEAA@XZ" + AutoParmTemplate<9223372036854775807LL> int64_max; + // CHECK: call {{.*}} @"??0?$AutoParmTemplate@$M_J0HPPPPPPPPPPPPPPP@@@QEAA@XZ" + AutoParmTemplate<-9223372036854775807LL - 1LL> int64_min; + // CHECK: call {{.*}} @"??0?$AutoParmTemplate@$M_J0?IAAAAAAAAAAAAAAA@@@QEAA@XZ" + AutoParmTemplate<(unsigned long long)-1> uint64_neg_1; + // CHECK: call {{.*}} @"??0?$AutoParmTemplate@$M_K0?0@@QEAA@XZ" + + AutoParmsTemplate<0, false, 'a'> c1; + // CHECK: call {{.*}} @"??0?$AutoParmsTemplate@$MH0A@$M_N0A@$MD0GB@@@QEAA@XZ" + AutoParmsTemplate<(unsigned long)1, 9223372036854775807LL> c2; + // CHECK: call {{.*}} @"??0?$AutoParmsTemplate@$MK00$M_J0HPPPPPPPPPPPPPPP@@@QEAA@XZ" +}