Author: Chuanqi Xu Date: 2026-08-24T10:10:44Z New Revision: a37533905af2449ff84ee160d85647c506b8ae99
URL: https://github.com/llvm/llvm-project/commit/a37533905af2449ff84ee160d85647c506b8ae99 DIFF: https://github.com/llvm/llvm-project/commit/a37533905af2449ff84ee160d85647c506b8ae99.diff LOG: [C++20] [Modules] Do not generate call to module initialization for const init (#218346) Close https://github.com/llvm/llvm-project/issues/218305 Added: clang/test/CodeGenCXX/module-initializer-elision.cpp Modified: clang/lib/Sema/Sema.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index f1e328ccba426..21f71d7f8b40e 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1415,8 +1415,18 @@ void Sema::ActOnEndOfTranslationUnit() { if (Module *CurrentModule = getCurrentModule(); CurrentModule && CurrentModule->isInterfaceOrPartition()) { auto DoesModNeedInit = [this](Module *M) { - if (!getASTContext().getModuleInitializers(M).empty()) - return true; + for (Decl *D : getASTContext().getModuleInitializers(M)) { + auto *VD = dyn_cast<VarDecl>(D); + // TLS initialization is not handled by the TU's global initializer. + if (!VD || VD->getTLSKind() != VarDecl::TLS_None) + continue; + + if (const VarDecl *InitDecl = VD->getInitializingDeclaration(); + (InitDecl && !InitDecl->hasConstantInitialization()) || + VD->needsDestruction(getASTContext()) == + QualType::DK_cxx_destructor) + return true; + } for (auto [Exported, _] : M->Exports) if (Exported->isNamedModuleInterfaceHasInit()) return true; diff --git a/clang/test/CodeGenCXX/module-initializer-elision.cpp b/clang/test/CodeGenCXX/module-initializer-elision.cpp new file mode 100644 index 0000000000000..4ad56df802546 --- /dev/null +++ b/clang/test/CodeGenCXX/module-initializer-elision.cpp @@ -0,0 +1,94 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t +// +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 NoInit.cpp \ +// RUN: -emit-module-interface -o NoInit.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 NoInit.pcm \ +// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=NO-INIT-MODULE +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 UseNoInit.cpp \ +// RUN: -fprebuilt-module-path=%t -emit-llvm -o - | \ +// RUN: FileCheck %s --check-prefix=NO-INIT +// +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 HasDtor.cpp \ +// RUN: -emit-module-interface -o HasDtor.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 UseHasDtor.cpp \ +// RUN: -fprebuilt-module-path=%t -emit-llvm -o - | \ +// RUN: FileCheck %s --check-prefix=HAS-DTOR +// +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 HasDynamic.cpp \ +// RUN: -emit-module-interface -o HasDynamic.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 UseHasDynamic.cpp \ +// RUN: -fprebuilt-module-path=%t -emit-llvm -o - | \ +// RUN: FileCheck %s --check-prefix=HAS-DYNAMIC + +// Test again for reduced BMI +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 NoInit.cpp \ +// RUN: -emit-reduced-module-interface -o NoInit.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 NoInit.pcm \ +// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=NO-INIT-MODULE +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 UseNoInit.cpp \ +// RUN: -fprebuilt-module-path=%t -emit-llvm -o - | \ +// RUN: FileCheck %s --check-prefix=NO-INIT +// +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 HasDtor.cpp \ +// RUN: -emit-reduced-module-interface -o HasDtor.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 UseHasDtor.cpp \ +// RUN: -fprebuilt-module-path=%t -emit-llvm -o - | \ +// RUN: FileCheck %s --check-prefix=HAS-DTOR +// +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 HasDynamic.cpp \ +// RUN: -emit-reduced-module-interface -o HasDynamic.pcm +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 UseHasDynamic.cpp \ +// RUN: -fprebuilt-module-path=%t -emit-llvm -o - | \ +// RUN: FileCheck %s --check-prefix=HAS-DYNAMIC + +//--- NoInit.cpp +export module NoInit; + +// Neither constant initialization nor dynamic TLS initialization contributes +// to the module initializer. +int a = 43; +int f(); +thread_local int tls = f(); + +// NO-INIT-MODULE-LABEL: define void @_ZGIW6NoInit() +// NO-INIT-MODULE: entry: +// NO-INIT-MODULE-NEXT: ret void + +//--- UseNoInit.cpp +import NoInit; + +// NO-INIT: source_filename = {{.*}}UseNoInit.cpp +// NO-INIT-NOT: @_ZGIW6NoInit +// NO-INIT-NOT: @llvm.global_ctors + +//--- HasDtor.cpp +export module HasDtor; + +// Constant initialization still needs a module initializer when it registers a +// destructor. +struct S { + constexpr S() = default; + ~S() {} +}; +constinit S s; + +//--- UseHasDtor.cpp +import HasDtor; + +// HAS-DTOR: define internal void @_GLOBAL__sub_I_UseHasDtor.cpp() +// HAS-DTOR: call void @_ZGIW7HasDtor() + +//--- HasDynamic.cpp +export module HasDynamic; + +// Dynamic initialization contributes to the module initializer. +int f(); +int n = f(); + +//--- UseHasDynamic.cpp +import HasDynamic; + +// HAS-DYNAMIC: define internal void @_GLOBAL__sub_I_UseHasDynamic.cpp() +// HAS-DYNAMIC: call void @_ZGIW10HasDynamic() _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
