[C++20] [Modules] Don't generate global ctors/dtors for variables which are available externally
Closes https://github.com/llvm/llvm-project/issues/59765. Currently we will generate the global ctor/dtor for variables in importing modules. It will cause multiple initialization/destructions. It makes no sense. This patch tries to not generate global ctor/dtor for variables which are available externally. Note that the variables in header units and clang modules won't be available externally by default. Reviewed By: iains Differential Revision: https://reviews.llvm.org/D140867
This commit is contained in:
@@ -345,6 +345,9 @@ Bug Fixes
|
||||
`Issue 59792 <https://github.com/llvm/llvm-project/issues/59792>`_
|
||||
- Fix an issue that makes Clang crash on lambda template parameters. This fixes
|
||||
`Issue 57960 <https://github.com/llvm/llvm-project/issues/57960>`_
|
||||
- Fix issue that the standard C++ modules importer will call global
|
||||
constructor/destructor for the global varaibles in the importing modules.
|
||||
This fixes `Issue 59765 <https://github.com/llvm/llvm-project/issues/59765>`_
|
||||
|
||||
Improvements to Clang's diagnostics
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -4824,7 +4824,13 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
|
||||
|
||||
llvm::TrackingVH<llvm::Constant> Init;
|
||||
bool NeedsGlobalCtor = false;
|
||||
// Whether the definition of the variable is available externally.
|
||||
// If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable
|
||||
// since this is the job for its original source.
|
||||
bool IsDefinitionAvailableExternally =
|
||||
getContext().GetGVALinkageForVariable(D) == GVA_AvailableExternally;
|
||||
bool NeedsGlobalDtor =
|
||||
!IsDefinitionAvailableExternally &&
|
||||
D->needsDestruction(getContext()) == QualType::DK_cxx_destructor;
|
||||
|
||||
const VarDecl *InitDecl;
|
||||
@@ -4878,7 +4884,9 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
|
||||
if (InitDecl->hasFlexibleArrayInit(getContext()))
|
||||
ErrorUnsupported(D, "flexible array initializer");
|
||||
Init = EmitNullConstant(T);
|
||||
NeedsGlobalCtor = true;
|
||||
|
||||
if (!IsDefinitionAvailableExternally)
|
||||
NeedsGlobalCtor = true;
|
||||
} else {
|
||||
ErrorUnsupported(D, "static initializer");
|
||||
Init = llvm::UndefValue::get(getTypes().ConvertType(T));
|
||||
|
||||
58
clang/test/CodeGenCXX/pr59765-modules-global-ctor-dtor.cppm
Normal file
58
clang/test/CodeGenCXX/pr59765-modules-global-ctor-dtor.cppm
Normal file
@@ -0,0 +1,58 @@
|
||||
// https://github.com/llvm/llvm-project/issues/59765
|
||||
// RUN: rm -rf %t
|
||||
// RUN: mkdir %t
|
||||
// RUN: split-file %s %t
|
||||
//
|
||||
// RUN: %clang_cc1 -std=c++20 %t/M.cppm -triple %itanium_abi_triple -emit-module-interface -o %t/M.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 %t/M.pcm -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/M.cppm
|
||||
// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/Use.cpp
|
||||
//
|
||||
// Check that the behavior of header units is normal as headers.
|
||||
// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -xc++-user-header %t/foo.h -emit-header-unit -o %t/foo.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 %t/UseHU.cpp -fmodule-file=%t/foo.pcm -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/UseHU.cpp
|
||||
|
||||
//--- M.cppm
|
||||
export module M;
|
||||
export class A {
|
||||
public:
|
||||
A();
|
||||
~A();
|
||||
void use();
|
||||
};
|
||||
export A a;
|
||||
|
||||
// CHECK: @_ZW1M1a = {{.*}}global %class.A zeroinitializer
|
||||
// CHECK: define{{.*}}void @__cxx_global_var_init()
|
||||
// CHECK-NEXT: entry:
|
||||
// CHECK-NEXT: call{{.*}}void @_ZNW1M1AC1Ev({{.*}}@_ZW1M1a
|
||||
// CHECK-NEXT: call{{.*}}i32 @__cxa_atexit(ptr @_ZNW1M1AD1Ev, ptr @_ZW1M1a
|
||||
|
||||
//--- Use.cpp
|
||||
import M;
|
||||
void use() {
|
||||
a.use();
|
||||
}
|
||||
|
||||
// CHECK-NOT: @_ZNW1M1AC1Ev
|
||||
// CHECK-NOT: @_ZNW1M1AD1Ev
|
||||
|
||||
//--- foo.h
|
||||
class A {
|
||||
public:
|
||||
A();
|
||||
~A();
|
||||
void use();
|
||||
};
|
||||
A a;
|
||||
|
||||
//--- UseHU.cpp
|
||||
import "foo.h";
|
||||
void use() {
|
||||
a.use();
|
||||
}
|
||||
|
||||
// CHECK: @a = {{.*}}global %class.A zeroinitializer
|
||||
// CHECK: define{{.*}}void @__cxx_global_var_init()
|
||||
// CHECK-NEXT: entry:
|
||||
// CHECK-NEXT: call{{.*}}void @_ZN1AC1Ev({{.*}}@a
|
||||
// CHECK-NEXT: call{{.*}}i32 @__cxa_atexit(ptr @_ZN1AD1Ev, ptr @a
|
||||
Reference in New Issue
Block a user