llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Max Winkler (MaxEW707)

<details>
<summary>Changes</summary>

Partial fix for https://github.com/llvm/llvm-project/issues/92204.
This PR just fixes VS2019+ since that is the suite of compilers that I require 
link compatibility with at the moment.
I still intend to fix VS2017 and to update llvm-undname in future PRs. Once 
those are also finished and merged I'll close out 
https://github.com/llvm/llvm-project/issues/92204.
I am hoping to get the llvm-undname PR up in a couple of weeks to be able to 
demangle the VS2019+ name mangling.

MSVC 1920+ mangles placeholder return types for non-templated functions with 
"@".
For example `auto foo() { return 0; }` is mangled as `?foo@@<!-- -->YA@<!-- 
-->XZ`.

MSVC 1920+ mangles placeholder return types for templated functions as the 
qualifiers of the AutoType followed by "_P" for `auto` and "_T" for 
`decltype(auto)`.
For example `template&lt;class T&gt; auto foo() { return 0; }` is mangled as 
`??$foo@<!-- -->H@@<!-- -->YA?A_PXZ` when `foo` is instantiated as follows 
`foo&lt;int&gt;()`.

Lambdas with placeholder return types are still mangled with clang's custom 
mangling since MSVC lambda mangling hasn't been deciphered yet.
Similarly any pointers in the return type with an address space are mangled 
with clang's custom mangling since that is a clang extension.

We cannot augment `mangleType` to support this mangling scheme as the mangling 
schemes for variables and functions differ.
auto variables are encoded with the fully deduced type where auto return types 
are not.
The following two functions with a static variable are mangled the same
```
template&lt;class T&gt;
int test()
{
    static int i = 0; // "?i@?1???$test@<!-- -->H@@<!-- -->YAHXZ@<!-- -->4HA"
    return i;
}

template&lt;class T&gt;
int test()
{
    static auto i = 0; // "?i@?1???$test@<!-- -->H@@<!-- -->YAHXZ@<!-- -->4HA"
    return i;
}
```
Inside `mangleType` once we get to mangling the `AutoType` we have no context 
if we are from a variable encoding or some other encoding.
Therefore it was easier to handle any special casing for `AutoType` return 
types with a separate function instead of using the `mangleType` infrastructure.


---

Patch is 22.66 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/102848.diff


5 Files Affected:

- (modified) clang/lib/AST/MicrosoftMangle.cpp (+162-9) 
- (added) clang/test/CodeGenCXX/mangle-ms-auto-return.cpp (+369) 
- (modified) clang/test/CodeGenCXX/mangle-ms-auto-templates-memptrs.cpp (+6-6) 
- (modified) clang/test/CodeGenCXX/mangle-ms-auto-templates-nullptr.cpp (+1-1) 
- (modified) clang/test/CodeGenCXX/mangle-ms-auto-templates.cpp (+3-3) 


``````````diff
diff --git a/clang/lib/AST/MicrosoftMangle.cpp 
b/clang/lib/AST/MicrosoftMangle.cpp
index 28f66e71c2f2de..5da12b55d1a281 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,6 +2506,58 @@ 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
@@ -2900,17 +2964,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 +4311,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..737c9c407f4703
--- /dev/null
+++ b/clang/test/CodeGenCXX/mangle-ms-auto-return.cpp
@@ -0,0 +1,369 @@
+// 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@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@X@@YA?B_PXZ"
+
+  AutoVolatileT<void>();
+  // CHECK: call {{.*}} @"??$AutoVolatileT@X@@YA?C_PXZ"
+
+  AutoConstVolatileT<void>();
+  // CHECK: call {{.*}} @"??$AutoConstVolatileT@X@@YA?D_PXZ"
+}
+
+void test_template_auto_int() {
+  AutoT<int>();
+  // CHECK: call {{.*}} @"??$AutoT@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@H@@YA?B_PXZ"
+
+  AutoVolatileT<int>();
+  // CHECK: call {{.*}} @"??$AutoVolatileT@H@@YA?C_PXZ"
+
+  AutoConstVolatileT<int>();
+  // CHECK: call {{.*}} @"??$AutoConstVolatileT@H@@YA?D_PXZ"
+}
+
+void test_template_auto_struct() {
+  AutoT<StructA>();
+  // CHECK: call {{.*}} @"??$AutoT@UStructA@@@@YA?A_PXZ"
+
+  AutoT<const StructA>();
+  // CHECK: call {{.*}} @"??$AutoT@$$CBUStructA@@@@YA?A_PXZ"
+
+  AutoConstT<StructA>();
+  // CHECK: call {{.*}} @"??$AutoConstT@UStructA@@@@YA?B_PXZ"
+
+  AutoVolatileT<StructA>();
+  // CHECK: call {{.*}} @"??$AutoVolatileT@UStructA@@@@YA?C_PXZ"
+
+  AutoConstVolatileT<StructA>();
+  // CHECK: call {{.*}} @"??$AutoConstVolatileT@UStructA@@@@YA?D_PXZ"
+}
+
+void test_template_auto_ptr() {
+  AutoT<int*>();
+  // CHECK: call {{.*}} @"??$AutoT@PEAH@@YA?A_PXZ"
+
+  AutoT<const int*>();
+  // CHECK: call {{.*}} @"??$AutoT@PEBH@@YA?A_PXZ"
+
+  AutoT<const int* const>();
+  // CHECK: call {{.*}} @"??$AutoT@QEBH@@YA?A_PXZ"
+
+  AutoConstT<int*>();
+  // CHECK: call {{.*}} @"??$AutoConstT@PEAH@@YA?B_PXZ"
+
+  AutoVolatileT<int*>();
+  // CHECK: call {{.*}} @"??$AutoVolatileT@PEAH@@YA?C_PXZ"
+
+  AutoConstVolatileT<int*>();
+  // CHECK: call {{.*}} @"??$AutoConstVolatileT@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@PEAH@@YAPEA_PXZ"
+
+  PtrAutoT<const int*>();
+  // CHECK: call {{.*}} @"??$PtrAutoT@PEBH@@YAPEA_PXZ"
+
+  PtrAutoT<const int* const>();
+  // CHECK: call {{.*}} @"??$PtrAutoT@QEBH@@YAPEA_PXZ"
+
+  PtrAutoConstT<int*>();
+  // CHECK: call {{.*}} @"??$PtrAutoConstT@PEAH@@YAPEB_PXZ"
+
+  PtrAutoVolatileT<int*>();
+  // CHECK: call {{.*}} @"??$PtrAutoVolatileT@PEAH@@YAPEC_PXZ"
+
+  PtrAutoConstVolatileT<int*>();
+  // CHECK: call {{.*}} @"??$PtrAutoConstVolatileT@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@P6AHXZ$1?func_int@@YAHXZ@@YAP6A?A_PXZXZ"
+
+  FuncPtrAutoT<const int (*)(), &func_constint>();
+  // CHECK: call {{.*}} 
@"??$FuncPtrAutoT@P6A?BHXZ$1?func_constint@@YA?BHXZ@@YAP6A?A_PXZXZ"
+
+  FuncPtrAutoT<void (*)(), &func_void>();
+  // CHECK: call {{.*}} 
@"??$FuncPtrAutoT@P6AXXZ$1?func_void@@YAXXZ@@YAP6A?A_PXZXZ"
+
+  FuncPtrAutoT<int * (*)(), &func_intptr>();
+  // CHECK: call {{.*}} 
@"??$FuncPtrAutoT@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@H@@YAAEA_PAEAH@Z"
+
+  ConstRefAutoT(x);
+  // CHECK: call {{.*}} @"??$ConstRefAutoT@H@@YAAEB_PAEAH@Z"
+
+  RRefAutoT(x);
+  // CHECK: call {{.*}} @"??$RRefAutoT@H@@YA$$QEA_PAEAH@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@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@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@H@@YA?A_TAEAH@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@QEBA?A?<auto>@@XZ"
+
+  auto lambdaIntRet = []() -> int { return 0; };
+  lambdaIntRet();
+  // CHECK: call {{.*}} @"??R<lambda_2>@?0??test_lambda@@YAXXZ@QEBA@XZ"
+
+  auto lambdaGenericIntIntRetAuto = [](auto a) { return a; };
+  lambdaGenericIntIntRetAuto(0);
+  // CHECK: call {{.*}} 
@"??$?RH@<lambda_0>@?0??test_lambda@@YAXXZ@QEBA?A?<auto>@@H@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@XZ"
+
+  TestNonTemplateAutoVoid();
+  // CHECK: call {{.*}} @"?TestNonTemplateAutoVoid@@YA@XZ"
+
+  TestNonTemplateAutoStructA();
+  // CHECK: call {{.*}} @"?TestNonTemplateAutoStructA@@YA@XZ"
+
+  TestNonTemplateConstAutoInt();
+  // CHECK: call {{.*}} @"?TestNonTemplateConstAutoInt@@YA@XZ"
+
+  TestNonTemplateConstAutoVoid();
+  // CHECK: call {{.*}} @"?TestNonTemplateConstAutoVoid@@YA@XZ"
+
+  TestNonTemplateConstAutoStructA();
+  // CHECK: call {{.*}} @"?TestNonTemplateConstAutoStructA@@YA@XZ"
+}
+
+decltype(auto) TestNonTemplateDecltypeAutoInt() {
+    return 0;
+}
+
+decltype(auto) TestNonTemplateDecltypeAutoVoid() {
+    return;
+}
+
+decltype(auto) TestNonTemplateDecltypeAutoStructA() {
+    return StructA{};
+}
+
+void test_nontemplate_decltypeauto() {
+  TestNonTemplateDecltypeAutoInt();
+  // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoInt@@YA@XZ"
+
+  TestNonTemplateDecltypeAutoVoid();
+  // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoVoid@@YA@XZ"
+
+  TestNonTemplateDecltypeAutoStructA();
+  // CHECK: call {{.*}} @"?TestNonTemplateDecltypeAutoStructA@@YA@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@PEQStructB@@H@@YAPEQStructB@@_PPEQ0@H@Z"
+
+  AutoConstMemberDataPtrT(&StructB::x);
+  // CHECK: call {{.*}} 
@"??$AutoConstMemberDataPtrT@PEQStructB@@H@@YAPERStructB@@_PPEQ0@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@P8StructC@@EAAXXZ@@YAP8StructC@@EAA?A_PXZP80@EAAXXZ@Z"
+
+  AutoConstMemberFuncPtrT(&StructD::test);
+  // CHECK: call {{.*}} 
@"??$AutoConstMemberFuncPtrT@P8StructD@@EAA?BHXZ@@YAP8StructD@@EAA?B_PXZP80@EAA?BHXZ@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@H@@YA?A?<auto>@@XZ"
+}
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@V@@QEAAXXZA@A@@@QEAA@XZ"
 
   AutoFunc<&S::f>();
-  // AFTER: call {{.*}} 
@"??$AutoFunc@$MP8S@@EAAXXZ1?f@1@QEAAXXZ@@YA?A?<auto>@@XZ"
+  // AFTER: call {{.*}} @"??$AutoFunc@$MP8S@@EAAXXZ1?f@1@QEAAXXZ@@YA?A_PXZ"
   // BEFORE: call {{.*}} @"??$AutoFunc@$1?f@S@@QEAAXXZ@@YA?A?<auto>@@XZ"
 
   AutoFunc<&M::f>();
-  // AFTER: call {{.*}} 
@"??$AutoFunc@$MP8M@@EAAXXZH?f@1@QEAAXXZA@@@YA?A?<auto>@@XZ"
+  // AFTER: call {{.*}} @"??$AutoFunc@$MP8M@@EAAXXZH?f@1@QEAAXXZA@@@YA?A_PXZ"
   // BEFORE: call {{.*}} @"??$AutoFunc@$H?f@M@@QEAAXXZA@@@YA?A?<auto>@@XZ"
 
   AutoFunc<&V::f>();
-  // AFTER: call {{.*}} 
@"??$AutoFunc@$MP8V@@EAAXXZI?f@1@QEAAXXZA@A@@@YA?A?<auto>@@XZ"
+  // AFTER: call {{.*}} @"??$AutoFunc@$MP8V@@EAAXXZI?f@1@QEAAXXZA@A@@@YA?A_PXZ"
   // BEFORE: call {{.*}} @"??$AutoFunc@$I?f@V@@QEAAXXZA@A@@@YA?A?<auto>@@XZ"
 
   AutoParmTemplate<&S::a> auto_data_single_inheritance;
@@ -58,14 +58,14 @@ void template_mangling() {
   // BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$FBA@A@@@QEAA@XZ"
 
   AutoFunc<&S::...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/102848
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to