On Sat, Sep 6, 2025 at 6:11 AM Jason Merrill <[email protected]> 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 <[email protected]>
> >
> > Fix
> >
> > Signed-off-by: H.J. Lu <[email protected]>
> > ---
> > 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.