aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2025-07-31 07:38:48 -0700
committerH.J. Lu <hjl.tools@gmail.com>2025-09-07 07:02:58 -0700
commita0344144dbccccf039f431a368f486f9dc6813ab (patch)
treee40d1f0b63e5ccec8b4a2c6ea72bc67c2810227c
parent93af5f69d15934edda4ff6a6eb63bde9ae7b8e45 (diff)
downloadgcc-a0344144dbccccf039f431a368f486f9dc6813ab.zip
gcc-a0344144dbccccf039f431a368f486f9dc6813ab.tar.gz
gcc-a0344144dbccccf039f431a368f486f9dc6813ab.tar.bz2
c++: Update TLS model after processing a TLS variable
Set a tentative TLS model in grokvardecl and update TLS mode with the default TLS access model after a TLS variable has been fully processed if the default TLS access model is stronger. gcc/cp/ PR c++/107393 * decl.cc (grokvardecl): Set a tentative TLS model which will be updated by cplus_decl_attributes later. * decl2.cc (cplus_decl_attributes): Update TLS model with the default TLS access model if the default TLS access model is stronger. * pt.cc (tsubst_decl): Set TLS model only after processing a variable. gcc/testsuite/ PR c++/107393 * g++.dg/tls/pr107393-1.C: New test. * g++.dg/tls/pr107393-2.C: Likewise. Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
-rw-r--r--gcc/cp/decl.cc5
-rw-r--r--gcc/cp/decl2.cc9
-rw-r--r--gcc/cp/pt.cc8
-rw-r--r--gcc/testsuite/g++.dg/tls/pr107393-1.C14
-rw-r--r--gcc/testsuite/g++.dg/tls/pr107393-2.C29
5 files changed, 61 insertions, 4 deletions
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index f088d09..a6a9842 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -12183,8 +12183,11 @@ grokvardecl (tree type,
if (DECL_EXTERNAL (decl) || TREE_STATIC (decl))
{
CP_DECL_THREAD_LOCAL_P (decl) = true;
+ // NB: Set a tentative TLS model to avoid tls_model attribute
+ // warnings due to lack of thread storage duration. It will
+ // be updated by cplus_decl_attributes later.
if (!processing_template_decl)
- set_decl_tls_model (decl, decl_default_tls_model (decl));
+ set_decl_tls_model (decl, TLS_MODEL_REAL);
}
if (declspecs->gnu_thread_keyword_p)
SET_DECL_GNU_TLS_P (decl);
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 6499be1..c9cca7b 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -2013,6 +2013,15 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags)
if (*decl == pattern)
TREE_UNAVAILABLE (tmpl) = true;
}
+
+ if (VAR_P (*decl) && CP_DECL_THREAD_LOCAL_P (*decl))
+ {
+ // tls_model attribute can set a stronger TLS access model.
+ tls_model model = DECL_TLS_MODEL (*decl);
+ tls_model default_model = decl_default_tls_model (*decl);
+ if (default_model > model)
+ set_decl_tls_model (*decl, default_model);
+ }
}
/* Walks through the namespace- or function-scope anonymous union
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 365a6c5..7f0d16f 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -16034,9 +16034,6 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
== TYPE_MAIN_VARIANT (type));
SET_DECL_VALUE_EXPR (r, ve);
}
- if (CP_DECL_THREAD_LOCAL_P (r)
- && !processing_template_decl)
- set_decl_tls_model (r, decl_default_tls_model (r));
}
else if (DECL_SELF_REFERENCE_P (t))
SET_DECL_SELF_REFERENCE_P (r);
@@ -16099,6 +16096,11 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
register_local_specialization (r, t);
}
+ if (VAR_P (r)
+ && CP_DECL_THREAD_LOCAL_P (r)
+ && !processing_template_decl)
+ set_decl_tls_model (r, decl_default_tls_model (r));
+
DECL_CHAIN (r) = NULL_TREE;
if (!apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
diff --git a/gcc/testsuite/g++.dg/tls/pr107393-1.C b/gcc/testsuite/g++.dg/tls/pr107393-1.C
new file mode 100644
index 0000000..644b4f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tls/pr107393-1.C
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++11 } }
+// { dg-require-effective-target fpic }
+// { dg-require-effective-target tls }
+// { dg-options "-O2 -fno-pic -fdump-ipa-whole-program" }
+// { dg-add-options tls }
+
+struct Dtor;
+template <typename> struct X { static thread_local Dtor m; };
+template <typename T> thread_local Dtor X<T>::m;
+extern template Dtor X<char>::m;
+void *e2 = &X<char>::m;
+
+// tls_model should be tls-initial-exec due to extern template.
+// { dg-final { scan-ipa-dump "Varpool flags: tls-initial-exec" "whole-program" } }
diff --git a/gcc/testsuite/g++.dg/tls/pr107393-2.C b/gcc/testsuite/g++.dg/tls/pr107393-2.C
new file mode 100644
index 0000000..6a69800
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tls/pr107393-2.C
@@ -0,0 +1,29 @@
+// { dg-do compile }
+// { dg-require-effective-target fpic }
+// { dg-require-effective-target tls }
+// { dg-options "-O2 -fno-pic -fdump-ipa-whole-program" }
+// { dg-add-options tls }
+
+template<class T>
+struct S {
+ static __thread int i;
+};
+
+template<class T>
+__thread int S<T>::i;
+
+extern template
+__thread int S<void>::i;
+
+int &vi()
+{
+ return S<void>::i;
+}
+
+int &ci()
+{
+ return S<char>::i;
+}
+
+// tls_model should be tls-initial-exec due to extern template.
+// { dg-final { scan-ipa-dump "Varpool flags: tls-initial-exec" "whole-program" } }