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 <nathanieloshead@gmail.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
This commit is contained in:
Nathaniel Shead
2025-05-22 22:16:22 +10:00
parent 43dddeef7a
commit 66e9a4f308
10 changed files with 82 additions and 3 deletions

View File

@@ -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))

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;
};

View File

@@ -0,0 +1,5 @@
// PR c++/120363
// { dg-additional-options "-fmodules" }
module M;
thread_local int test::instance;

View File

@@ -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();
}

View File

@@ -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>();

View File

@@ -0,0 +1,4 @@
// { dg-additional-options "-fmodule-header" }
// { dg-module-cmi {} }
#include "tls-3.h"

View File

@@ -0,0 +1,4 @@
// { dg-additional-options "-fmodules -fno-module-lazy" }
#include "tls-3.h"
import "tls-3_a.H";