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); + } expr = convert_from_reference (expr); } --- gcc/cp/typeck.c.jj 2019-03-13 21:21:27.000000000 +0100 +++ gcc/cp/typeck.c 2019-03-15 16:23:27.582046214 +0100 @@ -2443,6 +2443,16 @@ build_class_member_access_expr (cp_expr /* A static data member. */ result = member; mark_exp_read (object); + + tree wrap; + if (!cp_unevaluated_operand + && !processing_template_decl + && CP_DECL_THREAD_LOCAL_P (result) + && (wrap = get_tls_wrapper_fn (result))) + /* Replace an evaluated use of the thread_local variable with + a call to its wrapper. */ + result = build_cxx_call (wrap, 0, NULL, tf_warning_or_error); + /* 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/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