Skip to content

Commit 7aa7a52

Browse files
committed
[clang] Do not emit template parameter objects as COMDATs when they have internal linkage.
Per the ELF spec, section groups may only contain local symbols if those symbols are only referenced from within the section group. [1] In the case of template parameter objects, they can be referenced from outside the group when the type of the object was declared in an anonymous namespace. In that case, we can't place the object in a COMDAT. This matches GCC's linkage behavior on the test input. [1]: https://www.sco.com/developers/gabi/latest/ch4.sheader.html#section_groups
1 parent 2c030a1 commit 7aa7a52

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3765,7 +3765,7 @@ ConstantAddress CodeGenModule::GetAddrOfTemplateParamObject(
37653765
auto *GV = new llvm::GlobalVariable(getModule(), Init->getType(),
37663766
/*isConstant=*/true, Linkage, Init, Name);
37673767
setGVProperties(GV, TPO);
3768-
if (supportsCOMDAT())
3768+
if (supportsCOMDAT() && Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
37693769
GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
37703770
Emitter.finalize(GV);
37713771

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %clang_cc1 -emit-llvm -std=c++20 -triple x86_64-unknown-linux-gnu %s -o - | FileCheck %s
2+
3+
// COMDAT groups in ELF objects are not permitted to contain local symbols. While template parameter
4+
// objects are normally emitted in COMDATs, we shouldn't do so if they would have internal linkage.
5+
6+
extern "C" int printf(...);
7+
typedef __typeof__(sizeof(0)) size_t;
8+
9+
namespace {
10+
template<size_t N>
11+
struct DebugContext
12+
{
13+
char value[N];
14+
constexpr DebugContext(const char (&str)[N]) {
15+
for (size_t i = 0; i < N; ++i) {
16+
value[i] = str[i];
17+
}
18+
}
19+
};
20+
}
21+
22+
template<DebugContext Context>
23+
struct ConditionalDebug
24+
{
25+
public:
26+
static void log() {
27+
printf("%s", Context.value);
28+
}
29+
};
30+
31+
using Debug = ConditionalDebug<"compartment A">;
32+
33+
void foo() {
34+
Debug::log();
35+
}
36+
37+
// CHECK-NOT: $_ZTAXtlN12_GLOBAL__N_112DebugContextILm14EEEtlA14_cLc99ELc111ELc109ELc112ELc97ELc114ELc116ELc109ELc101ELc110ELc116ELc32ELc65EEEE = comdat any
38+
// CHECK: @_ZTAXtlN12_GLOBAL__N_112DebugContextILm14EEEtlA14_cLc99ELc111ELc109ELc112ELc97ELc114ELc116ELc109ELc101ELc110ELc116ELc32ELc65EEEE = internal constant %"struct.(anonymous namespace)::DebugContext" { [14 x i8] c"compartment A\00" }

0 commit comments

Comments
 (0)