https://gcc.gnu.org/g:66e9a4f3083356b064cc64651edad466a56f762b

commit r16-856-g66e9a4f3083356b064cc64651edad466a56f762b
Author: Nathaniel Shead <nathanielosh...@gmail.com>
Date:   Thu May 22 22:16:22 2025 +1000

    c++/modules: Fix merge of TLS init functions [PR120363]
    
    The PR notes that we missed setting DECL_CONTEXT on the TLS init
    function; we missed this initially because this function is not created
    in header units, only named modules.
    
    I also noticed that 'DECL_CONTEXT (fn) = DECL_CONTEXT (var)' was
    incorrect: for class members, this ends up having the modules merging
    machinery treat the decl as a member function, which breaks when
    attempting to dedup against an existing completed class type.  Instead
    we can just use the global_namespace as the context, because the name of
    the function is already mangled appropriately so that we'll match the
    correct duplicates.
    
            PR c++/120363
    
    gcc/cp/ChangeLog:
    
            * decl2.cc (get_tls_init_fn): Set context as global_namespace.
            (get_tls_wrapper_fn): Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/modules/pr113292_a.H: Move to...
            * g++.dg/modules/tls-1_a.H: ...here.
            * g++.dg/modules/pr113292_b.C: Move to...
            * g++.dg/modules/tls-1_b.C: ...here.
            * g++.dg/modules/pr113292_c.C: Move to...
            * g++.dg/modules/tls-1_c.C: ...here.
            * g++.dg/modules/tls-2_a.C: New test.
            * g++.dg/modules/tls-2_b.C: New test.
            * g++.dg/modules/tls-2_c.C: New test.
            * g++.dg/modules/tls-3.h: New test.
            * g++.dg/modules/tls-3_a.H: New test.
            * g++.dg/modules/tls-3_b.C: New test.
    
    Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com>
    Reviewed-by: Jason Merrill <ja...@redhat.com>

Diff:
---
 gcc/cp/decl2.cc                                    |  3 +-
 .../g++.dg/modules/{pr113292_a.H => tls-1_a.H}     |  0
 .../g++.dg/modules/{pr113292_b.C => tls-1_b.C}     |  2 +-
 .../g++.dg/modules/{pr113292_c.C => tls-1_c.C}     |  2 +-
 gcc/testsuite/g++.dg/modules/tls-2_a.C             | 12 +++++++
 gcc/testsuite/g++.dg/modules/tls-2_b.C             |  5 +++
 gcc/testsuite/g++.dg/modules/tls-2_c.C             | 11 ++++++
 gcc/testsuite/g++.dg/modules/tls-3.h               | 42 ++++++++++++++++++++++
 gcc/testsuite/g++.dg/modules/tls-3_a.H             |  4 +++
 gcc/testsuite/g++.dg/modules/tls-3_b.C             |  4 +++
 10 files changed, 82 insertions(+), 3 deletions(-)

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index a08d173c0df5..666ab784dee5 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -4028,6 +4028,7 @@ get_tls_init_fn (tree var)
       SET_DECL_LANGUAGE (fn, lang_c);
       TREE_PUBLIC (fn) = TREE_PUBLIC (var);
       DECL_ARTIFICIAL (fn) = true;
+      DECL_CONTEXT (fn) = FROB_CONTEXT (global_namespace);
       DECL_COMDAT (fn) = DECL_COMDAT (var);
       DECL_EXTERNAL (fn) = DECL_EXTERNAL (var);
       if (DECL_ONE_ONLY (var))
@@ -4087,7 +4088,7 @@ get_tls_wrapper_fn (tree var)
       TREE_PUBLIC (fn) = TREE_PUBLIC (var);
       DECL_ARTIFICIAL (fn) = true;
       DECL_IGNORED_P (fn) = 1;
-      DECL_CONTEXT (fn) = DECL_CONTEXT (var);
+      DECL_CONTEXT (fn) = FROB_CONTEXT (global_namespace);
       /* The wrapper is inline and emitted everywhere var is used.  */
       DECL_DECLARED_INLINE_P (fn) = true;
       if (TREE_PUBLIC (var))
diff --git a/gcc/testsuite/g++.dg/modules/pr113292_a.H 
b/gcc/testsuite/g++.dg/modules/tls-1_a.H
similarity index 100%
rename from gcc/testsuite/g++.dg/modules/pr113292_a.H
rename to gcc/testsuite/g++.dg/modules/tls-1_a.H
diff --git a/gcc/testsuite/g++.dg/modules/pr113292_b.C 
b/gcc/testsuite/g++.dg/modules/tls-1_b.C
similarity index 93%
rename from gcc/testsuite/g++.dg/modules/pr113292_b.C
rename to gcc/testsuite/g++.dg/modules/tls-1_b.C
index fc582a5a0cfe..941bff2710aa 100644
--- a/gcc/testsuite/g++.dg/modules/pr113292_b.C
+++ b/gcc/testsuite/g++.dg/modules/tls-1_b.C
@@ -1,7 +1,7 @@
 // PR c++/113292
 // { dg-additional-options "-fmodules-ts" }
 
-import "pr113292_a.H";
+import "tls-1_a.H";
 
 // provide a definition of 'instance' so things link
 thread_local test test::instance;
diff --git a/gcc/testsuite/g++.dg/modules/pr113292_c.C 
b/gcc/testsuite/g++.dg/modules/tls-1_c.C
similarity index 93%
rename from gcc/testsuite/g++.dg/modules/pr113292_c.C
rename to gcc/testsuite/g++.dg/modules/tls-1_c.C
index b5acf79db63c..4568413bb226 100644
--- a/gcc/testsuite/g++.dg/modules/pr113292_c.C
+++ b/gcc/testsuite/g++.dg/modules/tls-1_c.C
@@ -4,7 +4,7 @@
 // { dg-add-options tls }
 // { dg-additional-options "-fmodules-ts" }
 
-import "pr113292_a.H";
+import "tls-1_a.H";
 
 int main() {
   auto& instance = test::get_instance();
diff --git a/gcc/testsuite/g++.dg/modules/tls-2_a.C 
b/gcc/testsuite/g++.dg/modules/tls-2_a.C
new file mode 100644
index 000000000000..2efae6c00b5c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tls-2_a.C
@@ -0,0 +1,12 @@
+// PR c++/120363
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi M }
+
+export module M;
+
+export struct test {
+  static inline const int& get_instance() {
+    return instance;
+  }
+  static thread_local int instance;
+};
diff --git a/gcc/testsuite/g++.dg/modules/tls-2_b.C 
b/gcc/testsuite/g++.dg/modules/tls-2_b.C
new file mode 100644
index 000000000000..af3e70949c51
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tls-2_b.C
@@ -0,0 +1,5 @@
+// PR c++/120363
+// { dg-additional-options "-fmodules" }
+
+module M;
+thread_local int test::instance;
diff --git a/gcc/testsuite/g++.dg/modules/tls-2_c.C 
b/gcc/testsuite/g++.dg/modules/tls-2_c.C
new file mode 100644
index 000000000000..4489516fa7b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tls-2_c.C
@@ -0,0 +1,11 @@
+// PR c++/120363
+// { dg-module-do link }
+// { dg-require-effective-target tls_runtime }
+// { dg-add-options tls }
+// { dg-additional-options "-fmodules" }
+
+import M;
+
+int main() {
+  auto& instance = test::get_instance();
+}
diff --git a/gcc/testsuite/g++.dg/modules/tls-3.h 
b/gcc/testsuite/g++.dg/modules/tls-3.h
new file mode 100644
index 000000000000..6f4a236b7ebc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tls-3.h
@@ -0,0 +1,42 @@
+inline thread_local int tla;
+inline int& get_tla() {
+  return tla;
+}
+
+static thread_local int tlb;
+static int& get_tlb() {
+  return tlb;
+}
+
+struct test {
+  static const test& get_instance() {
+    return instance;
+  }
+  static thread_local test instance;
+};
+
+template <typename T>
+struct test_template {
+  static const test_template& get_instance() {
+    return instance;
+  }
+  static thread_local test_template instance;
+
+  template <typename U>
+  static const test_template& get_template_instance() {
+    return template_instance<U>;
+  }
+
+  template <typename U>
+  static thread_local test_template template_instance;
+};
+
+template <typename T>
+thread_local test_template<T> test_template<T>::instance;
+
+template <typename T>
+template <typename U>
+thread_local test_template<T> test_template<T>::template_instance;
+
+template struct test_template<int>;
+template const test_template<int>& 
test_template<int>::get_template_instance<int>();
diff --git a/gcc/testsuite/g++.dg/modules/tls-3_a.H 
b/gcc/testsuite/g++.dg/modules/tls-3_a.H
new file mode 100644
index 000000000000..beef907128b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tls-3_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#include "tls-3.h"
diff --git a/gcc/testsuite/g++.dg/modules/tls-3_b.C 
b/gcc/testsuite/g++.dg/modules/tls-3_b.C
new file mode 100644
index 000000000000..ab77b1ec0770
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tls-3_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules -fno-module-lazy" }
+
+#include "tls-3.h"
+import "tls-3_a.H";

Reply via email to