From: Jakub Jelinek Date: Fri, 30 Aug 2019 12:30:48 +0000 (+0200) Subject: backport: re PR c++/60702 (thread_local initialization) X-Git-Tag: releases/gcc-7.5.0~223 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=249dc8418e2f2ef19e02d68e52f9b88619fd7998;p=thirdparty%2Fgcc.git backport: re PR c++/60702 (thread_local initialization) Backported from mainline 2019-03-22 Jakub Jelinek 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. From-SVN: r275140 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5d7aaa65eb0a..14beaa8c0cf7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,6 +1,19 @@ 2019-08-30 Jakub Jelinek Backported from mainline + 2019-03-22 Jakub Jelinek + + 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. + 2019-03-21 Jakub Jelinek PR c++/89767 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 842d410f8421..7e31f9091674 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5962,7 +5962,7 @@ extern tree cp_build_parm_decl (tree, 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); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 7839e6246008..77ca73a8d5e2 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3255,7 +3255,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. */ @@ -3307,6 +3307,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() { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2df7402c905b..c85594e90db2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -17897,17 +17897,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); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index d0d0658c81fe..342857a0cb15 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2087,6 +2087,8 @@ finish_qualified_id_expr (tree qualifying_class, 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); } @@ -3746,18 +3748,10 @@ finish_id_expression (tree id_expression, *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 && variable_template_p (TREE_OPERAND (decl, 0))) { diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 3b30a1e5b195..305444b2d93f 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2378,6 +2378,12 @@ build_class_member_access_expr (cp_expr object, tree member, /* 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 21817bba375b..f4cd0d178503 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,24 @@ 2019-08-30 Jakub Jelinek Backported from mainline + 2019-03-22 Jakub Jelinek + + PR c++/60702 + * 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. + 2019-03-21 Jakub Jelinek PR c++/89767 diff --git a/gcc/testsuite/g++.dg/tls/thread_local11.C b/gcc/testsuite/g++.dg/tls/thread_local11.C new file mode 100644 index 000000000000..036d91ac41e0 --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local11.C @@ -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> (); +} diff --git a/gcc/testsuite/g++.dg/tls/thread_local11.h b/gcc/testsuite/g++.dg/tls/thread_local11.h new file mode 100644 index 000000000000..761b42dfe60a --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local11.h @@ -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 +S *f7 () { return &s3; } +template +int *f8 () { return &s4.i; } +template +S *f9 () { return &t.u5; } +template +int *f10 () { return &t.u6.i; } +template +S *f11 () { return &T::u7; } +template +int *f12 () { return &T::u8.i; } diff --git a/gcc/testsuite/g++.dg/tls/thread_local12a.C b/gcc/testsuite/g++.dg/tls/thread_local12a.C new file mode 100644 index 000000000000..87a17160d0a1 --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local12a.C @@ -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 (); +} diff --git a/gcc/testsuite/g++.dg/tls/thread_local12b.C b/gcc/testsuite/g++.dg/tls/thread_local12b.C new file mode 100644 index 000000000000..498bacec99ae --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local12b.C @@ -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 (); +} diff --git a/gcc/testsuite/g++.dg/tls/thread_local12c.C b/gcc/testsuite/g++.dg/tls/thread_local12c.C new file mode 100644 index 000000000000..92add8f7db93 --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local12c.C @@ -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 (); +} diff --git a/gcc/testsuite/g++.dg/tls/thread_local12d.C b/gcc/testsuite/g++.dg/tls/thread_local12d.C new file mode 100644 index 000000000000..78631366ba41 --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local12d.C @@ -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 (); +} diff --git a/gcc/testsuite/g++.dg/tls/thread_local12e.C b/gcc/testsuite/g++.dg/tls/thread_local12e.C new file mode 100644 index 000000000000..95c44f76a05d --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local12e.C @@ -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 (); +} diff --git a/gcc/testsuite/g++.dg/tls/thread_local12f.C b/gcc/testsuite/g++.dg/tls/thread_local12f.C new file mode 100644 index 000000000000..e7795dc060b3 --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local12f.C @@ -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 (); +} diff --git a/gcc/testsuite/g++.dg/tls/thread_local12g.C b/gcc/testsuite/g++.dg/tls/thread_local12g.C new file mode 100644 index 000000000000..c7c964a053d9 --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local12g.C @@ -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 (); +} diff --git a/gcc/testsuite/g++.dg/tls/thread_local12h.C b/gcc/testsuite/g++.dg/tls/thread_local12h.C new file mode 100644 index 000000000000..32b6841d6b8e --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local12h.C @@ -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 (); +} diff --git a/gcc/testsuite/g++.dg/tls/thread_local12i.C b/gcc/testsuite/g++.dg/tls/thread_local12i.C new file mode 100644 index 000000000000..815e14eaa69f --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local12i.C @@ -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 (); +} diff --git a/gcc/testsuite/g++.dg/tls/thread_local12j.C b/gcc/testsuite/g++.dg/tls/thread_local12j.C new file mode 100644 index 000000000000..0009de15e0eb --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local12j.C @@ -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 (); +} diff --git a/gcc/testsuite/g++.dg/tls/thread_local12k.C b/gcc/testsuite/g++.dg/tls/thread_local12k.C new file mode 100644 index 000000000000..589e87226ab8 --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local12k.C @@ -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 (); +} diff --git a/gcc/testsuite/g++.dg/tls/thread_local12l.C b/gcc/testsuite/g++.dg/tls/thread_local12l.C new file mode 100644 index 000000000000..273e1be020d7 --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/thread_local12l.C @@ -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 (); +}