PR c++/70735 - generic lambda and local static variable
authorJason Merrill <jason@redhat.com>
Mon, 23 May 2016 21:21:18 +0000 (17:21 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 23 May 2016 21:21:18 +0000 (17:21 -0400)
* pt.c (tsubst_copy): Just return a local variable from
non-template context.  Don't call rest_of_decl_compilation for
duplicated static locals.
(tsubst_decl): Set DECL_CONTEXT of local static from another
function.

From-SVN: r236615

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp1y/lambda-generic-static1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/lambda-generic-static2.C [new file with mode: 0644]

index 6201bdaa036f36ce3ca1eba3c8825ccba9d3d83d..232acc6772b6f1646e48b632eef1ea688863daf9 100644 (file)
@@ -1,3 +1,12 @@
+2016-05-23  Jason Merrill  <jason@redhat.com>
+
+       PR c++/70735
+       * pt.c (tsubst_copy): Just return a local variable from
+       non-template context.  Don't call rest_of_decl_compilation for
+       duplicated static locals.
+       (tsubst_decl): Set DECL_CONTEXT of local static from another
+       function.
+
 2016-05-23  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/70972
index 2ce8f40f791400aac50cf80351fe6b1b239c2a30..3e07fb0b6e0a32fcfd86079f0882238ab17dcd28 100644 (file)
@@ -12281,6 +12281,14 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            local_p = true;
            /* Subsequent calls to pushdecl will fill this in.  */
            ctx = NULL_TREE;
+           /* Unless this is a reference to a static variable from an
+              enclosing function, in which case we need to fill it in now.  */
+           if (TREE_STATIC (t))
+             {
+               tree fn = tsubst (DECL_CONTEXT (t), args, complain, in_decl);
+               if (fn != current_function_decl)
+                 ctx = fn;
+             }
            spec = retrieve_local_specialization (t);
          }
        /* If we already have the specialization we need, there is
@@ -13992,7 +14000,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case FUNCTION_DECL:
       if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
        r = tsubst (t, args, complain, in_decl);
-      else if (local_variable_p (t))
+      else if (local_variable_p (t)
+              && uses_template_parms (DECL_CONTEXT (t)))
        {
          r = retrieve_local_specialization (t);
          if (r == NULL_TREE)
@@ -14036,14 +14045,9 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
                  gcc_assert (cp_unevaluated_operand || TREE_STATIC (r)
                              || decl_constant_var_p (r)
                              || errorcount || sorrycount);
-                 if (!processing_template_decl)
-                   {
-                     if (TREE_STATIC (r))
-                       rest_of_decl_compilation (r, toplevel_bindings_p (),
-                                                 at_eof);
-                     else
-                       r = process_outer_var_ref (r, complain);
-                   }
+                 if (!processing_template_decl
+                     && !TREE_STATIC (r))
+                   r = process_outer_var_ref (r, complain);
                }
              /* Remember this for subsequent uses.  */
              if (local_specializations)
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static1.C
new file mode 100644 (file)
index 0000000..a1667a2
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/70735
+// { dg-do run { target c++1y } }
+
+int main()
+{
+  static int a;
+  auto f = [](auto) { return a; };
+  if (f(0) != 0)
+    __builtin_abort();
+  a = 1;
+  if (f(0) != 1)
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static2.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static2.C
new file mode 100644 (file)
index 0000000..51bf75f
--- /dev/null
@@ -0,0 +1,19 @@
+// PR c++/70735
+// { dg-do run { target c++1y } }
+
+template <class T>
+static void g()
+{
+  static int a;
+  auto f = [](auto) { return a; };
+  if (f(0) != 0)
+    __builtin_abort();
+  a = 1;
+  if (f(0) != 1)
+    __builtin_abort();
+}
+
+int main()
+{
+  g<int>();
+}