[clang] [WIP][clang] Fix std::tm etc. mangling on Solaris (PR #106353)

Rainer Orth via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 7 08:03:04 PDT 2024


https://github.com/rorth updated https://github.com/llvm/llvm-project/pull/106353

>From 646c6ad032fe9c15faee03246496958f7592ea75 Mon Sep 17 00:00:00 2001
From: Rainer Orth <ro at gcc.gnu.org>
Date: Wed, 28 Aug 2024 11:24:29 +0200
Subject: [PATCH 1/3] [WIP][clang] Fix std::tm etc. mangling on Solaris

Recently, Solaris bootstrap got broken because Solaris uses a non-standard
mangling of `std::tm` and a few others.  This was fixed with a hack in PR
Solaris ABI requirements, mangling `std::tm` as `tm` and similarly for
`std::div_t`, `std::ldiv_t`, and `std::lconv`.

Tested on `amd64-pc-solaris2.11`, `sparcv9-sun-solaris2.11`, and
`x86_64-pc-linux-gnu`.

Unfortunately, this patch is almost there, but not quite yet: while the new
testcase works as expected, the original trigger in
`clang/lib/Lex/PPMacroExpansion.cpp` is now mangled into
`_ZNKSt8time_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE3putES3_RSt8ios_basecPK2tmPKcSA_`
(`std::time_put<char, std::ostreambuf_iterator<char, std::char_traits<char>
> >::put(std::ostreambuf_iterator<char, std::char_traits<char> >,
std::ios_base&, char, tm const*, char const*, char const) const`) instead
of the expected
`_ZNKSt8time_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE3putES3_RSt8ios_basecPK2tmPKcSB_`
(`std::time_put<char, std::ostreambuf_iterator<char, std::char_traits<char>
> >::put(std::ostreambuf_iterator<char, std::char_traits<char> >,
std::ios_base&, char, tm const*, char const*, char const*) const`),
i.e. `char const` for the final arg instead of `char const*`.  I don't have
the slightest idea why, unfortunately.
---
 clang/lib/AST/ItaniumMangle.cpp    | 22 ++++++++++++++++++++++
 clang/lib/Lex/PPMacroExpansion.cpp |  6 ++++--
 clang/test/AST/solaris-tm.cpp      | 27 +++++++++++++++++++++++++++
 3 files changed, 53 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/AST/solaris-tm.cpp

diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 976670d1efa561..12c926d589b3dc 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -38,6 +38,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/RISCVTargetParser.h"
 #include <optional>
+#include <set>
 
 using namespace clang;
 
@@ -6953,6 +6954,27 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
     return false;
   }
 
+  if (getASTContext().getTargetInfo().getTriple().isOSSolaris()) {
+    if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND)) {
+      if (!isStdNamespace(Context.getEffectiveDeclContext(RD)))
+        return false;
+
+      // Issue #33114: Need non-standard mangling of std::tm etc. for
+      // Solaris ABI compatibility.
+      static std::set<StringRef> types{"div_t", "ldiv_t", "lconv", "tm"};
+
+      // <substitution> ::= tm # ::std::tm, same for the others
+      if (const IdentifierInfo *II = RD->getIdentifier()) {
+        StringRef type = II->getName();
+        if (types.count(type)) {
+          Out << type.size() << type;
+          return true;
+        }
+      }
+      return false;
+    }
+  }
+
   return false;
 }
 
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index 1d671ab72b0c03..a8991c28f0261f 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1604,10 +1604,12 @@ static bool isTargetVariantEnvironment(const TargetInfo &TI,
   return false;
 }
 
-#if defined(__sun__) && defined(__svr4__)
+#if defined(__sun__) && defined(__svr4__) && defined(__clang__) &&             \
+    __clang__ < 20
 // GCC mangles std::tm as tm for binary compatibility on Solaris (Issue
 // #33114).  We need to match this to allow the std::put_time calls to link
-// (PR #99075).
+// (PR #99075).  clang 20 contains a fix, but the workaround is still needed
+// with older versions.
 asm("_ZNKSt8time_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE3putES3_"
     "RSt8ios_basecPKSt2tmPKcSB_ = "
     "_ZNKSt8time_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE3putES3_"
diff --git a/clang/test/AST/solaris-tm.cpp b/clang/test/AST/solaris-tm.cpp
new file mode 100644
index 00000000000000..f3d16b7ba1116f
--- /dev/null
+++ b/clang/test/AST/solaris-tm.cpp
@@ -0,0 +1,27 @@
+/// Check that std::tm and a few others are mangled as tm on Solaris only.
+/// Issue #33114.
+///
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple amd64-pc-solaris2.11 | FileCheck --check-prefix=CHECK-SOLARIS %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-unknown-linux-gnu  | FileCheck --check-prefix=CHECK-LINUX %s
+//
+// REQUIRES: x86-registered-target
+//
+// CHECK-SOLARIS: @_Z6tmfunc2tm
+// CHECK-SOLARIS: @_Z7ldtfunc6ldiv_t
+// CHECK-LINUX:   @_Z6tmfuncSt2tm
+// CHECK-LINUX:   @_Z7ldtfuncSt6ldiv_t
+
+namespace std {
+  extern "C" {
+    struct tm {
+      int tm_sec;
+    };
+    struct ldiv_t {
+      long quot;
+    };
+  }
+}
+
+void tmfunc (std::tm tm) {}
+
+void ldtfunc (std::ldiv_t ldt) {}

>From 9cdeb8afb22268177b797ea23a7ef867ee84d216 Mon Sep 17 00:00:00 2001
From: Rainer Orth <ro at gcc.gnu.org>
Date: Fri, 27 Sep 2024 16:52:58 +0200
Subject: [PATCH 2/3] - Add ReleaseNotes entry. - Use llvm::is_contained.

---
 clang/docs/ReleaseNotes.rst     | 4 ++++
 clang/lib/AST/ItaniumMangle.cpp | 6 ++----
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2c29d49ba20f03..05074ac6e8f7be 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -348,6 +348,10 @@ OpenACC Specific Changes
 Target Specific Changes
 -----------------------
 
+- Clang now implements the Solaris-specific mangling of ``std::tm`` as
+  ``tm``, same for ``std::div_t``, ``std::ldiv_t``, and
+  ``std::lconv``, for Solaris ABI compatibility. (#GH33114)
+
 AMDGPU Support
 ^^^^^^^^^^^^^^
 
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 12c926d589b3dc..fa504abe981d69 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -38,7 +38,6 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/RISCVTargetParser.h"
 #include <optional>
-#include <set>
 
 using namespace clang;
 
@@ -6961,12 +6960,11 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
 
       // Issue #33114: Need non-standard mangling of std::tm etc. for
       // Solaris ABI compatibility.
-      static std::set<StringRef> types{"div_t", "ldiv_t", "lconv", "tm"};
-
+      //
       // <substitution> ::= tm # ::std::tm, same for the others
       if (const IdentifierInfo *II = RD->getIdentifier()) {
         StringRef type = II->getName();
-        if (types.count(type)) {
+        if (llvm::is_contained({"div_t", "ldiv_t", "lconv", "tm"}, type)) {
           Out << type.size() << type;
           return true;
         }

>From b6cc0348e47a0c11dcd0dd253a93b0d84bad271e Mon Sep 17 00:00:00 2001
From: Rainer Orth <ro at gcc.gnu.org>
Date: Mon, 7 Oct 2024 17:02:23 +0200
Subject: [PATCH 3/3] - Handle in CXXNameMangler::mangleUnscopedName. - Extend
 testcase.

---
 clang/lib/AST/ItaniumMangle.cpp | 39 +++++++++++++++------------------
 clang/test/AST/solaris-tm.cpp   | 17 +++++++++-----
 2 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index fa504abe981d69..01ca6d3ec0def9 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -1161,8 +1161,25 @@ void CXXNameMangler::mangleUnscopedName(GlobalDecl GD, const DeclContext *DC,
   //                  ::= St <unqualified-name>   # ::std::
 
   assert(!isa<LinkageSpecDecl>(DC) && "unskipped LinkageSpecDecl");
-  if (isStdNamespace(DC))
+  if (isStdNamespace(DC)) {
+    if (getASTContext().getTargetInfo().getTriple().isOSSolaris()) {
+      const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
+      if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND)) {
+        // Issue #33114: Need non-standard mangling of std::tm etc. for
+        // Solaris ABI compatibility.
+        //
+        // <substitution> ::= tm # ::std::tm, same for the others
+        if (const IdentifierInfo *II = RD->getIdentifier()) {
+          StringRef type = II->getName();
+          if (llvm::is_contained({"div_t", "ldiv_t", "lconv", "tm"}, type)) {
+            Out << type.size() << type;
+            return;
+          }
+        }
+      }
+    }
     Out << "St";
+  }
 
   mangleUnqualifiedName(GD, DC, AdditionalAbiTags);
 }
@@ -6953,26 +6970,6 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
     return false;
   }
 
-  if (getASTContext().getTargetInfo().getTriple().isOSSolaris()) {
-    if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND)) {
-      if (!isStdNamespace(Context.getEffectiveDeclContext(RD)))
-        return false;
-
-      // Issue #33114: Need non-standard mangling of std::tm etc. for
-      // Solaris ABI compatibility.
-      //
-      // <substitution> ::= tm # ::std::tm, same for the others
-      if (const IdentifierInfo *II = RD->getIdentifier()) {
-        StringRef type = II->getName();
-        if (llvm::is_contained({"div_t", "ldiv_t", "lconv", "tm"}, type)) {
-          Out << type.size() << type;
-          return true;
-        }
-      }
-      return false;
-    }
-  }
-
   return false;
 }
 
diff --git a/clang/test/AST/solaris-tm.cpp b/clang/test/AST/solaris-tm.cpp
index f3d16b7ba1116f..e559ece1429af8 100644
--- a/clang/test/AST/solaris-tm.cpp
+++ b/clang/test/AST/solaris-tm.cpp
@@ -5,11 +5,6 @@
 // RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-unknown-linux-gnu  | FileCheck --check-prefix=CHECK-LINUX %s
 //
 // REQUIRES: x86-registered-target
-//
-// CHECK-SOLARIS: @_Z6tmfunc2tm
-// CHECK-SOLARIS: @_Z7ldtfunc6ldiv_t
-// CHECK-LINUX:   @_Z6tmfuncSt2tm
-// CHECK-LINUX:   @_Z7ldtfuncSt6ldiv_t
 
 namespace std {
   extern "C" {
@@ -22,6 +17,18 @@ namespace std {
   }
 }
 
+// CHECK-SOLARIS: @_Z6tmfunc2tm
+// CHECK-SOLARIS: @_Z9tmccpfunc2tmPKcS1_
+// CHECK-SOLARIS: @_Z7tm2func2tmS_
+// CHECK-LINUX:   @_Z6tmfuncSt2tm
+// CHECK-LINUX:   @_Z9tmccpfuncSt2tmPKcS1_
+// CHECK-LINUX:   @_Z7tm2funcSt2tmS_
+
 void tmfunc (std::tm tm) {}
+void tmccpfunc (std::tm tm, const char *ccp, const char *ccp2) {}
+void tm2func (std::tm tm, std::tm tm2) {}
+
+// CHECK-SOLARIS: @_Z7ldtfunc6ldiv_t
+// CHECK-LINUX:   @_Z7ldtfuncSt6ldiv_t
 
 void ldtfunc (std::ldiv_t ldt) {}



More information about the cfe-commits mailing list