[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