[clang] [WIP][clang] Fix std::tm etc. mangling on Solaris (PR #106353)
Rainer Orth via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 28 02:28:44 PDT 2024
https://github.com/rorth created https://github.com/llvm/llvm-project/pull/106353
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.
>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] [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) {}
More information about the cfe-commits
mailing list