On Thu, Mar 21, 2019 at 07:31:44PM -0400, Jason Merrill wrote: > How about > > else if (tree wrap = maybe_call_tls_wrapper_fn (expr)) > expr = wrap;
LGTM. Here is the full patch I've bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2019-03-22 Jakub Jelinek <ja...@redhat.com> PR c++/60702 * cp-tree.h (get_tls_wrapper_fn): Remove declaration. (maybe_get_tls_wrapper_call): Declare. * decl2.c (get_tls_wrapper_fn): Make static. (maybe_get_tls_wrapper_call): New function. * typeck.c (build_class_member_access_expr): Handle accesses to TLS variables. * semantics.c (finish_qualified_id_expr): Likewise. (finish_id_expression_1): Use maybe_get_tls_wrapper_call. * pt.c (tsubst_copy_and_build): 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/cp-tree.h.jj 2019-03-21 22:58:21.982655423 +0100 +++ gcc/cp/cp-tree.h 2019-03-22 09:01:02.002112835 +0100 @@ -6513,7 +6513,7 @@ extern tree cp_build_parm_decl (tree, extern tree get_guard (tree); extern tree get_guard_cond (tree, bool); extern tree set_guard (tree); -extern tree get_tls_wrapper_fn (tree); +extern tree maybe_get_tls_wrapper_call (tree); extern void mark_needed (tree); extern bool decl_needed_p (tree); extern void note_vague_linkage_fn (tree); --- gcc/cp/decl2.c.jj 2019-03-11 22:56:51.889732197 +0100 +++ gcc/cp/decl2.c 2019-03-22 09:01:23.678755950 +0100 @@ -3442,7 +3442,7 @@ get_tls_init_fn (tree var) VAR and then returns a reference to VAR. The wrapper function is used in place of VAR everywhere VAR is mentioned. */ -tree +static tree get_tls_wrapper_fn (tree var) { /* Only C++11 TLS vars need this wrapper fn. */ @@ -3496,6 +3496,22 @@ get_tls_wrapper_fn (tree var) return fn; } +/* If EXPR is a thread_local variable that should be wrapped by init + wrapper function, return a call to that function, otherwise return + NULL. */ + +tree +maybe_get_tls_wrapper_call (tree expr) +{ + if (VAR_P (expr) + && !processing_template_decl + && !cp_unevaluated_operand + && CP_DECL_THREAD_LOCAL_P (expr)) + if (tree wrap = get_tls_wrapper_fn (expr)) + return build_cxx_call (wrap, 0, NULL, tf_warning_or_error); + return NULL; +} + /* At EOF, generate the definition for the TLS wrapper function FN: T& var_wrapper() { --- gcc/cp/typeck.c.jj 2019-03-19 07:46:39.065896955 +0100 +++ gcc/cp/typeck.c 2019-03-22 09:03:52.203310668 +0100 @@ -2443,6 +2443,12 @@ build_class_member_access_expr (cp_expr /* A static data member. */ result = member; mark_exp_read (object); + + if (tree wrap = maybe_get_tls_wrapper_call (result)) + /* Replace an evaluated use of the thread_local variable with + a call to its wrapper. */ + result = wrap; + /* If OBJECT has side-effects, they are supposed to occur. */ if (TREE_SIDE_EFFECTS (object)) result = build2 (COMPOUND_EXPR, TREE_TYPE (result), object, result); --- gcc/cp/semantics.c.jj 2019-03-18 10:48:29.710038297 +0100 +++ gcc/cp/semantics.c 2019-03-22 09:03:01.823140117 +0100 @@ -2143,6 +2143,8 @@ finish_qualified_id_expr (tree qualifyin expr = build_qualified_name (TREE_TYPE (expr), qualifying_class, expr, template_p); + else if (tree wrap = maybe_get_tls_wrapper_call (expr)) + expr = wrap; expr = convert_from_reference (expr); } @@ -3788,18 +3790,10 @@ finish_id_expression_1 (tree id_expressi *non_integral_constant_expression_p = true; } - tree wrap; - if (VAR_P (decl) - && !cp_unevaluated_operand - && !processing_template_decl - && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)) - && CP_DECL_THREAD_LOCAL_P (decl) - && (wrap = get_tls_wrapper_fn (decl))) - { - /* Replace an evaluated use of the thread_local variable with - a call to its wrapper. */ - decl = build_cxx_call (wrap, 0, NULL, tf_warning_or_error); - } + if (tree wrap = maybe_get_tls_wrapper_call (decl)) + /* Replace an evaluated use of the thread_local variable with + a call to its wrapper. */ + decl = wrap; else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR && !dependent_p && variable_template_p (TREE_OPERAND (decl, 0))) --- gcc/cp/pt.c.jj 2019-03-21 22:58:30.481517816 +0100 +++ gcc/cp/pt.c 2019-03-22 09:17:25.286923144 +0100 @@ -19403,17 +19403,10 @@ tsubst_copy_and_build (tree t, { tree r = tsubst_copy (t, args, complain, in_decl); /* ??? We're doing a subset of finish_id_expression here. */ - if (VAR_P (r) - && !processing_template_decl - && !cp_unevaluated_operand - && (TREE_STATIC (r) || DECL_EXTERNAL (r)) - && CP_DECL_THREAD_LOCAL_P (r)) - { - if (tree wrap = get_tls_wrapper_fn (r)) - /* Replace an evaluated use of the thread_local variable with - a call to its wrapper. */ - r = build_cxx_call (wrap, 0, NULL, tf_warning_or_error); - } + if (tree wrap = maybe_get_tls_wrapper_call (r)) + /* Replace an evaluated use of the thread_local variable with + a call to its wrapper. */ + r = wrap; else if (outer_automatic_var_p (r)) r = process_outer_var_ref (r, complain); --- gcc/testsuite/g++.dg/tls/thread_local11.C.jj 2019-03-15 17:02:44.752275408 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local11.C 2019-03-15 17:31:19.199665422 +0100 @@ -0,0 +1,48 @@ +// PR c++/60702 +// { dg-do compile { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } +// { dg-additional-options "-fdump-tree-gimple" } +// { dg-final { scan-tree-dump-times "_ZTW2s1" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTW2s2" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTW2s3" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTW2s4" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u1E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u2E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u3E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u4E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u5E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u6E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u7E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTWN1T2u8E" 2 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTH2s1" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTH2s2" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTH2s3" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTH2s4" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u1E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u2E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u3E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u4E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u5E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u6E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u7E" 1 "gimple" } } +// { dg-final { scan-tree-dump-times "_ZTHN1T2u8E" 1 "gimple" } } + +#include "thread_local11.h" + +void +foo () +{ + f1 (); + f2 (); + f3 (); + f4 (); + f5 (); + f6 (); + f7<0> (); + f8<0> (); + f9<0> (); + f10<0> (); + f11<0> (); + f12<0> (); +} --- gcc/testsuite/g++.dg/tls/thread_local11.h.jj 2019-03-15 17:30:31.198440309 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local11.h 2019-03-15 17:31:00.667964581 +0100 @@ -0,0 +1,26 @@ +// PR c++/60702 + +extern "C" void abort (); +struct S { S () { i = 42; }; int i; }; +thread_local S s1, s2, s3, s4; +struct T { static thread_local S u1, u2, u3, u4, u5, u6, u7, u8; int i; } t; +thread_local S T::u1, T::u2, T::u3, T::u4, T::u5, T::u6, T::u7, T::u8; + +S *f1 () { return &s1; } +int *f2 () { return &s2.i; } +S *f3 () { return &t.u1; } +int *f4 () { return &t.u2.i; } +S *f5 () { return &T::u3; } +int *f6 () { return &T::u4.i; } +template <int N> +S *f7 () { return &s3; } +template <int N> +int *f8 () { return &s4.i; } +template <int N> +S *f9 () { return &t.u5; } +template <int N> +int *f10 () { return &t.u6.i; } +template <int N> +S *f11 () { return &T::u7; } +template <int N> +int *f12 () { return &T::u8.i; } --- gcc/testsuite/g++.dg/tls/thread_local12a.C.jj 2019-03-15 17:26:42.911125577 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local12a.C 2019-03-15 17:33:26.482610680 +0100 @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (f1 ()->i != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12b.C.jj 2019-03-15 17:35:25.549685123 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local12b.C 2019-03-15 17:33:34.781476709 +0100 @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (*f2 () != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12c.C.jj 2019-03-15 17:35:25.549685123 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local12c.C 2019-03-15 17:33:42.843346568 +0100 @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (f3 ()->i != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12d.C.jj 2019-03-15 17:35:25.549685123 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local12d.C 2019-03-15 17:33:56.433127186 +0100 @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (*f4 () != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12e.C.jj 2019-03-15 17:35:25.549685123 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local12e.C 2019-03-15 17:34:04.892990612 +0100 @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (f5 ()->i != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12f.C.jj 2019-03-15 17:35:25.549685123 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local12f.C 2019-03-15 17:34:13.534851108 +0100 @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (*f6 () != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12g.C.jj 2019-03-15 17:35:25.549685123 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local12g.C 2019-03-15 17:34:22.050713633 +0100 @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (f7<0> ()->i != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12h.C.jj 2019-03-15 17:35:25.549685123 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local12h.C 2019-03-15 17:34:31.316564053 +0100 @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (*f8<0> () != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12i.C.jj 2019-03-15 17:35:25.549685123 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local12i.C 2019-03-15 17:34:41.387401475 +0100 @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (f9<0> ()->i != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12j.C.jj 2019-03-15 17:35:25.549685123 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local12j.C 2019-03-15 17:34:50.933247380 +0100 @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (*f10<0> () != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12k.C.jj 2019-03-15 17:35:25.549685123 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local12k.C 2019-03-15 17:35:01.798071988 +0100 @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (f11<0> ()->i != 42) abort (); +} --- gcc/testsuite/g++.dg/tls/thread_local12l.C.jj 2019-03-15 17:35:25.550685107 +0100 +++ gcc/testsuite/g++.dg/tls/thread_local12l.C 2019-03-15 17:35:09.352948983 +0100 @@ -0,0 +1,12 @@ +// PR c++/60702 +// { dg-do run { target c++11 } } +// { dg-add-options tls } +// { dg-require-effective-target tls_runtime } + +#include "thread_local11.h" + +int +main () +{ + if (*f12<0> () != 42) abort (); +} Jakub