https://github.com/memory-thrasher updated 
https://github.com/llvm/llvm-project/pull/97792

>From 533d1577d04477ec4ec0c7ce16e06aaa36064dd3 Mon Sep 17 00:00:00 2001
From: Sidney Kelley <memory.thras...@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             | 57 ++++++++++++++-----
 .../CodeGen/ms_mangler_templatearg_opte.cpp   | 47 +++++++++++++++
 2 files changed, 90 insertions(+), 14 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..f348a3a2dcce71 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1922,9 +1922,12 @@ 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;
+    // msvc does not support this, so no mangling will ever be "right", so this
+    // was picked arbitrarily.
+    if (V.isLValueOnePastTheEnd()) {
+      Out << "@IN"; // for "invalid pointer" since it always is invalid.
+      return;
+    }
 
     APValue::LValueBase Base = V.getLValueBase();
     if (!V.hasLValuePath() || V.getLValuePath().empty()) {
@@ -1938,12 +1941,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 +2002,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 +2124,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;
+}
+

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to