On 3/15/19 4:53 PM, Jakub Jelinek wrote:
Hi!

As the testcase shows, we replace TLS vars that need initialization
in finish_id_expression_1 and in tsubst_copy_and_build of a VAR_DECL
with a _ZTW* call, but miss it in other cases where finish_id_expression
is not actually called.  In particular build_class_member_access_expr
when we do object.static_tls_data_member access doesn't wrap it, and
when using some_class::static_tls_data_member in a teplate, we go
through finish_qualified_id_expr and not finish_id_expression either
(and tsubst_copy in that case, so it doesn't go through
tsubst_copy_and_build).

The following patch fixes that.  While it is not a regression, it is a
serious wrong-code issue that just gained 6th reporter of the same issue.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2019-03-15  Jakub Jelinek  <ja...@redhat.com>

        PR c++/60702
        * semantics.c (finish_qualified_id_expr): Handle accesses to TLS
        variables.
        * typeck.c (build_class_member_access_expr): Likewise.

        * g++.dg/tls/thread_local11.C: New test.
        * g++.dg/tls/thread_local11.h: New test.
        * g++.dg/tls/thread_local12a.C: New test.
        * g++.dg/tls/thread_local12b.C: New test.
        * g++.dg/tls/thread_local12c.C: New test.
        * g++.dg/tls/thread_local12d.C: New test.
        * g++.dg/tls/thread_local12e.C: New test.
        * g++.dg/tls/thread_local12f.C: New test.
        * g++.dg/tls/thread_local12g.C: New test.
        * g++.dg/tls/thread_local12h.C: New test.
        * g++.dg/tls/thread_local12i.C: New test.
        * g++.dg/tls/thread_local12j.C: New test.
        * g++.dg/tls/thread_local12k.C: New test.
        * g++.dg/tls/thread_local12l.C: New test.

--- gcc/cp/semantics.c.jj       2019-03-14 09:14:16.718012031 +0100
+++ gcc/cp/semantics.c  2019-03-15 16:53:14.270384477 +0100
@@ -2135,6 +2135,17 @@ finish_qualified_id_expr (tree qualifyin
        expr = build_qualified_name (TREE_TYPE (expr),
                                     qualifying_class, expr,
                                     template_p);
+      else if (VAR_P (expr)
+              && !processing_template_decl
+              && !cp_unevaluated_operand
+              && (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
+              && CP_DECL_THREAD_LOCAL_P (expr))
+       {
+         if (tree wrap = get_tls_wrapper_fn (expr))
+           /* Replace an evaluated use of the thread_local variable with
+              a call to its wrapper.  */
+           expr = build_cxx_call (wrap, 0, NULL, tf_warning_or_error);
+       }

Let's factor this pattern out into another function. And we don't need to check TREE_STATIC || DECL_EXTERNAL anymore.

Jason

Reply via email to