diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h --- a/clang/include/clang/Basic/LangOptions.h +++ b/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. diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/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 = QualType()); + 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.isNull()) { + 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. if (Optional Value = E->getIntegerConstantExpr(Context.getASTContext())) { - mangleIntegerLiteral(*Value, E->getType()->isBooleanType()); + mangleIntegerLiteral(*Value, PD, E->getType()); 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: @@ -2707,8 +2723,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"}); } @@ -2947,7 +2962,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"}); } @@ -2987,8 +3002,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"}); } diff --git a/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp b/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp @@ -0,0 +1,39 @@ +// 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 --check-prefix=AFTER %s +// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19.14 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-windows-msvc | FileCheck --check-prefix=BEFORE %s + +template +class AutoParmTemplate { +public: + AutoParmTemplate() {} +}; + +template +class AutoParmsTemplate { +public: + AutoParmsTemplate() {} +}; + +void template_mangling() { + AutoParmTemplate<0> auto_int; + // AFTER: call {{.*}} @"??0?$AutoParmTemplate@$MH0A@@@QEAA@XZ" + // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$0A@@@QEAA@XZ" + AutoParmTemplate<'a'> auto_char; + // AFTER: call {{.*}} @"??0?$AutoParmTemplate@$MD0GB@@@QEAA@XZ" + // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$0GB@@@QEAA@XZ" + AutoParmTemplate<9223372036854775807LL> int64_max; + // AFTER: call {{.*}} @"??0?$AutoParmTemplate@$M_J0HPPPPPPPPPPPPPPP@@@QEAA@XZ" + // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$0HPPPPPPPPPPPPPPP@@@QEAA@XZ" + AutoParmTemplate<-9223372036854775807LL - 1LL> int64_min; + // AFTER: call {{.*}} @"??0?$AutoParmTemplate@$M_J0?IAAAAAAAAAAAAAAA@@@QEAA@XZ" + // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$0?IAAAAAAAAAAAAAAA@@@QEAA@XZ" + AutoParmTemplate<(unsigned long long)-1> uint64_neg_1; + // AFTER: call {{.*}} @"??0?$AutoParmTemplate@$M_K0?0@@QEAA@XZ" + // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$0?0@@QEAA@XZ" + + AutoParmsTemplate<0, false, 'a'> c1; + // AFTER: call {{.*}} @"??0?$AutoParmsTemplate@$MH0A@$M_N0A@$MD0GB@@@QEAA@XZ" + // BEFORE: call {{.*}} @"??0?$AutoParmsTemplate@$0A@$0A@$0GB@@@QEAA@XZ" + AutoParmsTemplate<(unsigned long)1, 9223372036854775807LL> c2; + // AFTER: call {{.*}} @"??0?$AutoParmsTemplate@$MK00$M_J0HPPPPPPPPPPPPPPP@@@QEAA@XZ" + // BEFORE: call {{.*}} @"??0?$AutoParmsTemplate@$00$0HPPPPPPPPPPPPPPP@@@QEAA@XZ" +}