[clang] [Clang] [AST] Fix placeholder return type name mangling for MSVC 1920+ / VS2019+ (PR #102848)

Max Winkler via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 13 18:42:27 PDT 2024


https://github.com/MaxEW707 updated https://github.com/llvm/llvm-project/pull/102848

>From e5071bd3be7607730654e5aa815a535db130fdee Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.winkler at gmail.com>
Date: Sun, 11 Aug 2024 16:50:58 -0700
Subject: [PATCH 1/5] Fix placeholder return type name mangling for MSVC 1920+

---
 clang/lib/AST/MicrosoftMangle.cpp             | 172 ++++++++-
 .../test/CodeGenCXX/mangle-ms-auto-return.cpp | 358 ++++++++++++++++++
 .../mangle-ms-auto-templates-memptrs.cpp      |  12 +-
 .../mangle-ms-auto-templates-nullptr.cpp      |   2 +-
 .../CodeGenCXX/mangle-ms-auto-templates.cpp   |   6 +-
 5 files changed, 531 insertions(+), 19 deletions(-)
 create mode 100644 clang/test/CodeGenCXX/mangle-ms-auto-return.cpp

diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 28f66e71c2f2de..ecbddc1aacc073 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -408,6 +408,9 @@ class MicrosoftCXXNameMangler {
   void mangleSourceName(StringRef Name);
   void mangleNestedName(GlobalDecl GD);
 
+  void mangleAutoReturnType(QualType T, SourceRange Range,
+                            QualifierMangleMode QMM);
+
 private:
   bool isStructorDecl(const NamedDecl *ND) const {
     return ND == Structor || getStructor(ND) == Structor;
@@ -477,6 +480,15 @@ class MicrosoftCXXNameMangler {
                           SourceRange Range);
   void mangleObjCKindOfType(const ObjCObjectType *T, Qualifiers Quals,
                             SourceRange Range);
+
+  void mangleAutoReturnType(const MemberPointerType *T, Qualifiers Quals,
+                            SourceRange Range);
+  void mangleAutoReturnType(const PointerType *T, Qualifiers Quals,
+                            SourceRange Range);
+  void mangleAutoReturnType(const LValueReferenceType *T, Qualifiers Quals,
+                            SourceRange Range);
+  void mangleAutoReturnType(const RValueReferenceType *T, Qualifiers Quals,
+                            SourceRange Range);
 };
 }
 
@@ -2494,8 +2506,61 @@ void MicrosoftCXXNameMangler::mangleAddressSpaceType(QualType T,
   mangleArtificialTagType(TagTypeKind::Struct, ASMangling, {"__clang"});
 }
 
+void MicrosoftCXXNameMangler::mangleAutoReturnType(QualType T,
+                                                   SourceRange Range,
+                                                   QualifierMangleMode QMM) {
+  assert(getASTContext().getLangOpts().isCompatibleWithMSVC(
+             LangOptions::MSVC2019) &&
+         "Cannot mangle MSVC 2017 auto return types!");
+
+  if (isa<AutoType>(T)) {
+    const auto *AT = T->getContainedAutoType();
+    Qualifiers Quals = T.getLocalQualifiers();
+
+    if (QMM == QMM_Result)
+      Out << '?';
+    if (QMM != QMM_Drop)
+      mangleQualifiers(Quals, false);
+    Out << (AT->isDecltypeAuto() ? "_T" : "_P");
+    return;
+  }
+
+  T = T.getDesugaredType(getASTContext());
+  Qualifiers Quals = T.getLocalQualifiers();
+
+  switch (QMM) {
+  case QMM_Drop:
+  case QMM_Result:
+    break;
+  case QMM_Mangle:
+    mangleQualifiers(Quals, false);
+    break;
+  default:
+    llvm_unreachable("QMM_Escape unexpected");
+  }
+
+  const Type *ty = T.getTypePtr();
+  switch (ty->getTypeClass()) {
+  case Type::MemberPointer:
+    mangleAutoReturnType(cast<MemberPointerType>(ty), Quals, Range);
+    break;
+  case Type::Pointer:
+    mangleAutoReturnType(cast<PointerType>(ty), Quals, Range);
+    break;
+  case Type::LValueReference:
+    mangleAutoReturnType(cast<LValueReferenceType>(ty), Quals, Range);
+    break;
+  case Type::RValueReference:
+    mangleAutoReturnType(cast<RValueReferenceType>(ty), Quals, Range);
+    break;
+  default:
+    llvm_unreachable("Invalid type expected");
+  }
+}
+
 void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
                                          QualifierMangleMode QMM) {
+
   // Don't use the canonical types.  MSVC includes things like 'const' on
   // pointer arguments to function pointers that canonicalization strips away.
   T = T.getDesugaredType(getASTContext());
@@ -2900,17 +2965,51 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
       // can differ by their calling convention and are typically deduced.  So
       // we make sure that this type gets mangled properly.
       mangleType(ResultType, Range, QMM_Result);
-    } else if (const auto *AT = dyn_cast_or_null<AutoType>(
-                   ResultType->getContainedAutoType())) {
-      Out << '?';
-      mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false);
-      Out << '?';
+    } else if (IsInLambda) {
+      if (const auto *AT = ResultType->getContainedAutoType()) {
+        assert(AT->getKeyword() == AutoTypeKeyword::Auto &&
+               "should only need to mangle auto!");
+        Out << '?';
+        mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false);
+        Out << '?';
+        mangleSourceName("<auto>");
+        Out << '@';
+      } else {
+        Out << '@';
+      }
+    } else if (const auto *AT = ResultType->getContainedAutoType()) {
       assert(AT->getKeyword() != AutoTypeKeyword::GNUAutoType &&
              "shouldn't need to mangle __auto_type!");
-      mangleSourceName(AT->isDecltypeAuto() ? "<decltype-auto>" : "<auto>");
-      Out << '@';
-    } else if (IsInLambda) {
-      Out << '@';
+
+      // If we have any pointer types with the clang address space extension
+      // then defer to the custom clang mangling to keep backwards
+      // compatibility. See `mangleType(const PointerType *T, Qualifiers Quals,
+      // SourceRange Range)` for details.
+      auto UseClangMangling = [](QualType ResultType) {
+        QualType T = ResultType;
+        while (const auto *PT = dyn_cast<PointerType>(T.getTypePtr())) {
+          T = T->getPointeeType();
+          if (T.getQualifiers().hasAddressSpace())
+            return true;
+        }
+        return false;
+      };
+
+      if (getASTContext().getLangOpts().isCompatibleWithMSVC(
+              LangOptions::MSVC2019) &&
+          !UseClangMangling(ResultType)) {
+        if (D && !D->getPrimaryTemplate()) {
+          Out << '@';
+        } else {
+          mangleAutoReturnType(ResultType, Range, QMM_Result);
+        }
+      } else {
+        Out << '?';
+        mangleQualifiers(ResultType.getLocalQualifiers(), /*IsMember=*/false);
+        Out << '?';
+        mangleSourceName(AT->isDecltypeAuto() ? "<decltype-auto>" : "<auto>");
+        Out << '@';
+      }
     } else {
       if (ResultType->isVoidType())
         ResultType = ResultType.getUnqualifiedType();
@@ -4213,6 +4312,61 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
   Mangler.getStream() << '@';
 }
 
+void MicrosoftCXXNameMangler::mangleAutoReturnType(const MemberPointerType *T,
+                                                   Qualifiers Quals,
+                                                   SourceRange Range) {
+  QualType PointeeType = T->getPointeeType();
+  manglePointerCVQualifiers(Quals);
+  manglePointerExtQualifiers(Quals, PointeeType);
+  if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
+    Out << '8';
+    mangleName(T->getClass()->castAs<RecordType>()->getDecl());
+    mangleFunctionType(FPT, nullptr, true);
+  } else {
+    mangleQualifiers(PointeeType.getQualifiers(), true);
+    mangleName(T->getClass()->castAs<RecordType>()->getDecl());
+    mangleAutoReturnType(PointeeType, Range, QMM_Drop);
+  }
+}
+
+void MicrosoftCXXNameMangler::mangleAutoReturnType(const PointerType *T,
+                                                   Qualifiers Quals,
+                                                   SourceRange Range) {
+  QualType PointeeType = T->getPointeeType();
+  assert(!PointeeType.getQualifiers().hasAddressSpace() &&
+         "Unexpected address space mangling required");
+
+  manglePointerCVQualifiers(Quals);
+  manglePointerExtQualifiers(Quals, PointeeType);
+
+  if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
+    Out << '6';
+    mangleFunctionType(FPT);
+  } else {
+    mangleAutoReturnType(PointeeType, Range, QMM_Mangle);
+  }
+}
+
+void MicrosoftCXXNameMangler::mangleAutoReturnType(const LValueReferenceType *T,
+                                                   Qualifiers Quals,
+                                                   SourceRange Range) {
+  QualType PointeeType = T->getPointeeType();
+  assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!");
+  Out << 'A';
+  manglePointerExtQualifiers(Quals, PointeeType);
+  mangleAutoReturnType(PointeeType, Range, QMM_Mangle);
+}
+
+void MicrosoftCXXNameMangler::mangleAutoReturnType(const RValueReferenceType *T,
+                                                   Qualifiers Quals,
+                                                   SourceRange Range) {
+  QualType PointeeType = T->getPointeeType();
+  assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!");
+  Out << "$$Q";
+  manglePointerExtQualifiers(Quals, PointeeType);
+  mangleAutoReturnType(PointeeType, Range, QMM_Mangle);
+}
+
 MicrosoftMangleContext *MicrosoftMangleContext::create(ASTContext &Context,
                                                        DiagnosticsEngine &Diags,
                                                        bool IsAux) {
diff --git a/clang/test/CodeGenCXX/mangle-ms-auto-return.cpp b/clang/test/CodeGenCXX/mangle-ms-auto-return.cpp
new file mode 100644
index 00000000000000..9b34a9abfd75d8
--- /dev/null
+++ b/clang/test/CodeGenCXX/mangle-ms-auto-return.cpp
@@ -0,0 +1,358 @@
+// 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
+
+struct StructA {};
+
+template<class T>
+auto AutoT() { return T(); }
+
+template<class T>
+const auto AutoConstT() { return T(); }
+
+template<class T>
+volatile auto AutoVolatileT() { return T(); }
+
+template<class T>
+const volatile auto AutoConstVolatileT() { return T(); }
+
+// The qualifiers of the return type should always be emitted even for void types.
+// Void types usually have their qualifers stripped in the mangled name for MSVC ABI.
+void test_template_auto_void() {
+  AutoT<void>();
+  // CHECK: call {{.*}} @"??$AutoT at X@@YA?A_PXZ"
+
+  AutoT<const void>();
+  // CHECK: call {{.*}} @"??$AutoT@$$CBX@@YA?A_PXZ"
+
+  AutoT<volatile void>();
+  // CHECK: call {{.*}} @"??$AutoT@$$CCX@@YA?A_PXZ"
+
+  AutoT<const volatile void>();
+  // CHECK: call {{.*}} @"??$AutoT@$$CDX@@YA?A_PXZ"
+
+  AutoConstT<void>();
+  // CHECK: call {{.*}} @"??$AutoConstT at X@@YA?B_PXZ"
+
+  AutoVolatileT<void>();
+  // CHECK: call {{.*}} @"??$AutoVolatileT at X@@YA?C_PXZ"
+
+  AutoConstVolatileT<void>();
+  // CHECK: call {{.*}} @"??$AutoConstVolatileT at X@@YA?D_PXZ"
+}
+
+void test_template_auto_int() {
+  AutoT<int>();
+  // CHECK: call {{.*}} @"??$AutoT at H@@YA?A_PXZ"
+
+  AutoT<const int>();
+  // CHECK: call {{.*}} @"??$AutoT@$$CBH@@YA?A_PXZ"
+
+  AutoT<volatile int>();
+  // CHECK: call {{.*}} @"??$AutoT@$$CCH@@YA?A_PXZ"
+
+  AutoT<const volatile int>();
+  // CHECK: call {{.*}} @"??$AutoT@$$CDH@@YA?A_PXZ"
+
+  AutoConstT<int>();
+  // CHECK: call {{.*}} @"??$AutoConstT at H@@YA?B_PXZ"
+
+  AutoVolatileT<int>();
+  // CHECK: call {{.*}} @"??$AutoVolatileT at H@@YA?C_PXZ"
+
+  AutoConstVolatileT<int>();
+  // CHECK: call {{.*}} @"??$AutoConstVolatileT at H@@YA?D_PXZ"
+}
+
+void test_template_auto_struct() {
+  AutoT<StructA>();
+  // CHECK: call {{.*}} @"??$AutoT at UStructA@@@@YA?A_PXZ"
+
+  AutoT<const StructA>();
+  // CHECK: call {{.*}} @"??$AutoT@$$CBUStructA@@@@YA?A_PXZ"
+
+  AutoConstT<StructA>();
+  // CHECK: call {{.*}} @"??$AutoConstT at UStructA@@@@YA?B_PXZ"
+
+  AutoVolatileT<StructA>();
+  // CHECK: call {{.*}} @"??$AutoVolatileT at UStructA@@@@YA?C_PXZ"
+
+  AutoConstVolatileT<StructA>();
+  // CHECK: call {{.*}} @"??$AutoConstVolatileT at UStructA@@@@YA?D_PXZ"
+}
+
+void test_template_auto_ptr() {
+  AutoT<int*>();
+  // CHECK: call {{.*}} @"??$AutoT at PEAH@@YA?A_PXZ"
+
+  AutoT<const int*>();
+  // CHECK: call {{.*}} @"??$AutoT at PEBH@@YA?A_PXZ"
+
+  AutoT<const int* const>();
+  // CHECK: call {{.*}} @"??$AutoT at QEBH@@YA?A_PXZ"
+
+  AutoConstT<int*>();
+  // CHECK: call {{.*}} @"??$AutoConstT at PEAH@@YA?B_PXZ"
+
+  AutoVolatileT<int*>();
+  // CHECK: call {{.*}} @"??$AutoVolatileT at PEAH@@YA?C_PXZ"
+
+  AutoConstVolatileT<int*>();
+  // CHECK: call {{.*}} @"??$AutoConstVolatileT at PEAH@@YA?D_PXZ"
+}
+
+template<class T>
+auto* PtrAutoT() { return T(); }
+
+template<class T>
+const auto* PtrAutoConstT() { return T(); }
+
+template<class T>
+volatile auto* PtrAutoVolatileT() { return T(); }
+
+template<class T>
+const volatile auto* PtrAutoConstVolatileT() { return T(); }
+
+void test_template_ptr_auto() {
+  PtrAutoT<int*>();
+  // CHECK: call {{.*}} @"??$PtrAutoT at PEAH@@YAPEA_PXZ"
+
+  PtrAutoT<const int*>();
+  // CHECK: call {{.*}} @"??$PtrAutoT at PEBH@@YAPEA_PXZ"
+
+  PtrAutoT<const int* const>();
+  // CHECK: call {{.*}} @"??$PtrAutoT at QEBH@@YAPEA_PXZ"
+
+  PtrAutoConstT<int*>();
+  // CHECK: call {{.*}} @"??$PtrAutoConstT at PEAH@@YAPEB_PXZ"
+
+  PtrAutoVolatileT<int*>();
+  // CHECK: call {{.*}} @"??$PtrAutoVolatileT at PEAH@@YAPEC_PXZ"
+
+  PtrAutoConstVolatileT<int*>();
+  // CHECK: call {{.*}} @"??$PtrAutoConstVolatileT at PEAH@@YAPED_PXZ"
+}
+
+int func_int();
+const int func_constint();
+void func_void();
+int* func_intptr();
+
+template<class T, T v>
+auto (*FuncPtrAutoT())() { return v; }
+
+void test_template_func_ptr_auto() {
+  FuncPtrAutoT<int (*)(), &func_int>();
+  // CHECK: call {{.*}} @"??$FuncPtrAutoT at P6AHXZ$1?func_int@@YAHXZ@@YAP6A?A_PXZXZ"
+
+  FuncPtrAutoT<const int (*)(), &func_constint>();
+  // CHECK: call {{.*}} @"??$FuncPtrAutoT at P6A?BHXZ$1?func_constint@@YA?BHXZ@@YAP6A?A_PXZXZ"
+
+  FuncPtrAutoT<void (*)(), &func_void>();
+  // CHECK: call {{.*}} @"??$FuncPtrAutoT at P6AXXZ$1?func_void@@YAXXZ@@YAP6A?A_PXZXZ"
+
+  FuncPtrAutoT<int * (*)(), &func_intptr>();
+  // CHECK: call {{.*}} @"??$FuncPtrAutoT at P6APEAHXZ$1?func_intptr@@YAPEAHXZ@@YAP6A?A_PXZXZ"
+}
+
+template<class T>
+auto& RefAutoT(T& x) { return x; }
+
+template<class T>
+const auto& ConstRefAutoT(T& x) { return x; }
+
+template<class T>
+auto&& RRefAutoT(T& x) { return static_cast<int&&>(x); }
+
+void test_template_ref_auto() {
+  int x;
+
+  RefAutoT(x);
+  // CHECK: call {{.*}} @"??$RefAutoT at H@@YAAEA_PAEAH at Z"
+
+  ConstRefAutoT(x);
+  // CHECK: call {{.*}} @"??$ConstRefAutoT at H@@YAAEB_PAEAH at Z"
+
+  RRefAutoT(x);
+  // CHECK: call {{.*}} @"??$RRefAutoT at H@@YA$$QEA_PAEAH at Z"
+}
+
+template<class T>
+decltype(auto) DecltypeAutoT() { return T(); }
+
+template<class T>
+decltype(auto) DecltypeAutoT2(T& x) { return static_cast<T&&>(x); }
+
+void test_template_decltypeauto() {
+  DecltypeAutoT<void>();
+  // CHECK: call {{.*}} @"??$DecltypeAutoT at X@@YA?A_TXZ"
+
+  DecltypeAutoT<const void>();
+  // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CBX@@YA?A_TXZ"
+
+  DecltypeAutoT<volatile void>();
+  // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CCX@@YA?A_TXZ"
+
+  DecltypeAutoT<const volatile void>();
+  // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CDX@@YA?A_TXZ"
+
+  DecltypeAutoT<int>();
+  // CHECK: call {{.*}} @"??$DecltypeAutoT at H@@YA?A_TXZ"
+
+  DecltypeAutoT<const int>();
+  // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CBH@@YA?A_TXZ"
+
+  DecltypeAutoT<volatile int>();
+  // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CCH@@YA?A_TXZ"
+
+  DecltypeAutoT<const volatile int>();
+  // CHECK: call {{.*}} @"??$DecltypeAutoT@$$CDH@@YA?A_TXZ"
+
+  int x;
+
+  DecltypeAutoT2(x);
+  // CHECK: call {{.*}} @"??$DecltypeAutoT2 at H@@YA?A_TAEAH at Z"
+}
+
+// Still want to use clang's custom mangling for lambdas to keep backwards compatibility until
+// MSVC lambda name mangling has been deciphered.
+void test_lambda() {
+  auto lambdaIntRetAuto = []() { return 0; };
+  lambdaIntRetAuto();
+  // CHECK: call {{.*}} @"??R<lambda_1>@?0??test_lambda@@YAXXZ at QEBA?A?<auto>@@XZ"
+
+  auto lambdaIntRet = []() -> int { return 0; };
+  lambdaIntRet();
+  // CHECK: call {{.*}} @"??R<lambda_2>@?0??test_lambda@@YAXXZ at QEBA@XZ"
+
+  auto lambdaGenericIntIntRetAuto = [](auto a) { return a; };
+  lambdaGenericIntIntRetAuto(0);
+  // CHECK: call {{.*}} @"??$?RH@<lambda_0>@?0??test_lambda@@YAXXZ at QEBA?A?<auto>@@H at Z"
+}
+
+auto TestTrailingInt() -> int {
+  return 0;
+}
+
+auto TestTrailingConstVolatileVoid() -> const volatile void {
+}
+
+auto TestTrailingStructA() -> StructA {
+  return StructA{};
+}
+
+void test_trailing_return() {
+  TestTrailingInt();
+  // CHECK: call {{.*}} @"?TestTrailingInt@@YAHXZ"
+
+  TestTrailingConstVolatileVoid();
+  // CHECK: call {{.*}} @"?TestTrailingConstVolatileVoid@@YAXXZ"
+
+  TestTrailingStructA();
+  // CHECK: call {{.*}} @"?TestTrailingStructA@@YA?AUStructA@@XZ"
+}
+
+auto TestNonTemplateAutoInt() {
+  return 0;
+}
+
+auto TestNonTemplateAutoVoid() {
+  return;
+}
+
+auto TestNonTemplateAutoStructA() {
+  return StructA{};
+}
+
+const auto TestNonTemplateConstAutoInt() {
+  return 0;
+}
+
+const auto TestNonTemplateConstAutoVoid() {
+  return;
+}
+
+const auto TestNonTemplateConstAutoStructA() {
+  return StructA{};
+}
+
+void test_nontemplate_auto() {
+  TestNonTemplateAutoInt();
+  // CHECK: call {{.*}} @"?TestNonTemplateAutoInt@@YA at XZ"
+
+  TestNonTemplateAutoVoid();
+  // CHECK: call {{.*}} @"?TestNonTemplateAutoVoid@@YA at XZ"
+
+  TestNonTemplateAutoStructA();
+  // CHECK: call {{.*}} @"?TestNonTemplateAutoStructA@@YA at XZ"
+
+  TestNonTemplateConstAutoInt();
+  // CHECK: call {{.*}} @"?TestNonTemplateConstAutoInt@@YA at XZ"
+
+  TestNonTemplateConstAutoVoid();
+  // CHECK: call {{.*}} @"?TestNonTemplateConstAutoVoid@@YA at XZ"
+
+  TestNonTemplateConstAutoStructA();
+  // CHECK: call {{.*}} @"?TestNonTemplateConstAutoStructA@@YA at XZ"
+}
+
+decltype(auto) TestNonTemplateDecltypeAutoInt() {
+    return 0;
+}
+
+decltype(auto) TestNonTemplateDecltypeAutoVoid() {
+    return;
+}
+
+decltype(auto) TestNonTemplateDecltypeAutoStructA() {
+    return StructA{};
+}
+
+void test_nontemplate_decltypeauto() {
+  TestNonTemplateDecltypeAutoInt();
+  // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoInt@@YA at XZ"
+
+  TestNonTemplateDecltypeAutoVoid();
+  // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoVoid@@YA at XZ"
+
+  TestNonTemplateDecltypeAutoStructA();
+  // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoStructA@@YA at XZ"
+}
+
+struct StructB {
+  int x;
+};
+
+template<class T>
+auto StructB::* AutoMemberDataPtrT(T x) { return x; }
+
+template<class T>
+const auto StructB::* AutoConstMemberDataPtrT(T x) { return x; }
+
+void test_template_auto_member_data_ptr() {
+  AutoMemberDataPtrT(&StructB::x);
+  // CHECK: call {{.*}} @"??$AutoMemberDataPtrT at PEQStructB@@H@@YAPEQStructB@@_PPEQ0 at H@Z"
+
+  AutoConstMemberDataPtrT(&StructB::x);
+  // CHECK: call {{.*}} @"??$AutoConstMemberDataPtrT at PEQStructB@@H@@YAPERStructB@@_PPEQ0 at H@Z"
+}
+
+struct StructC {
+  void test() {}
+};
+
+struct StructD {
+  const int test() { return 0; }
+};
+
+template<class T>
+auto (StructC::*AutoMemberFuncPtrT(T x))() { return x; }
+
+template<class T>
+const auto (StructD::*AutoConstMemberFuncPtrT(T x))() { return x; }
+
+void test_template_auto_member_func_ptr() {
+  AutoMemberFuncPtrT(&StructC::test);
+  // CHECK: call {{.*}} @"??$AutoMemberFuncPtrT at P8StructC@@EAAXXZ@@YAP8StructC@@EAA?A_PXZP80 at EAAXXZ@Z"
+
+  AutoConstMemberFuncPtrT(&StructD::test);
+  // CHECK: call {{.*}} @"??$AutoConstMemberFuncPtrT at P8StructD@@EAA?BHXZ@@YAP8StructD@@EAA?B_PXZP80 at EAA?BHXZ at Z"
+}
diff --git a/clang/test/CodeGenCXX/mangle-ms-auto-templates-memptrs.cpp b/clang/test/CodeGenCXX/mangle-ms-auto-templates-memptrs.cpp
index 360ebdecc5562b..b7bc3953f0b438 100644
--- a/clang/test/CodeGenCXX/mangle-ms-auto-templates-memptrs.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-auto-templates-memptrs.cpp
@@ -34,15 +34,15 @@ void template_mangling() {
   // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$I?f at V@@QEAAXXZA at A@@@QEAA at XZ"
 
   AutoFunc<&S::f>();
-  // AFTER: call {{.*}} @"??$AutoFunc@$MP8S@@EAAXXZ1?f at 1@QEAAXXZ@@YA?A?<auto>@@XZ"
+  // AFTER: call {{.*}} @"??$AutoFunc@$MP8S@@EAAXXZ1?f at 1@QEAAXXZ@@YA?A_PXZ"
   // BEFORE: call {{.*}} @"??$AutoFunc@$1?f at S@@QEAAXXZ@@YA?A?<auto>@@XZ"
 
   AutoFunc<&M::f>();
-  // AFTER: call {{.*}} @"??$AutoFunc@$MP8M@@EAAXXZH?f at 1@QEAAXXZA@@@YA?A?<auto>@@XZ"
+  // AFTER: call {{.*}} @"??$AutoFunc@$MP8M@@EAAXXZH?f at 1@QEAAXXZA@@@YA?A_PXZ"
   // BEFORE: call {{.*}} @"??$AutoFunc@$H?f at M@@QEAAXXZA@@@YA?A?<auto>@@XZ"
 
   AutoFunc<&V::f>();
-  // AFTER: call {{.*}} @"??$AutoFunc@$MP8V@@EAAXXZI?f at 1@QEAAXXZA at A@@@YA?A?<auto>@@XZ"
+  // AFTER: call {{.*}} @"??$AutoFunc@$MP8V@@EAAXXZI?f at 1@QEAAXXZA at A@@@YA?A_PXZ"
   // BEFORE: call {{.*}} @"??$AutoFunc@$I?f at V@@QEAAXXZA at A@@@YA?A?<auto>@@XZ"
 
   AutoParmTemplate<&S::a> auto_data_single_inheritance;
@@ -58,14 +58,14 @@ void template_mangling() {
   // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$FBA at A@@@QEAA at XZ"
 
   AutoFunc<&S::a>();
-  // AFTER: call {{.*}} @"??$AutoFunc@$MPEQS@@H07@@YA?A?<auto>@@XZ"
+  // AFTER: call {{.*}} @"??$AutoFunc@$MPEQS@@H07@@YA?A_PXZ"
   // BEFORE: call {{.*}} @"??$AutoFunc@$07@@YA?A?<auto>@@XZ"
 
   AutoFunc<&M::a>();
-  // AFTER: call {{.*}} @"??$AutoFunc@$MPEQM@@H0M@@@YA?A?<auto>@@XZ"
+  // AFTER: call {{.*}} @"??$AutoFunc@$MPEQM@@H0M@@@YA?A_PXZ"
   // BEFORE: call {{.*}} @"??$AutoFunc@$0M@@@YA?A?<auto>@@XZ"
 
   AutoFunc<&V::a>();
-  // AFTER: call {{.*}} @"??$AutoFunc@$MPEQV@@HFBA at A@@@YA?A?<auto>@@XZ"
+  // AFTER: call {{.*}} @"??$AutoFunc@$MPEQV@@HFBA at A@@@YA?A_PXZ"
   // BEFORE: call {{.*}} @"??$AutoFunc@$FBA at A@@@YA?A?<auto>@@XZ"
 }
diff --git a/clang/test/CodeGenCXX/mangle-ms-auto-templates-nullptr.cpp b/clang/test/CodeGenCXX/mangle-ms-auto-templates-nullptr.cpp
index 8f98c1e59f73d7..251d9219c01ce2 100644
--- a/clang/test/CodeGenCXX/mangle-ms-auto-templates-nullptr.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-auto-templates-nullptr.cpp
@@ -19,6 +19,6 @@ void template_mangling() {
   // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$0A@@@QEAA at XZ"
 
   AutoFunc<nullptr>();
-  // AFTER: call {{.*}} @"??$AutoFunc@$M$$T0A@@@YA?A?<auto>@@XZ"
+  // AFTER: call {{.*}} @"??$AutoFunc@$M$$T0A@@@YA?A_PXZ"
   // BEFORE: call {{.*}} @"??$AutoFunc@$0A@@@YA?A?<auto>@@XZ"
 }
diff --git a/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp b/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp
index ff5395cea75eb7..effcc31ee31103 100644
--- a/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp
@@ -26,7 +26,7 @@ int j;
 
 void template_mangling() {
   AutoFunc<1>();
-  // AFTER: call {{.*}} @"??$AutoFunc@$MH00@@YA?A?<auto>@@XZ"
+  // AFTER: call {{.*}} @"??$AutoFunc@$MH00@@YA?A_PXZ"
   // BEFORE: call {{.*}} @"??$AutoFunc@$00@@YA?A?<auto>@@XZ"
   AutoParmTemplate<0> auto_int;
   // AFTER: call {{.*}} @"??0?$AutoParmTemplate@$MH0A@@@QEAA at XZ"
@@ -52,7 +52,7 @@ void template_mangling() {
   // BEFORE: call {{.*}} @"??0?$AutoParmsTemplate@$00$0HPPPPPPPPPPPPPPP@@@QEAA at XZ"
 
   AutoFunc<&i>();
-  // AFTER: call {{.*}} @"??$AutoFunc@$MPEAH1?i@@3HA@@YA?A?<auto>@@XZ"
+  // AFTER: call {{.*}} @"??$AutoFunc@$MPEAH1?i@@3HA@@YA?A_PXZ"
   // BEFORE: call {{.*}} @"??$AutoFunc@$1?i@@3HA@@YA?A?<auto>@@XZ"
 
   AutoParmTemplate<&i> auto_int_ptr;
@@ -64,7 +64,7 @@ void template_mangling() {
   // BEFORE: call {{.*}} @"??0?$AutoParmsTemplate@$1?i@@3HA$1?j@@3HA@@QEAA at XZ"
 
   AutoFunc<&Func>();
-  // AFTER: call {{.*}} @"??$AutoFunc@$MP6AHXZ1?Func@@YAHXZ@@YA?A?<auto>@@XZ"
+  // AFTER: call {{.*}} @"??$AutoFunc@$MP6AHXZ1?Func@@YAHXZ@@YA?A_PXZ"
   // BEFORE: call {{.*}} @"??$AutoFunc@$1?Func@@YAHXZ@@YA?A?<auto>@@XZ"
 
   AutoParmTemplate<&Func> auto_func_ptr;

>From c316645d62c2a78e84ddf9bd52b7e3067286b08b Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.winkler at gmail.com>
Date: Sun, 11 Aug 2024 21:50:20 -0700
Subject: [PATCH 2/5] formatting

---
 clang/lib/AST/MicrosoftMangle.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index ecbddc1aacc073..5da12b55d1a281 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -2560,7 +2560,6 @@ void MicrosoftCXXNameMangler::mangleAutoReturnType(QualType T,
 
 void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
                                          QualifierMangleMode QMM) {
-
   // Don't use the canonical types.  MSVC includes things like 'const' on
   // pointer arguments to function pointers that canonicalization strips away.
   T = T.getDesugaredType(getASTContext());

>From 13f1086e046eacc8c82a1fff2c357444ecc22174 Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.winkler at gmail.com>
Date: Sun, 11 Aug 2024 22:02:52 -0700
Subject: [PATCH 3/5] add missing address space test

---
 clang/test/CodeGenCXX/mangle-ms-auto-return.cpp | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/clang/test/CodeGenCXX/mangle-ms-auto-return.cpp b/clang/test/CodeGenCXX/mangle-ms-auto-return.cpp
index 9b34a9abfd75d8..737c9c407f4703 100644
--- a/clang/test/CodeGenCXX/mangle-ms-auto-return.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-auto-return.cpp
@@ -356,3 +356,14 @@ void test_template_auto_member_func_ptr() {
   AutoConstMemberFuncPtrT(&StructD::test);
   // CHECK: call {{.*}} @"??$AutoConstMemberFuncPtrT at P8StructD@@EAA?BHXZ@@YAP8StructD@@EAA?B_PXZP80 at EAA?BHXZ at Z"
 }
+
+template<class T>
+auto * __attribute__((address_space(1))) * AutoPtrAddressSpaceT() {
+  T * __attribute__((address_space(1))) * p = nullptr;
+  return p;
+}
+
+void test_template_auto_address_space_ptr() {
+  AutoPtrAddressSpaceT<int>();
+  // CHECK: call {{.*}} @"??$AutoPtrAddressSpaceT at H@@YA?A?<auto>@@XZ"
+}

>From 9ce68b9ab3cf2201e978a6128622dfaf43caf039 Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.winkler at gmail.com>
Date: Mon, 12 Aug 2024 20:09:40 -0700
Subject: [PATCH 4/5] Remove unused SourceRange argument

---
 clang/lib/AST/MicrosoftMangle.cpp | 46 ++++++++++++-------------------
 1 file changed, 18 insertions(+), 28 deletions(-)

diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 5da12b55d1a281..bd88bd5fd8f0e8 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -408,8 +408,7 @@ class MicrosoftCXXNameMangler {
   void mangleSourceName(StringRef Name);
   void mangleNestedName(GlobalDecl GD);
 
-  void mangleAutoReturnType(QualType T, SourceRange Range,
-                            QualifierMangleMode QMM);
+  void mangleAutoReturnType(QualType T, QualifierMangleMode QMM);
 
 private:
   bool isStructorDecl(const NamedDecl *ND) const {
@@ -481,14 +480,10 @@ class MicrosoftCXXNameMangler {
   void mangleObjCKindOfType(const ObjCObjectType *T, Qualifiers Quals,
                             SourceRange Range);
 
-  void mangleAutoReturnType(const MemberPointerType *T, Qualifiers Quals,
-                            SourceRange Range);
-  void mangleAutoReturnType(const PointerType *T, Qualifiers Quals,
-                            SourceRange Range);
-  void mangleAutoReturnType(const LValueReferenceType *T, Qualifiers Quals,
-                            SourceRange Range);
-  void mangleAutoReturnType(const RValueReferenceType *T, Qualifiers Quals,
-                            SourceRange Range);
+  void mangleAutoReturnType(const MemberPointerType *T, Qualifiers Quals);
+  void mangleAutoReturnType(const PointerType *T, Qualifiers Quals);
+  void mangleAutoReturnType(const LValueReferenceType *T, Qualifiers Quals);
+  void mangleAutoReturnType(const RValueReferenceType *T, Qualifiers Quals);
 };
 }
 
@@ -2507,7 +2502,6 @@ void MicrosoftCXXNameMangler::mangleAddressSpaceType(QualType T,
 }
 
 void MicrosoftCXXNameMangler::mangleAutoReturnType(QualType T,
-                                                   SourceRange Range,
                                                    QualifierMangleMode QMM) {
   assert(getASTContext().getLangOpts().isCompatibleWithMSVC(
              LangOptions::MSVC2019) &&
@@ -2542,16 +2536,16 @@ void MicrosoftCXXNameMangler::mangleAutoReturnType(QualType T,
   const Type *ty = T.getTypePtr();
   switch (ty->getTypeClass()) {
   case Type::MemberPointer:
-    mangleAutoReturnType(cast<MemberPointerType>(ty), Quals, Range);
+    mangleAutoReturnType(cast<MemberPointerType>(ty), Quals);
     break;
   case Type::Pointer:
-    mangleAutoReturnType(cast<PointerType>(ty), Quals, Range);
+    mangleAutoReturnType(cast<PointerType>(ty), Quals);
     break;
   case Type::LValueReference:
-    mangleAutoReturnType(cast<LValueReferenceType>(ty), Quals, Range);
+    mangleAutoReturnType(cast<LValueReferenceType>(ty), Quals);
     break;
   case Type::RValueReference:
-    mangleAutoReturnType(cast<RValueReferenceType>(ty), Quals, Range);
+    mangleAutoReturnType(cast<RValueReferenceType>(ty), Quals);
     break;
   default:
     llvm_unreachable("Invalid type expected");
@@ -3000,7 +2994,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
         if (D && !D->getPrimaryTemplate()) {
           Out << '@';
         } else {
-          mangleAutoReturnType(ResultType, Range, QMM_Result);
+          mangleAutoReturnType(ResultType, QMM_Result);
         }
       } else {
         Out << '?';
@@ -4312,8 +4306,7 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
 }
 
 void MicrosoftCXXNameMangler::mangleAutoReturnType(const MemberPointerType *T,
-                                                   Qualifiers Quals,
-                                                   SourceRange Range) {
+                                                   Qualifiers Quals) {
   QualType PointeeType = T->getPointeeType();
   manglePointerCVQualifiers(Quals);
   manglePointerExtQualifiers(Quals, PointeeType);
@@ -4324,13 +4317,12 @@ void MicrosoftCXXNameMangler::mangleAutoReturnType(const MemberPointerType *T,
   } else {
     mangleQualifiers(PointeeType.getQualifiers(), true);
     mangleName(T->getClass()->castAs<RecordType>()->getDecl());
-    mangleAutoReturnType(PointeeType, Range, QMM_Drop);
+    mangleAutoReturnType(PointeeType, QMM_Drop);
   }
 }
 
 void MicrosoftCXXNameMangler::mangleAutoReturnType(const PointerType *T,
-                                                   Qualifiers Quals,
-                                                   SourceRange Range) {
+                                                   Qualifiers Quals) {
   QualType PointeeType = T->getPointeeType();
   assert(!PointeeType.getQualifiers().hasAddressSpace() &&
          "Unexpected address space mangling required");
@@ -4342,28 +4334,26 @@ void MicrosoftCXXNameMangler::mangleAutoReturnType(const PointerType *T,
     Out << '6';
     mangleFunctionType(FPT);
   } else {
-    mangleAutoReturnType(PointeeType, Range, QMM_Mangle);
+    mangleAutoReturnType(PointeeType, QMM_Mangle);
   }
 }
 
 void MicrosoftCXXNameMangler::mangleAutoReturnType(const LValueReferenceType *T,
-                                                   Qualifiers Quals,
-                                                   SourceRange Range) {
+                                                   Qualifiers Quals) {
   QualType PointeeType = T->getPointeeType();
   assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!");
   Out << 'A';
   manglePointerExtQualifiers(Quals, PointeeType);
-  mangleAutoReturnType(PointeeType, Range, QMM_Mangle);
+  mangleAutoReturnType(PointeeType, QMM_Mangle);
 }
 
 void MicrosoftCXXNameMangler::mangleAutoReturnType(const RValueReferenceType *T,
-                                                   Qualifiers Quals,
-                                                   SourceRange Range) {
+                                                   Qualifiers Quals) {
   QualType PointeeType = T->getPointeeType();
   assert(!Quals.hasConst() && !Quals.hasVolatile() && "unexpected qualifier!");
   Out << "$$Q";
   manglePointerExtQualifiers(Quals, PointeeType);
-  mangleAutoReturnType(PointeeType, Range, QMM_Mangle);
+  mangleAutoReturnType(PointeeType, QMM_Mangle);
 }
 
 MicrosoftMangleContext *MicrosoftMangleContext::create(ASTContext &Context,

>From 55b8eb32a334304bb775b17ea40dd9b0c2cfca64 Mon Sep 17 00:00:00 2001
From: MaxEW707 <max.enrico.winkler at gmail.com>
Date: Tue, 13 Aug 2024 18:42:10 -0700
Subject: [PATCH 5/5] Update release notes

---
 clang/docs/ReleaseNotes.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3c2e0282d1c72d..4b6ddd1dd8d0f3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -46,6 +46,8 @@ C++ Specific Potentially Breaking Changes
 ABI Changes in This Version
 ---------------------------
 
+- Fixed Microsoft name mangling of placeholder, auto and decltype(auto), return types 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
 ----------------------------------------
 



More information about the cfe-commits mailing list