From: Jakub Jelinek Date: Fri, 22 Mar 2019 14:42:57 +0000 (+0100) Subject: re PR c++/60702 (thread_local initialization) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5c3703c552d12e7e62febf4fe5deb837a1305f78;p=gcc.git re PR c++/60702 (thread_local initialization) 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: r269875 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 71f9d67edbe..16f1b8e1aae 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,16 @@ 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. + PR c++/87481 * constexpr.c (struct constexpr_ctx): Add constexpr_ops_count member. (cxx_eval_constant_expression): When not skipping, not constant class diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 15e39e1b545..3fe91ad2160 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6513,7 +6513,7 @@ extern tree cp_build_parm_decl (tree, 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 f8637da77da..6f23ee1cd3f 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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() { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6c15419e9cc..afb7ece57d1 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 599e0e39d4e..15b766d644d 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2143,6 +2143,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); } @@ -3788,18 +3790,10 @@ finish_id_expression_1 (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 && !dependent_p && variable_template_p (TREE_OPERAND (decl, 0))) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index f77e9c6180d..e2c5fc22ce4 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2443,6 +2443,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 febe7b3d863..8324702d242 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,21 @@ 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. + PR c++/87481 * g++.dg/cpp1y/constexpr-87481.C: New test. 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 00000000000..036d91ac41e --- /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 00000000000..761b42dfe60 --- /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 00000000000..87a17160d0a --- /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 00000000000..498bacec99a --- /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 00000000000..92add8f7db9 --- /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 00000000000..78631366ba4 --- /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 00000000000..95c44f76a05 --- /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 00000000000..e7795dc060b --- /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 00000000000..c7c964a053d --- /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 00000000000..32b6841d6b8 --- /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 00000000000..815e14eaa69 --- /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 00000000000..0009de15e0e --- /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 00000000000..589e87226ab --- /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 00000000000..273e1be020d --- /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 (); +}