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