[llvm-branch-commits] [clang] release/19.x: [C++20] [Modules] Fix the duplicated static initializer problem (#114193) (PR #114197)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Oct 30 02:33:12 PDT 2024
https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/114197
Backport 259eaa6878ead1e2e7ef572a874dc3d885c1899b
Requested by: @ChuanqiXu9
>From 6a3b8b5c12d45c5f981e90dae1a1e6c40d986cc7 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <yedeng.yd at linux.alibaba.com>
Date: Wed, 30 Oct 2024 17:27:04 +0800
Subject: [PATCH] [C++20] [Modules] Fix the duplicated static initializer
problem (#114193)
Reproducer:
```
//--- a.cppm
export module a;
int func();
static int a = func();
//--- a.cpp
import a;
```
The `func()` should only execute once. However, before this patch we
will somehow import `static int a` from a.cppm incorrectly and
initialize that again.
This is super bad and can introduce serious runtime behaviors.
And also surprisingly, it looks like the root cause of the problem is
simply some oversight choosing APIs.
(cherry picked from commit 259eaa6878ead1e2e7ef572a874dc3d885c1899b)
---
clang/lib/CodeGen/CodeGenModule.cpp | 4 ++--
clang/test/Modules/static-initializer.cppm | 18 ++++++++++++++++++
2 files changed, 20 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Modules/static-initializer.cppm
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 151505baf38db1..2a5d5f9083ae65 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -7080,8 +7080,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
// For C++ standard modules we are done - we will call the module
// initializer for imported modules, and that will likewise call those for
// any imports it has.
- if (CXX20ModuleInits && Import->getImportedOwningModule() &&
- !Import->getImportedOwningModule()->isModuleMapModule())
+ if (CXX20ModuleInits && Import->getImportedModule() &&
+ Import->getImportedModule()->isNamedModule())
break;
// For clang C++ module map modules the initializers for sub-modules are
diff --git a/clang/test/Modules/static-initializer.cppm b/clang/test/Modules/static-initializer.cppm
new file mode 100644
index 00000000000000..10d4854ee67fa6
--- /dev/null
+++ b/clang/test/Modules/static-initializer.cppm
@@ -0,0 +1,18 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/a.cpp -fmodule-file=a=%t/a.pcm -emit-llvm -o - | FileCheck %t/a.cpp
+
+//--- a.cppm
+export module a;
+int func();
+static int a = func();
+
+//--- a.cpp
+import a;
+
+// CHECK-NOT: internal global
+// CHECK-NOT: __cxx_global_var_init
+
More information about the llvm-branch-commits
mailing list