Skip to content

[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

Merged
merged 2 commits into from
Jun 21, 2024

Conversation

MaxEW707
Copy link
Contributor

@MaxEW707 MaxEW707 commented May 17, 2024

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;
}

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels May 17, 2024
@llvmbot
Copy link
Member

llvmbot commented May 17, 2024

@llvm/pr-subscribers-clang

Author: Max Winkler (MaxEW707)

Changes

https://godbolt.org/z/G1K8Wszn9 for reference.

Starting with MSVC 1920+, VS2019, C++17 auto NTTP now adds M &lt;type&gt; 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&lt;auto&gt;
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&lt;&amp;i&gt; x;
}

Full diff: https://github.com/llvm/llvm-project/pull/92477.diff

3 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+7)
  • (modified) clang/lib/AST/MicrosoftMangle.cpp (+60-3)
  • (modified) clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp (+31)
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"
+
 }

@MaxEW707 MaxEW707 force-pushed the mew/nttp-auto-ptr-fptr-ms-mangle-fix branch from 76f732d to 940187a Compare May 17, 2024 04:37
@dwblaikie dwblaikie requested a review from zmodem May 20, 2024 18:17
@MaxEW707
Copy link
Contributor Author

Friendly ping @rnk @efriedma-quic @zmodem

Copy link
Collaborator

@efriedma-quic efriedma-quic left a 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?

Copy link
Collaborator

@zmodem zmodem left a 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)

@MaxEW707
Copy link
Contributor Author

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.

Your commit message mentions variables, function pointers, and member function pointers... is there anything else we need to handle? Null pointers? Integers?

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.

@MaxEW707 MaxEW707 merged commit 7b906d4 into llvm:main Jun 21, 2024
5 checks passed
@MaxEW707 MaxEW707 deleted the mew/nttp-auto-ptr-fptr-ms-mangle-fix branch June 21, 2024 02:49
MaxEW707 added a commit that referenced this pull request Jun 27, 2024
…, 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.
lravenclaw pushed a commit to lravenclaw/llvm-project that referenced this pull request Jul 3, 2024
…, 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.
MaxEW707 added a commit that referenced this pull request Jul 4, 2024
Fixes #70899.

This is a continuation of
#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.
kbluck pushed a commit to kbluck/llvm-project that referenced this pull request Jul 6, 2024
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.
AlexisPerry pushed a commit to llvm-project-tlp/llvm-project that referenced this pull request Jul 9, 2024
…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;
}
```
AlexisPerry pushed a commit to llvm-project-tlp/llvm-project that referenced this pull request Jul 9, 2024
…, 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants