[clang] Adds an arbitrary pseudonym to clang"s windows mangler... (PR #97792)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jul 6 08:47:20 PDT 2024
https://github.com/memory-thrasher updated https://github.com/llvm/llvm-project/pull/97792
>From 9f909ffb4714294d62264e541a44137adfcd7cb9 Mon Sep 17 00:00:00 2001
From: Sidney Kelley <memory.thrasher at gmail.com>
Date: Thu, 4 Jul 2024 23:03:16 -0700
Subject: [PATCH] Adds an arbitrary pseudonym to clang"s windows mangler to
handle template argument values that are pointers one-past-the-end of a
non-array symbol. Also improves error messages in other template argument
scenarios where clang bails.
---
clang/lib/AST/MicrosoftMangle.cpp | 64 ++++++++++++++-----
.../CodeGen/ms_mangler_templatearg_opte.cpp | 47 ++++++++++++++
2 files changed, 96 insertions(+), 15 deletions(-)
create mode 100644 clang/test/CodeGen/ms_mangler_templatearg_opte.cpp
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index fac14ce1dce8ce..2c5b0e8d7a66ef 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1922,11 +1922,19 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
if (WithScalarType)
mangleType(T, SourceRange(), QMM_Escape);
- // We don't know how to mangle past-the-end pointers yet.
- if (V.isLValueOnePastTheEnd())
- break;
-
APValue::LValueBase Base = V.getLValueBase();
+
+ // this might not cover every case but did cover issue 97756
+ // see test CodeGen/ms_mangler_templatearg_opte
+ if (V.isLValueOnePastTheEnd()) {
+ Out << "5E";
+ auto *VD = Base.dyn_cast<const ValueDecl *>();
+ if (VD)
+ mangle(VD);
+ Out << "@";
+ return;
+ }
+
if (!V.hasLValuePath() || V.getLValuePath().empty()) {
// Taking the address of a complete object has a special-case mangling.
if (Base.isNull()) {
@@ -1938,12 +1946,23 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
mangleNumber(V.getLValueOffset().getQuantity());
} else if (!V.hasLValuePath()) {
// FIXME: This can only happen as an extension. Invent a mangling.
- break;
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID =
+ Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this template argument yet "
+ "(non-null base with null lvalue path)");
+ Diags.Report(DiagID);
+ return;
} else if (auto *VD = Base.dyn_cast<const ValueDecl*>()) {
Out << "E";
mangle(VD);
} else {
- break;
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "cannot mangle this template argument yet (empty lvalue path)");
+ Diags.Report(DiagID);
+ return;
}
} else {
if (TAK == TplArgKind::ClassNTTP && T->isPointerType())
@@ -1988,8 +2007,14 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
Out << *I;
auto *VD = Base.dyn_cast<const ValueDecl*>();
- if (!VD)
- break;
+ if (!VD) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "cannot mangle this template argument yet (null value decl)");
+ Diags.Report(DiagID);
+ return;
+ }
Out << (TAK == TplArgKind::ClassNTTP ? 'E' : '1');
mangle(VD);
@@ -2104,15 +2129,24 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T,
return;
}
- case APValue::AddrLabelDiff:
- case APValue::FixedPoint:
- break;
+ case APValue::AddrLabelDiff: {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error, "cannot mangle this template argument yet "
+ "(value type: address label diff)");
+ Diags.Report(DiagID);
+ return;
}
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(
- DiagnosticsEngine::Error, "cannot mangle this template argument yet");
- Diags.Report(DiagID);
+ case APValue::FixedPoint: {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "cannot mangle this template argument yet (value type: fixed point)");
+ Diags.Report(DiagID);
+ return;
+ }
+ }
}
void MicrosoftCXXNameMangler::mangleObjCProtocol(const ObjCProtocolDecl *PD) {
diff --git a/clang/test/CodeGen/ms_mangler_templatearg_opte.cpp b/clang/test/CodeGen/ms_mangler_templatearg_opte.cpp
new file mode 100644
index 00000000000000..66fe6aa2c04c24
--- /dev/null
+++ b/clang/test/CodeGen/ms_mangler_templatearg_opte.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -emit-llvm -std=c++20 -x c++ < %s | FileCheck -check-prefix=WIN64 %s
+
+/*
+
+This works (linux host):
+clang++ -std=c++20 -c ms_mangler_templatearg_opte.cpp -o /dev/null
+
+Before this case's corresponding patch, this did not:
+clang -cc1 -triple x86_64-pc-windows-msvc19.33.0 -emit-obj -std=c++20 -o ms_mangler_templatearg_opte.obj -x c++ ms_mangler_templatearg_opte.cpp
+
+The first pass is fine, it's the final pass of cesum where L.data = (&ints)+1 that clang bawks at. Obviously this address can't be dereferenced, but the `if constexpr` sees to that. The unused template param should not break the mangler.
+
+*/
+
+
+typedef long long unsigned size_t;
+
+template<class T> struct llist {
+ const T* data;
+ size_t len;
+ constexpr llist(const T* data, size_t len) : data(data), len(len) {};
+ constexpr inline bool empty() const { return len == 0; };
+ constexpr llist<T> next() const { return { data+1, len-1 }; };
+ constexpr const T& peek() const { return data[0]; };
+};
+
+//recurse to iterate over the list, without the need for a terminal overload or duplicated handling of the terminal case
+template<llist<int> L> int cesum() {
+ if constexpr(L.empty()) {
+ return 0;
+ } else {
+ return L.peek() + cesum<L.next()>();
+ }
+};
+
+// WIN64: {{cesum.*ints}}
+constexpr int ints[] = { 1, 2, 7, 8, 9, -17, -10 }; //Note: this does NOT break the unpatched mangler
+
+// WIN64: {{cesum.*one_int}}
+constexpr int one_int = 7;
+
+int template_instance() {
+ cesum<llist<int>(ints, sizeof(ints)/sizeof(int))>();
+ cesum<llist<int>(&one_int, 1)>();
+ return 0;
+}
+
More information about the cfe-commits
mailing list