Give reference temporaries private linkage if their variable has strong,
external linkage.
http://reviews.llvm.org/D3515
Files:
lib/CodeGen/CGDecl.cpp
lib/CodeGen/CGDeclCXX.cpp
lib/CodeGen/CodeGenModule.cpp
test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp
test/CodeGenCXX/const-init-cxx11.cpp
test/CodeGenCXX/const-init-cxx1y.cpp
test/CodeGenCXX/cxx11-thread-local.cpp
test/CodeGenCXX/cxx1y-variable-template.cpp
test/CodeGenCXX/specialized-static-data-mem-init.cpp
test/CodeGenCXX/static-init-3.cpp
test/CodeGenCXX/template-instantiation.cpp
test/CodeGenCXX/vla.cpp
Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp
+++ lib/CodeGen/CGDecl.cpp
@@ -126,17 +126,11 @@
void CodeGenFunction::EmitVarDecl(const VarDecl &D) {
if (D.isStaticLocal()) {
llvm::GlobalValue::LinkageTypes Linkage =
- llvm::GlobalValue::InternalLinkage;
+ CGM.GetLLVMLinkageVarDefinition(&D, /*isConstant=*/false);
- // If the variable is externally visible, it must have weak linkage so it
- // can be uniqued.
- if (D.isExternallyVisible()) {
- Linkage = llvm::GlobalValue::LinkOnceODRLinkage;
-
- // FIXME: We need to force the emission/use of a guard variable for
- // some variables even if we can constant-evaluate them because
- // we can't guarantee every translation unit will constant-evaluate them.
- }
+ // FIXME: We need to force the emission/use of a guard variable for
+ // some variables even if we can constant-evaluate them because
+ // we can't guarantee every translation unit will constant-evaluate them.
return EmitStaticVarDecl(D, Linkage);
}
Index: lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- lib/CodeGen/CGDeclCXX.cpp
+++ lib/CodeGen/CGDeclCXX.cpp
@@ -417,8 +417,8 @@
// Use guarded initialization if the global variable is weak. This
// occurs for, e.g., instantiated static data members and
// definitions explicitly marked weak.
- if (Addr->getLinkage() == llvm::GlobalValue::WeakODRLinkage ||
- Addr->getLinkage() == llvm::GlobalValue::WeakAnyLinkage) {
+ if (llvm::GlobalVariable::isWeakLinkage(Addr->getLinkage()) ||
+ llvm::GlobalVariable::isLinkOnceLinkage(Addr->getLinkage())) {
EmitCXXGuardedInit(*D, Addr, PerformInit);
} else {
EmitCXXGlobalVarDeclInit(*D, Addr, PerformInit);
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -1987,8 +1987,10 @@
return llvm::GlobalVariable::WeakODRLinkage;
else
return llvm::GlobalVariable::WeakAnyLinkage;
- } else if (Linkage == GVA_TemplateInstantiation || Linkage == GVA_StrongODR)
+ } else if (Linkage == GVA_StrongODR)
return llvm::GlobalVariable::WeakODRLinkage;
+ else if (Linkage == GVA_TemplateInstantiation)
+ return llvm::Function::LinkOnceODRLinkage;
else if (D->getTLSKind() == VarDecl::TLS_Dynamic &&
getTarget().getTriple().isMacOSX())
// On Darwin, the backing variable for a C++11 thread_local variable always
@@ -2001,9 +2003,17 @@
// If required by the ABI, give definitions of static data members with inline
// initializers linkonce_odr linkage.
return llvm::GlobalVariable::LinkOnceODRLinkage;
- // C++ doesn't have tentative definitions and thus cannot have common linkage.
- else if (!getLangOpts().CPlusPlus &&
- !isVarDeclStrongDefinition(D, CodeGenOpts.NoCommon))
+ else if (D->isStaticLocal()) {
+ // If the variable is externally visible, it must have weak linkage so it
+ // can be uniqued.
+ if (D->isExternallyVisible())
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+ else
+ return llvm::GlobalValue::InternalLinkage;
+ } else if (!getLangOpts().CPlusPlus &&
+ !isVarDeclStrongDefinition(D, CodeGenOpts.NoCommon))
+ // C++ doesn't have tentative definitions and thus cannot have common
+ // linkage.
return llvm::GlobalVariable::CommonLinkage;
return llvm::GlobalVariable::ExternalLinkage;
@@ -2860,10 +2870,16 @@
}
// Create a global variable for this lifetime-extended temporary.
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(getModule(), Type, Constant,
- llvm::GlobalValue::PrivateLinkage,
- InitialValue, Name.c_str());
+ llvm::GlobalValue::LinkageTypes Linkage =
+ GetLLVMLinkageVarDefinition(VD, Constant);
+ if (Linkage == llvm::GlobalVariable::ExternalLinkage)
+ Linkage = llvm::GlobalVariable::PrivateLinkage;
+ unsigned AddrSpace = GetGlobalVarAddressSpace(
+ VD, getContext().getTargetAddressSpace(MaterializedType));
+ llvm::GlobalVariable *GV = new llvm::GlobalVariable(
+ getModule(), Type, Constant, Linkage, InitialValue, Name.c_str(),
+ /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal,
+ AddrSpace);
GV->setAlignment(
getContext().getTypeAlignInChars(MaterializedType).getQuantity());
if (VD->getTLSKind())
Index: test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp
===================================================================
--- test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp
+++ test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp
@@ -20,8 +20,8 @@
// For implicit instantiation of
long& get(bool Cond1, bool Cond2) {
- // CHECK: @_ZN1XIlE7member1E = weak_odr global i64 0
- // CHECK: @_ZN1XIlE7member2E = weak_odr global i64 17
+ // CHECK: @_ZN1XIlE7member1E = linkonce_odr global i64 0
+ // CHECK: @_ZN1XIlE7member2E = linkonce_odr global i64 17
// CHECK: @_ZN1XIlE7member3E = external global i64
return Cond1? X<long>::member1
: Cond2? X<long>::member2
Index: test/CodeGenCXX/const-init-cxx11.cpp
===================================================================
--- test/CodeGenCXX/const-init-cxx11.cpp
+++ test/CodeGenCXX/const-init-cxx11.cpp
@@ -393,6 +393,9 @@
// CHECK: @_ZZN12LocalVarInit3aggEvE1a = internal constant {{.*}} i32 101
// CHECK: @_ZZN12LocalVarInit4ctorEvE1a = internal constant {{.*}} i32 102
// CHECK: @_ZZN12LocalVarInit8mutable_EvE1a = private unnamed_addr constant {{.*}} i32 103
+// CHECK: @_ZGRN33ClassTemplateWithStaticDataMember1SIvE1aE = linkonce_odr constant i32 5
+// CHECK: @_ZN33ClassTemplateWithStaticDataMember3useE = constant i32* @_ZGRN33ClassTemplateWithStaticDataMember1SIvE1aE
+// CHECK: @_ZGRZN20InlineStaticConstRef3funEvE1i = linkonce_odr constant i32 10
// Constant initialization tests go before this point,
// dynamic initialization tests go after.
@@ -552,3 +555,22 @@
// CHECK: call {{.*}} @_ZN4Null4nullEv(
int S::*q = null();
}
+
+namespace InlineStaticConstRef {
+ inline const int &fun() {
+ static const int &i = 10;
+ return i;
+ // CHECK: ret i32* @_ZGRZN20InlineStaticConstRef3funEvE1i
+ }
+ const int &use = fun();
+}
+
+namespace ClassTemplateWithStaticDataMember {
+ template <typename T>
+ struct S {
+ static const int &a;
+ };
+ template <typename T>
+ const int &S<T>::a = 5;
+ const int &use = S<void>::a;
+}
Index: test/CodeGenCXX/const-init-cxx1y.cpp
===================================================================
--- test/CodeGenCXX/const-init-cxx1y.cpp
+++ test/CodeGenCXX/const-init-cxx1y.cpp
@@ -38,6 +38,36 @@
// CHECK: @_ZN21ModifyStaticTemporary1cE = global {{.*}} zeroinitializer
}
+// CHECK: @_ZGRN28VariableTemplateWithConstRef1iIvEE = linkonce_odr constant i32 5, align 4
+// CHECK: @_ZN28VariableTemplateWithConstRef3useE = constant i32* @_ZGRN28VariableTemplateWithConstRef1iIvEE
+namespace VariableTemplateWithConstRef {
+ template <typename T>
+ const int &i = 5;
+ const int &use = i<void>;
+}
+
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE = linkonce_odr constant i32 1
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3 = linkonce_odr constant i32 2
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3 }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5 = linkonce_odr constant i32 3
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5 }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7 = linkonce_odr constant i32 4
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE8 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7 }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE9 = linkonce_odr global {{.*}} { {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2, {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4, {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6, {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE8 }
+// CHECK: @_ZN24VariableTemplateWithPack1pE = global {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE9
+namespace VariableTemplateWithPack {
+ struct A {
+ const int &r;
+ };
+ struct S {
+ A &&a, &&b, &&c, &&d;
+ };
+ template <int... N>
+ S &&s = {A{N}...};
+ S *p = &s<1, 2, 3, 4>;
+}
+
// CHECK: __cxa_atexit({{.*}} @_ZN1BD1Ev {{.*}} @b
// CHECK: define
Index: test/CodeGenCXX/cxx11-thread-local.cpp
===================================================================
--- test/CodeGenCXX/cxx11-thread-local.cpp
+++ test/CodeGenCXX/cxx11-thread-local.cpp
@@ -21,7 +21,7 @@
// CHECK: @e = global i32 0
int e = V<int>::m;
-// CHECK: @_ZN1VIiE1mE = weak_odr thread_local global i32 0
+// CHECK: @_ZN1VIiE1mE = linkonce_odr thread_local global i32 0
// CHECK: @_ZZ1fvE1n = internal thread_local global i32 0
@@ -35,18 +35,18 @@
// CHECK: @_ZZ8tls_dtorvE1u = internal thread_local global
// CHECK: @_ZGVZ8tls_dtorvE1u = internal thread_local global i8 0
-// CHECK: @_ZGRZ8tls_dtorvE1u = private thread_local global
+// CHECK: @_ZGRZ8tls_dtorvE1u = internal thread_local global
-// CHECK: @_ZGVN1VIiE1mE = weak_odr thread_local global i64 0
+// CHECK: @_ZGVN1VIiE1mE = linkonce_odr thread_local global i64 0
// CHECK: @__tls_guard = internal thread_local global i8 0
// CHECK: @llvm.global_ctors = appending global {{.*}} @[[GLOBAL_INIT:[^ ]*]]
// CHECK: @_ZTH1a = alias void ()* @__tls_init
// CHECK: @_ZTHL1d = alias internal void ()* @__tls_init
// CHECK: @_ZTHN1U1mE = alias void ()* @__tls_init
-// CHECK: @_ZTHN1VIiE1mE = alias weak_odr void ()* @__tls_init
+// CHECK: @_ZTHN1VIiE1mE = alias linkonce_odr void ()* @__tls_init
// Individual variable initialization functions:
Index: test/CodeGenCXX/cxx1y-variable-template.cpp
===================================================================
--- test/CodeGenCXX/cxx1y-variable-template.cpp
+++ test/CodeGenCXX/cxx1y-variable-template.cpp
@@ -18,7 +18,7 @@
template<typename T> template<typename U> template<typename V> int Outer<T>::Inner<U>::arr[sizeof(T) + sizeof(U) + sizeof(V)] = { init_arr() };
int *p = Outer<char[100]>::Inner<char[20]>::arr<char[3]>;
-// CHECK: @_ZN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = weak_odr global [123 x i32] zeroinitializer
-// CHECK: @_ZGVN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = weak_odr global
+// CHECK: @_ZN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global [123 x i32] zeroinitializer
+// CHECK: @_ZGVN5OuterIA100_cE5InnerIA20_cE3arrIA3_cEE = linkonce_odr global
// CHECK: call {{.*}}@_Z8init_arrv
Index: test/CodeGenCXX/specialized-static-data-mem-init.cpp
===================================================================
--- test/CodeGenCXX/specialized-static-data-mem-init.cpp
+++ test/CodeGenCXX/specialized-static-data-mem-init.cpp
@@ -2,8 +2,8 @@
// rdar: // 8562966
// pr8409
-// CHECK: @_ZN1CIiE11needs_guardE = weak_odr global
-// CHECK: @_ZGVN1CIiE11needs_guardE = weak_odr global
+// CHECK: @_ZN1CIiE11needs_guardE = linkonce_odr global
+// CHECK: @_ZGVN1CIiE11needs_guardE = linkonce_odr global
struct K
{
Index: test/CodeGenCXX/static-init-3.cpp
===================================================================
--- test/CodeGenCXX/static-init-3.cpp
+++ test/CodeGenCXX/static-init-3.cpp
@@ -16,8 +16,8 @@
}
};
-// CHECK: @_ZN2X1I2X2I1BEE8instanceE = weak_odr global %struct.X2* null, align 8
-// CHECJ: @_ZN2X1I2X2I1AEE8instanceE = weak_odr global %struct.X2* null, align 8
+// CHECK: @_ZN2X1I2X2I1BEE8instanceE = linkonce_odr global %struct.X2* null, align 8
+// CHECJ: @_ZN2X1I2X2I1AEE8instanceE = linkonce_odr global %struct.X2* null, align 8
template<class T> T & X1<T>::instance = X1<T>::get();
class A { };
Index: test/CodeGenCXX/template-instantiation.cpp
===================================================================
--- test/CodeGenCXX/template-instantiation.cpp
+++ test/CodeGenCXX/template-instantiation.cpp
@@ -9,8 +9,8 @@
// CHECK-NOT: @_ZTVN5test018stdio_sync_filebufIA2_iEE
// CHECK: @_ZTVN5test018stdio_sync_filebufIA3_iEE = weak_odr unnamed_addr constant
-// CHECK: @_ZN7PR100011SIiE3arrE = weak_odr global [3 x i32]
-// CHECK-NOT: @_ZN7PR100011SIiE3arr2E = weak_odr global [3 x i32]A
+// CHECK: @_ZN7PR100011SIiE3arrE = linkonce_odr global [3 x i32]
+// CHECK-NOT: @_ZN7PR100011SIiE3arr2E = linkonce_odr global [3 x i32]A
// CHECK: @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr unnamed_addr constant
Index: test/CodeGenCXX/vla.cpp
===================================================================
--- test/CodeGenCXX/vla.cpp
+++ test/CodeGenCXX/vla.cpp
@@ -9,7 +9,7 @@
int f() {
// Make sure that the reference here is enough to trigger the instantiation of
// the static data member.
- // CHECK: @_ZN1SIiE1nE = weak_odr global i32 5
+ // CHECK: @_ZN1SIiE1nE = linkonce_odr global i32 5
int a[S<int>::n];
return sizeof a;
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits