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 @@ -4337,6 +4337,23 @@ } llvm::Type* InitType = Init->getType(); + + bool ReplaceInitWithGV = false; + llvm::GlobalValue *OrigEntry = GetGlobalValue(getMangledName(D)); + if (Init == OrigEntry && OrigEntry->getValueType() != InitType) { + // Type of the initializer does not match the type of the global - + // GetAddrOfGlobalVar is going to recreate it, replace all uses of + // the original entry and erase the original entry from the + // module. + // + // However, if Init is an address of the global itself, then it is + // not a use, and thus it will not be replaced. It will become a + // dangling pointer after GetAddrOfGlobalVar. Replace it once we + // get a new GV. + // + ReplaceInitWithGV = true; + } + llvm::Constant *Entry = GetAddrOfGlobalVar(D, InitType, ForDefinition_t(!IsTentative)); @@ -4404,6 +4421,9 @@ getCUDARuntime().handleVarRegistration(D, *GV); } + if (ReplaceInitWithGV) + Init = llvm::ConstantExpr::getBitCast(GV, GV->getValueType()); + GV->setInitializer(Init); if (emitter) emitter->finalize(GV); diff --git a/clang/test/CodeGenCXX/dso-handle-custom.cpp b/clang/test/CodeGenCXX/dso-handle-custom.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/dso-handle-custom.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fexceptions %s -o - | FileCheck %s --check-prefixes CHECK,CHECK-DEFAULT +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -fexceptions %s -o - -DHIDDEN | FileCheck %s --check-prefixes CHECK,CHECK-HIDDEN + +class A { +public: + ~A(); +} a; + +// CHECK-DEFAULT: @__dso_handle = global i8* bitcast (i8** @__dso_handle to i8*), align 8 +// CHECK-HIDDEN: @__dso_handle = hidden global i8* bitcast (i8** @__dso_handle to i8*), align 8 +// CHECK: define internal void @__cxx_global_var_init() +// CHECK: call i32 @__cxa_atexit({{.*}}, {{.*}}, i8* bitcast (i8** @__dso_handle to i8*)) + +#ifdef HIDDEN +void *__dso_handle __attribute__((__visibility__("hidden"))) = &__dso_handle; +#else +void *__dso_handle = &__dso_handle; +#endif + +void use(void *); +void use_dso_handle() { + use(__dso_handle); +}