On Sat, Sep 6, 2025 at 6:11 AM Jason Merrill <ja...@redhat.com> wrote: > > On 9/6/25 12:40 AM, H.J. Lu wrote: > > 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.to...@gmail.com> > > > > Fix > > > > Signed-off-by: H.J. Lu <hjl.to...@gmail.com> > > --- > > gcc/cp/decl.cc | 5 ++++- > > gcc/cp/decl2.cc | 9 +++++++++ > > gcc/cp/pt.cc | 8 +++++--- > > gcc/testsuite/g++.dg/tls/pr107393-1.C | 14 +++++++++++++ > > gcc/testsuite/g++.dg/tls/pr107393-2.C | 29 +++++++++++++++++++++++++++ > > 5 files changed, 61 insertions(+), 4 deletions(-) > > create mode 100644 gcc/testsuite/g++.dg/tls/pr107393-1.C > > create mode 100644 gcc/testsuite/g++.dg/tls/pr107393-2.C > > > > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc > > index f088d09f51e..a6a98426ed9 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); > > Do we need any change here? A tls_model attribute will override > whatever is set here, so it seems fine to use the default here as well > as in cplus_decl_attributes.
The issue is that decl_default_tls_model may return a wrong stronger model since we haven't processed the tls_model attribute yet. When it happens, cplus_decl_attributes can't override the TLS model since it is stronger than what decl_default_tls_model returns. > > > } > > 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 6499be1d33b..c9cca7b0270 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 365a6c55a83..7f0d16f217e 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 00000000000..644b4f48e36 > > --- /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 00000000000..6a69800f2a2 > > --- /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" } } > -- H.J.