-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang-cl][AST] Fix auto NTTP MSVC 1920+ mangling for pointer types #92477
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang-cl][AST] Fix auto NTTP MSVC 1920+ mangling for pointer types #92477
Conversation
@llvm/pr-subscribers-clang Author: Max Winkler (MaxEW707) Changeshttps://godbolt.org/z/G1K8Wszn9 for reference. Starting with MSVC 1920+, VS2019, C++17 auto NTTP now adds Here is a small example. The godbolt has more thorough examples.
Full diff: https://github.com/llvm/llvm-project/pull/92477.diff 3 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a3c8e4141ca54..80ea74ed295f9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -79,6 +79,13 @@ ABI Changes in This Version
- Fixed Microsoft calling convention when returning classes that have a deleted
copy assignment operator. Such a class should be returned indirectly.
+- Fixed Microsoft name mangling for auto non-type template arguments of pointer
+ type for MSVC 1920+. This change resolves incompatibilities with code compiled
+ by MSVC 1920+ but will introduce incompatibilities with code compiled by
+ earlier versions of Clang unless such code is built with the compiler option
+ `-fms-compatibility-version=19.14` to imitate the MSVC 1914 mangling behavior.
+
+
AST Dumping Potentially Breaking Changes
----------------------------------------
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 36d611750ca48..627c4511f2816 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -372,6 +372,11 @@ class MicrosoftCXXNameMangler {
void mangleMemberFunctionPointer(const CXXRecordDecl *RD,
const CXXMethodDecl *MD,
StringRef Prefix = "$");
+ void mangleFunctionPointer(const FunctionDecl *FD,
+ const NonTypeTemplateParmDecl *PD,
+ QualType TemplateArgType);
+ void mangleVarDecl(const VarDecl *VD, const NonTypeTemplateParmDecl *PD,
+ QualType TemplateArgType);
void mangleMemberFunctionPointerInClassNTTP(const CXXRecordDecl *RD,
const CXXMethodDecl *MD);
void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
@@ -799,6 +804,50 @@ MicrosoftCXXNameMangler::mangleMemberFunctionPointer(const CXXRecordDecl *RD,
mangleNumber(VBTableOffset);
}
+void MicrosoftCXXNameMangler::mangleFunctionPointer(
+ const FunctionDecl *FD, const NonTypeTemplateParmDecl *PD,
+ QualType TemplateArgType) {
+ // <func-ptr> ::= $1? <mangled-name>
+ // <func-ptr> ::= <auto-nttp>
+ //
+ // <auto-nttp> ::= $ M <type> 1? <mangled-name>
+ Out << '$';
+
+ if (getASTContext().getLangOpts().isCompatibleWithMSVC(
+ LangOptions::MSVC2019) &&
+ PD && PD->getType()->getTypeClass() == Type::Auto &&
+ !TemplateArgType.isNull()) {
+ Out << "M";
+ mangleType(TemplateArgType, SourceRange(), QMM_Drop);
+ }
+
+ Out << "1?";
+ mangleName(FD);
+ mangleFunctionEncoding(FD, /*ShouldMangle=*/true);
+}
+
+void MicrosoftCXXNameMangler::mangleVarDecl(const VarDecl *VD,
+ const NonTypeTemplateParmDecl *PD,
+ QualType TemplateArgType) {
+ // <var-ptr> ::= $1? <mangled-name>
+ // <var-ptr> ::= <auto-nttp>
+ //
+ // <auto-nttp> ::= $ M <type> 1? <mangled-name>
+ Out << '$';
+
+ if (getASTContext().getLangOpts().isCompatibleWithMSVC(
+ LangOptions::MSVC2019) &&
+ PD && PD->getType()->getTypeClass() == Type::Auto &&
+ !TemplateArgType.isNull()) {
+ Out << "M";
+ mangleType(TemplateArgType, SourceRange(), QMM_Drop);
+ }
+
+ Out << "1?";
+ mangleName(VD);
+ mangleVariableEncoding(VD);
+}
+
void MicrosoftCXXNameMangler::mangleMemberFunctionPointerInClassNTTP(
const CXXRecordDecl *RD, const CXXMethodDecl *MD) {
// <nttp-class-member-function-pointer> ::= <member-function-pointer>
@@ -1552,6 +1601,9 @@ void MicrosoftCXXNameMangler::mangleIntegerLiteral(
const llvm::APSInt &Value, const NonTypeTemplateParmDecl *PD,
QualType TemplateArgType) {
// <integer-literal> ::= $0 <number>
+ // <integer-literal> ::= <auto-nttp>
+ //
+ // <auto-nttp> ::= $ M <type> 0 <number>
Out << "$";
// Since MSVC 2019, add 'M[<type>]' after '$' for auto template parameter when
@@ -1629,8 +1681,11 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
// ::= <member-data-pointer>
// ::= <member-function-pointer>
// ::= $ <constant-value>
+ // ::= $ <auto-nttp-constant-value>
// ::= <template-args>
//
+ // <auto-nttp-constant-value> ::= M <type> <constant-value>
+ //
// <constant-value> ::= 0 <number> # integer
// ::= 1 <mangled-name> # address of D
// ::= 2 <type> <typed-constant-value>* @ # struct
@@ -1678,15 +1733,17 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
mangleMemberFunctionPointer(
MD->getParent()->getMostRecentNonInjectedDecl(), MD);
} else {
- Out << "$1?";
- mangleName(FD);
- mangleFunctionEncoding(FD, /*ShouldMangle=*/true);
+ mangleFunctionPointer(FD, cast<NonTypeTemplateParmDecl>(Parm),
+ TA.getParamTypeForDecl());
}
} else if (TA.getParamTypeForDecl()->isRecordType()) {
Out << "$";
auto *TPO = cast<TemplateParamObjectDecl>(ND);
mangleTemplateArgValue(TPO->getType().getUnqualifiedType(),
TPO->getValue(), TplArgKind::ClassNTTP);
+ } else if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+ mangleVarDecl(VD, cast<NonTypeTemplateParmDecl>(Parm),
+ TA.getParamTypeForDecl());
} else {
mangle(ND, "$1?");
}
diff --git a/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp b/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp
index c17f5f5e4477f..ff5395cea75eb 100644
--- a/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp
@@ -18,6 +18,12 @@ auto AutoFunc() {
return a;
}
+int Func();
+int Func2();
+
+int i;
+int j;
+
void template_mangling() {
AutoFunc<1>();
// AFTER: call {{.*}} @"??$AutoFunc@$MH00@@YA?A?<auto>@@XZ"
@@ -44,4 +50,29 @@ void template_mangling() {
AutoParmsTemplate<(unsigned long)1, 9223372036854775807LL> c2;
// AFTER: call {{.*}} @"??0?$AutoParmsTemplate@$MK00$M_J0HPPPPPPPPPPPPPPP@@@QEAA@XZ"
// BEFORE: call {{.*}} @"??0?$AutoParmsTemplate@$00$0HPPPPPPPPPPPPPPP@@@QEAA@XZ"
+
+ AutoFunc<&i>();
+ // AFTER: call {{.*}} @"??$AutoFunc@$MPEAH1?i@@3HA@@YA?A?<auto>@@XZ"
+ // BEFORE: call {{.*}} @"??$AutoFunc@$1?i@@3HA@@YA?A?<auto>@@XZ"
+
+ AutoParmTemplate<&i> auto_int_ptr;
+ // AFTER: call {{.*}} @"??0?$AutoParmTemplate@$MPEAH1?i@@3HA@@QEAA@XZ"
+ // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$1?i@@3HA@@QEAA@XZ"
+
+ AutoParmsTemplate<&i, &j> auto_int_ptrs;
+ // AFTER: call {{.*}} @"??0?$AutoParmsTemplate@$MPEAH1?i@@3HA$MPEAH1?j@@3HA@@QEAA@XZ"
+ // BEFORE: call {{.*}} @"??0?$AutoParmsTemplate@$1?i@@3HA$1?j@@3HA@@QEAA@XZ"
+
+ AutoFunc<&Func>();
+ // AFTER: call {{.*}} @"??$AutoFunc@$MP6AHXZ1?Func@@YAHXZ@@YA?A?<auto>@@XZ"
+ // BEFORE: call {{.*}} @"??$AutoFunc@$1?Func@@YAHXZ@@YA?A?<auto>@@XZ"
+
+ AutoParmTemplate<&Func> auto_func_ptr;
+ // AFTER: call {{.*}} @"??0?$AutoParmTemplate@$MP6AHXZ1?Func@@YAHXZ@@QEAA@XZ"
+ // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$1?Func@@YAHXZ@@QEAA@XZ"
+
+ AutoParmsTemplate<&Func, &Func2> auto_func_ptrs;
+ // AFTER: call {{.*}} @"??0?$AutoParmsTemplate@$MP6AHXZ1?Func@@YAHXZ$MP6AHXZ1?Func2@@YAHXZ@@QEAA@XZ"
+ // BEFORE: call {{.*}} @"??0?$AutoParmsTemplate@$1?Func@@YAHXZ$1?Func2@@YAHXZ@@QEAA@XZ"
+
}
|
76f732d
to
940187a
Compare
Friendly ping @rnk @efriedma-quic @zmodem |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Your commit message mentions variables, function pointers, and member function pointers... is there anything else we need to handle? Null pointers? Integers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay (please feel free to ping earlier). This looks good to me.
Will llvm/lib/Demangle/MicrosoftDemangle.cpp also need to be updated? (That could be done separately)
Possibly. I didn't realize the llvm-project implemented demangling as well. I'll take a look at the demangle code after I merge this PR and get a separate PR up if it needs updating.
auto return functions that have NTTP parameters need fixing: #92204 Integers were fixed in this commit here: 83286a1 I need to check null pointers. I haven't checked C++20 float point or literal class types either. |
…, pointer to data and integral types (#96590) As cited here, #92477, undname needs updating to support the new auto NTTP name mangling. In short the deduced type of the auto NTTP parameter is mangled as `$M <type> <nttp-param>`. However the deduced type is not printed for the undecorated name so the `$M <type>` is parsed but simply ignored when stringifying the generated AST.
…, pointer to data and integral types (llvm#96590) As cited here, llvm#92477, undname needs updating to support the new auto NTTP name mangling. In short the deduced type of the auto NTTP parameter is mangled as `$M <type> <nttp-param>`. However the deduced type is not printed for the undecorated name so the `$M <type>` is parsed but simply ignored when stringifying the generated AST.
Fixes llvm#70899. This is a continuation of llvm#92477 for pointers to member data and pointers to member functions. The mangled name must be prefixed with `$M <mangled-type>` for the deduced type of the nttp parameter.
…lvm#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; } ```
…, pointer to data and integral types (llvm#96590) As cited here, llvm#92477, undname needs updating to support the new auto NTTP name mangling. In short the deduced type of the auto NTTP parameter is mangled as `$M <type> <nttp-param>`. However the deduced type is not printed for the undecorated name so the `$M <type>` is parsed but simply ignored when stringifying the generated AST.
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.