diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3238,9 +3238,13 @@ return ConstantAddress::invalid(); } - auto *GV = new llvm::GlobalVariable( - getModule(), Init->getType(), - /*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name); + llvm::GlobalValue::LinkageTypes Linkage = + isExternallyVisible(TPO->getLinkageAndVisibility().getLinkage()) + ? llvm::GlobalValue::LinkOnceODRLinkage + : llvm::GlobalValue::InternalLinkage; + auto *GV = new llvm::GlobalVariable(getModule(), Init->getType(), + /*isConstant=*/true, Linkage, Init, Name); + setGVProperties(GV, TPO); if (supportsCOMDAT()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); Emitter.finalize(GV); diff --git a/clang/test/CodeGenCXX/template-param-objects-linkage.cpp b/clang/test/CodeGenCXX/template-param-objects-linkage.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/template-param-objects-linkage.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 %s -emit-llvm -o - | FileCheck %s + +struct S { char buf[32]; }; +template constexpr const char* f() { return s.buf; } +const char* fbuf = f(); +// CHECK: @_ZTAXtl1StlA32_cLc97EEEE = linkonce_odr constant { <{ i8, [31 x i8] }> } + +namespace { + struct UN { char buf[64]; }; +} +template constexpr const char* g() { return un.buf; } +const char* gbuf = g(); +// CHECK: @_ZTAXtlN12_GLOBAL__N_12UNEtlA64_cLc98EEEE = internal constant { <{ i8, [63 x i8] }> } + +struct Foo { int *i; }; +int m = 0; +namespace { int n; } + +template +const int* h() { return foo.i; } + +const int* hm = h(); +// CHECK: @_ZTAXtl3FooadL_Z1mEEE = linkonce_odr constant %struct.Foo { ptr @m } + +const int* hn = h(); +// CHECK: @_ZTAXtl3FooadL_ZN12_GLOBAL__N_11nEEEE = internal constant %struct.Foo { ptr @_ZN12_GLOBAL__N_11nE } diff --git a/clang/test/CodeGenCXX/template-param-objects-visibility.cpp b/clang/test/CodeGenCXX/template-param-objects-visibility.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/template-param-objects-visibility.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 %s -emit-llvm -o - | FileCheck %s + +struct S { char buf[32]; }; +template constexpr const char* f() { return s.buf; } +const char* fbuf = f(); +// CHECK: @_ZTAXtl1StlA32_cLc97EEEE = linkonce_odr constant { <{ i8, [31 x i8] }> } + +struct __attribute__ ((visibility ("hidden"))) HN { char buf[64]; }; +template constexpr const char* g() { return hn.buf; } +const char* gbuf = g(); +// CHECK: @_ZTAXtl2HNtlA64_cLc98EEEE = linkonce_odr hidden constant { <{ i8, [63 x i8] }> } diff --git a/clang/test/CodeGenCXX/template-param-objects.cpp b/clang/test/CodeGenCXX/template-param-objects.cpp --- a/clang/test/CodeGenCXX/template-param-objects.cpp +++ b/clang/test/CodeGenCXX/template-param-objects.cpp @@ -7,7 +7,9 @@ // ITANIUM: [[HELLO:@_ZTAXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100EEEE]] // MSABI: [[HELLO:@"[?][?]__N2US@@3D0GI@@0GF@@0GM@@0GM@@0GP@@0CA@@0HH@@0GP@@0HC@@0GM@@0GE@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@@@@"]] -// CHECK-SAME: = linkonce_odr constant { <{ [11 x i8], [21 x i8] }> } { <{ [11 x i8], [21 x i8] }> <{ [11 x i8] c"hello world", [21 x i8] zeroinitializer }> }, comdat +// ITANIUM-SAME: = linkonce_odr constant { <{ [11 x i8], [21 x i8] }> } { <{ [11 x i8], [21 x i8] }> <{ [11 x i8] c"hello world", [21 x i8] zeroinitializer }> }, comdat +// MSABI-SAME: = linkonce_odr dso_local constant { <{ [11 x i8], [21 x i8] }> } { <{ [11 x i8], [21 x i8] }> <{ [11 x i8] c"hello world", [21 x i8] zeroinitializer }> }, comdat + // ITANIUM: @p // MSABI: @"?p@@3PEBDEB"