https://github.com/ChuanqiXu9 created https://github.com/llvm/llvm-project/pull/218304
Close https://github.com/llvm/llvm-project/issues/212170 See the discussion above for the details. >From 396a050db6d81b315f303dae6a0339ce7b2b7dbf Mon Sep 17 00:00:00 2001 From: Chuanqi Xu <[email protected]> Date: Mon, 24 Aug 2026 09:43:17 +0800 Subject: [PATCH] [C++20] [Modules] Preserve the initializer for unused static variable in modules Close https://github.com/llvm/llvm-project/issues/212170 See the discussion above for the details. --- clang/lib/Sema/SemaDecl.cpp | 17 ++++++---- clang/test/Modules/pr212170.cppm | 54 ++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 clang/test/Modules/pr212170.cppm diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 5055ef3d1cbb1..a99fcb56d1138 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -15378,12 +15378,17 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { FinalizeVarWithDestructor(var, RD); // If this variable must be emitted, add it as an initializer for the current - // module. - if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty() && - (ModuleScopes.back().Module->isHeaderLikeModule() || - // For named modules, we may only emit non discardable variables. - !isDiscardableGVALinkage(Context.GetGVALinkageForVariable(var)))) - Context.addModuleInitializer(ModuleScopes.back().Module, var); + // module. For named modules, discardable inline variables may be deferred + // until they are odr-used. Non-inline variables that must be emitted, + // including those with side-effecting initialization, must still be emitted + // even if they have internal linkage. + if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty()) { + GVALinkage Linkage = Context.GetGVALinkageForVariable(var); + if (ModuleScopes.back().Module->isHeaderLikeModule() || + !isDiscardableGVALinkage(Linkage) || + (Linkage == GVA_Internal && !var->isInline())) + Context.addModuleInitializer(ModuleScopes.back().Module, var); + } // Build the bindings if this is a structured binding declaration. if (auto *DD = dyn_cast<DecompositionDecl>(var)) diff --git a/clang/test/Modules/pr212170.cppm b/clang/test/Modules/pr212170.cppm new file mode 100644 index 0000000000000..65442d011cc53 --- /dev/null +++ b/clang/test/Modules/pr212170.cppm @@ -0,0 +1,54 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 \ +// RUN: -emit-module-interface %t/test.cppm -o %t/test.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 \ +// RUN: -emit-llvm %t/test.pcm -o - | FileCheck %t/test.cppm \ +// RUN: --implicit-check-not=inline_bar \ +// RUN: --implicit-check-not=static_inline_bar +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 \ +// RUN: -fmodule-file=test=%t/test.pcm -emit-llvm %t/use.cpp -o - | \ +// RUN: FileCheck %t/use.cpp + +// https://github.com/llvm/llvm-project/issues/212170 + +//--- test.cppm + +export module test; + +int side_effect(); + +static int bar = side_effect(); +[[gnu::used]] static int used_bar = side_effect(); + +inline int inline_bar = side_effect(); +static inline int static_inline_bar = side_effect(); + +// CHECK-DAG: @_ZL3bar = internal global i32 0 +// CHECK-DAG: @_ZL8used_bar = internal global i32 0 + +// CHECK-LABEL: define internal void @__cxx_global_var_init() +// CHECK: call{{.*}} @_ZW4test11side_effectv() +// CHECK: store i32 {{.*}}, ptr @_ZL3bar + +// CHECK-LABEL: define internal void @__cxx_global_var_init.1() +// CHECK: call{{.*}} @_ZW4test11side_effectv() +// CHECK: store i32 {{.*}}, ptr @_ZL8used_bar + +// CHECK-LABEL: define void @_ZGIW4test() +// CHECK: call void @__cxx_global_var_init() +// CHECK: call void @__cxx_global_var_init.1() + +//--- use.cpp + +import test; + +int main() {} + +// The consumer calls the module initializer but does not emit copies of the +// module's internal variables or their initialization functions. +// CHECK-NOT: @_ZL3bar +// CHECK-NOT: @_ZL8used_bar +// CHECK: declare void @_ZGIW4test() +// CHECK-LABEL: define internal void @_GLOBAL__sub_I_use.cpp() +// CHECK: call void @_ZGIW4test() _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
