-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Fix std::tm etc. mangling on Solaris #106353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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.
@llvm/pr-subscribers-clang Author: Rainer Orth (rorth) ChangesRecently, Solaris bootstrap got broken because Solaris uses a non-standard mangling of Tested on Unfortunately, this patch is almost there, but not quite yet: while the new testcase works as expected, the original trigger in Full diff: https://github.com/llvm/llvm-project/pull/106353.diff 3 Files Affected:
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) {}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also add a changelog entry?
Thanks!
clang/lib/AST/ItaniumMangle.cpp
Outdated
// <substitution> ::= tm # ::std::tm, same for the others | ||
if (const IdentifierInfo *II = RD->getIdentifier()) { | ||
StringRef type = II->getName(); | ||
if (types.count(type)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (types.count(type)) { | |
if (llvm::is_contained({"div_t", "ldiv_t", "lconv", "tm"}, type)) { |
using a std::set is a bit overkill here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do: I'm pretty ignorant of C++ actually...
#if defined(__sun__) && defined(__svr4__) && defined(__clang__) && \ | ||
__clang__ < 20 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does every version of gcc we support handles that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Certainly: the fix for GCC PR libstdc++-v3/1773 went in 13 years ago. That should be good enough ;-)
I've never seen them used in LLVM. Has that changed recently? |
Check out |
Ah, that. I was thinking of the GNU style |
- Use llvm::is_contained.
Incorporate review comments. However, I still have a mis-mangling of the code that triggered this patch. I've now been able to create a reduced example:
On Linux/x86_64, Any suggestions? |
The code assumes standard substitutions are not themselves substitutable. So you probably need to call mangleSubstitution/addSubstitution explicitly in the code. mangleSubstitution checks if there's an existing substitution, addSubstitution appends to the list of substitutions. See https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-compression . Make sure you have a testcase with a function that takes two std::tm arguments. |
Ah, that makes sense. I can see this when compiling my testcase for However, I'm still having a hard time around here: a simple
just leads to infinite recursion (obviously), but I couldn't find how to drop the |
Try casting the pointer to uintptr_t? Might be simpler to mess with CXXNameMangler::mangleUnscopedName, though, which I think is where the St prefix is getting added. |
That just created a total mess, unfortunately, like duplicating args or dropping the
This worked seamlessly indeed. Thanks for the suggestion. I'm currently running a last round of testing and will post the working patch once I'm done. |
- Extend testcase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
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 #100724. The Solaris ABI requires manglingstd::tm
astm
and similarly forstd::div_t
,std::ldiv_t
, andstd::lconv
, which is what this patch implements. The hack needs to stay in place to allow building with older versions ofclang
.Tested on
amd64-pc-solaris2.11
,sparcv9-sun-solaris2.11
(2-stage builds with bothclang-19
andgcc-14
as build compiler), andx86_64-pc-linux-gnu
.