Skip to content

Commit 7b906d4

Browse files
authored
[clang-cl][AST] Fix auto NTTP MSVC 1920+ mangling for pointer types (#92477)
https://godbolt.org/z/G1K8Wszn9 for reference. Starting with MSVC 1920+, VS2019, C++17 auto NTTP now adds `M <type>` to the mangled name to avoid name collisions with different deduced types. This PR fixes pointers. Pointers to members will be fixed in an upcoming PR. Here is a small example. The godbolt has more thorough examples. ``` template<auto> struct AutoParmTemplate { AutoParmTemplate() {} }; int i; int main() { // MSVC 1916: ??0?$AutoParmTemplate@$1?i@@3Ha@@qeaa@XZ // MSVC 1929: ??0?$AutoParmTemplate@$MPEAH1?i@@3Ha@@qeaa@XZ // Clang: ??0?$AutoParmTemplate@$1?i@@3Ha@@qeaa@XZ AutoParmTemplate<&i> x; } ```
1 parent e1c03dd commit 7b906d4

File tree

3 files changed

+98
-3
lines changed

3 files changed

+98
-3
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ ABI Changes in This Version
9595
- Fixed Microsoft calling convention when returning classes that have a deleted
9696
copy assignment operator. Such a class should be returned indirectly.
9797

98+
- Fixed Microsoft name mangling for auto non-type template arguments of pointer
99+
type for MSVC 1920+. This change resolves incompatibilities with code compiled
100+
by MSVC 1920+ but will introduce incompatibilities with code compiled by
101+
earlier versions of Clang unless such code is built with the compiler option
102+
`-fms-compatibility-version=19.14` to imitate the MSVC 1914 mangling behavior.
103+
104+
98105
AST Dumping Potentially Breaking Changes
99106
----------------------------------------
100107

clang/lib/AST/MicrosoftMangle.cpp

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ class MicrosoftCXXNameMangler {
372372
void mangleMemberFunctionPointer(const CXXRecordDecl *RD,
373373
const CXXMethodDecl *MD,
374374
StringRef Prefix = "$");
375+
void mangleFunctionPointer(const FunctionDecl *FD,
376+
const NonTypeTemplateParmDecl *PD,
377+
QualType TemplateArgType);
378+
void mangleVarDecl(const VarDecl *VD, const NonTypeTemplateParmDecl *PD,
379+
QualType TemplateArgType);
375380
void mangleMemberFunctionPointerInClassNTTP(const CXXRecordDecl *RD,
376381
const CXXMethodDecl *MD);
377382
void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
@@ -799,6 +804,50 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD,
799804
mangleNumber(VBTableOffset);
800805
}
801806

807+
void MicrosoftCXXNameMangler::mangleFunctionPointer(
808+
const FunctionDecl *FD, const NonTypeTemplateParmDecl *PD,
809+
QualType TemplateArgType) {
810+
// <func-ptr> ::= $1? <mangled-name>
811+
// <func-ptr> ::= <auto-nttp>
812+
//
813+
// <auto-nttp> ::= $ M <type> 1? <mangled-name>
814+
Out << '$';
815+
816+
if (getASTContext().getLangOpts().isCompatibleWithMSVC(
817+
LangOptions::MSVC2019) &&
818+
PD && PD->getType()->getTypeClass() == Type::Auto &&
819+
!TemplateArgType.isNull()) {
820+
Out << "M";
821+
mangleType(TemplateArgType, SourceRange(), QMM_Drop);
822+
}
823+
824+
Out << "1?";
825+
mangleName(FD);
826+
mangleFunctionEncoding(FD, /*ShouldMangle=*/true);
827+
}
828+
829+
void MicrosoftCXXNameMangler::mangleVarDecl(const VarDecl *VD,
830+
const NonTypeTemplateParmDecl *PD,
831+
QualType TemplateArgType) {
832+
// <var-ptr> ::= $1? <mangled-name>
833+
// <var-ptr> ::= <auto-nttp>
834+
//
835+
// <auto-nttp> ::= $ M <type> 1? <mangled-name>
836+
Out << '$';
837+
838+
if (getASTContext().getLangOpts().isCompatibleWithMSVC(
839+
LangOptions::MSVC2019) &&
840+
PD && PD->getType()->getTypeClass() == Type::Auto &&
841+
!TemplateArgType.isNull()) {
842+
Out << "M";
843+
mangleType(TemplateArgType, SourceRange(), QMM_Drop);
844+
}
845+
846+
Out << "1?";
847+
mangleName(VD);
848+
mangleVariableEncoding(VD);
849+
}
850+
802851
void MicrosoftCXXNameMangler::mangleMemberFunctionPointerInClassNTTP(
803852
const CXXRecordDecl *RD, const CXXMethodDecl *MD) {
804853
// <nttp-class-member-function-pointer> ::= <member-function-pointer>
@@ -1555,6 +1604,9 @@ void MicrosoftCXXNameMangler::mangleIntegerLiteral(
15551604
const llvm::APSInt &Value, const NonTypeTemplateParmDecl *PD,
15561605
QualType TemplateArgType) {
15571606
// <integer-literal> ::= $0 <number>
1607+
// <integer-literal> ::= <auto-nttp>
1608+
//
1609+
// <auto-nttp> ::= $ M <type> 0 <number>
15581610
Out << "$";
15591611

15601612
// Since MSVC 2019, add 'M[<type>]' after '$' for auto template parameter when
@@ -1632,8 +1684,11 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
16321684
// ::= <member-data-pointer>
16331685
// ::= <member-function-pointer>
16341686
// ::= $ <constant-value>
1687+
// ::= $ <auto-nttp-constant-value>
16351688
// ::= <template-args>
16361689
//
1690+
// <auto-nttp-constant-value> ::= M <type> <constant-value>
1691+
//
16371692
// <constant-value> ::= 0 <number> # integer
16381693
// ::= 1 <mangled-name> # address of D
16391694
// ::= 2 <type> <typed-constant-value>* @ # struct
@@ -1681,15 +1736,17 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
16811736
mangleMemberFunctionPointer(
16821737
MD->getParent()->getMostRecentNonInjectedDecl(), MD);
16831738
} else {
1684-
Out << "$1?";
1685-
mangleName(FD);
1686-
mangleFunctionEncoding(FD, /*ShouldMangle=*/true);
1739+
mangleFunctionPointer(FD, cast<NonTypeTemplateParmDecl>(Parm),
1740+
TA.getParamTypeForDecl());
16871741
}
16881742
} else if (TA.getParamTypeForDecl()->isRecordType()) {
16891743
Out << "$";
16901744
auto *TPO = cast<TemplateParamObjectDecl>(ND);
16911745
mangleTemplateArgValue(TPO->getType().getUnqualifiedType(),
16921746
TPO->getValue(), TplArgKind::ClassNTTP);
1747+
} else if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
1748+
mangleVarDecl(VD, cast<NonTypeTemplateParmDecl>(Parm),
1749+
TA.getParamTypeForDecl());
16931750
} else {
16941751
mangle(ND, "$1?");
16951752
}

clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ auto AutoFunc() {
1818
return a;
1919
}
2020

21+
int Func();
22+
int Func2();
23+
24+
int i;
25+
int j;
26+
2127
void template_mangling() {
2228
AutoFunc<1>();
2329
// AFTER: call {{.*}} @"??$AutoFunc@$MH00@@YA?A?<auto>@@XZ"
@@ -44,4 +50,29 @@ void template_mangling() {
4450
AutoParmsTemplate<(unsigned long)1, 9223372036854775807LL> c2;
4551
// AFTER: call {{.*}} @"??0?$AutoParmsTemplate@$MK00$M_J0HPPPPPPPPPPPPPPP@@@QEAA@XZ"
4652
// BEFORE: call {{.*}} @"??0?$AutoParmsTemplate@$00$0HPPPPPPPPPPPPPPP@@@QEAA@XZ"
53+
54+
AutoFunc<&i>();
55+
// AFTER: call {{.*}} @"??$AutoFunc@$MPEAH1?i@@3HA@@YA?A?<auto>@@XZ"
56+
// BEFORE: call {{.*}} @"??$AutoFunc@$1?i@@3HA@@YA?A?<auto>@@XZ"
57+
58+
AutoParmTemplate<&i> auto_int_ptr;
59+
// AFTER: call {{.*}} @"??0?$AutoParmTemplate@$MPEAH1?i@@3HA@@QEAA@XZ"
60+
// BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$1?i@@3HA@@QEAA@XZ"
61+
62+
AutoParmsTemplate<&i, &j> auto_int_ptrs;
63+
// AFTER: call {{.*}} @"??0?$AutoParmsTemplate@$MPEAH1?i@@3HA$MPEAH1?j@@3HA@@QEAA@XZ"
64+
// BEFORE: call {{.*}} @"??0?$AutoParmsTemplate@$1?i@@3HA$1?j@@3HA@@QEAA@XZ"
65+
66+
AutoFunc<&Func>();
67+
// AFTER: call {{.*}} @"??$AutoFunc@$MP6AHXZ1?Func@@YAHXZ@@YA?A?<auto>@@XZ"
68+
// BEFORE: call {{.*}} @"??$AutoFunc@$1?Func@@YAHXZ@@YA?A?<auto>@@XZ"
69+
70+
AutoParmTemplate<&Func> auto_func_ptr;
71+
// AFTER: call {{.*}} @"??0?$AutoParmTemplate@$MP6AHXZ1?Func@@YAHXZ@@QEAA@XZ"
72+
// BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$1?Func@@YAHXZ@@QEAA@XZ"
73+
74+
AutoParmsTemplate<&Func, &Func2> auto_func_ptrs;
75+
// AFTER: call {{.*}} @"??0?$AutoParmsTemplate@$MP6AHXZ1?Func@@YAHXZ$MP6AHXZ1?Func2@@YAHXZ@@QEAA@XZ"
76+
// BEFORE: call {{.*}} @"??0?$AutoParmsTemplate@$1?Func@@YAHXZ$1?Func2@@YAHXZ@@QEAA@XZ"
77+
4778
}

0 commit comments

Comments
 (0)