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

Reply via email to