re PR middle-end/58624 (gcc internal compiler error: Segmentaion fault in insert_to_a...
authorJason Merrill <jason@redhat.com>
Tue, 26 Aug 2014 19:39:36 +0000 (15:39 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 26 Aug 2014 19:39:36 +0000 (15:39 -0400)
PR c++/58624
* pt.c (tsubst_decl) [VAR_DECL]: Copy TLS model.
(tsubst_copy_and_build) [VAR_DECL]: Use TLS wrapper.
* semantics.c (finish_id_expression): Don't call TLS wrapper in a
template.

From-SVN: r214543

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/tls/thread_local10.C [new file with mode: 0644]

index 04394c31ab6b232d6b1030cb8c21ac8689c55130..388293a806b89de1f01fa29cd4f7eb1881cc543d 100644 (file)
@@ -1,3 +1,11 @@
+2014-08-26  Jason Merrill  <jason@redhat.com>
+
+       PR c++/58624
+       * pt.c (tsubst_decl) [VAR_DECL]: Copy TLS model.
+       (tsubst_copy_and_build) [VAR_DECL]: Use TLS wrapper.
+       * semantics.c (finish_id_expression): Don't call TLS wrapper in a
+       template.
+
 2014-08-25  Jason Merrill  <jason@redhat.com>
 
        * pt.c (check_explicit_specialization): Don't complain about
index 59df38722a8f672081b80b114b10a0151d6bed84..eac837f0a032207f58b59d9461045635d61753f3 100644 (file)
@@ -11225,6 +11225,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
                  }
                SET_DECL_VALUE_EXPR (r, ve);
              }
+           if (TREE_STATIC (r) || DECL_EXTERNAL (r))
+             set_decl_tls_model (r, decl_tls_model (t));
          }
        else if (DECL_SELF_REFERENCE_P (t))
          SET_DECL_SELF_REFERENCE_P (r);
@@ -15410,6 +15412,17 @@ tsubst_copy_and_build (tree t,
     case PARM_DECL:
       {
        tree r = tsubst_copy (t, args, complain, in_decl);
+       if (VAR_P (r)
+           && !processing_template_decl
+           && !cp_unevaluated_operand
+           && (TREE_STATIC (r) || DECL_EXTERNAL (r))
+           && 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_CODE (TREE_TYPE (t)) != REFERENCE_TYPE)
          /* If the original type was a reference, we'll be wrapped in
index 16abad0572b1af1cb132bf452abe9ff9ba8a1945..9c9fc1c08826ecd4cdd04adbe629c5143217711d 100644 (file)
@@ -3500,6 +3500,7 @@ finish_id_expression (tree id_expression,
       tree wrap;
       if (VAR_P (decl)
          && !cp_unevaluated_operand
+         && !processing_template_decl
          && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
          && DECL_THREAD_LOCAL_P (decl)
          && (wrap = get_tls_wrapper_fn (decl)))
diff --git a/gcc/testsuite/g++.dg/tls/thread_local10.C b/gcc/testsuite/g++.dg/tls/thread_local10.C
new file mode 100644 (file)
index 0000000..48c1b86
--- /dev/null
@@ -0,0 +1,23 @@
+// PR c++/58624
+
+// { dg-do run { target c++11 } }
+// { dg-add-options tls }
+// { dg-require-effective-target tls_runtime }
+
+int i;
+
+template <typename> struct A
+{
+  static thread_local int s;
+
+  A () { i = s; }
+};
+
+int f() { return 42; }
+template <typename T> thread_local int A<T>::s = f();
+
+int main () {
+  A<void> a;
+  if (i != 42)
+    __builtin_abort();
+}