Skip to content

Commit

Permalink
[clang] Fix std::tm etc. mangling on Solaris (#106353)
Browse files Browse the repository at this point in the history
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 mangling `std::tm` as
`tm` and similarly for `std::div_t`, `std::ldiv_t`, and `std::lconv`,
which is what this patch implements. The hack needs to stay in place to
allow building with older versions of `clang`.

Tested on `amd64-pc-solaris2.11`, `sparcv9-sun-solaris2.11` (2-stage
builds with both `clang-19` and `gcc-14` as build compiler), and
`x86_64-pc-linux-gnu`.
  • Loading branch information
rorth authored Oct 7, 2024
1 parent 971b579 commit b3c1403
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 3 deletions.
4 changes: 4 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,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
^^^^^^^^^^^^^^

Expand Down
19 changes: 18 additions & 1 deletion clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1164,8 +1164,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);
}
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Lex/PPMacroExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_"
Expand Down
34 changes: 34 additions & 0 deletions clang/test/AST/solaris-tm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/// 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

namespace std {
extern "C" {
struct tm {
int tm_sec;
};
struct ldiv_t {
long quot;
};
}
}

// 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) {}

0 comments on commit b3c1403

Please sign in to comment.