diff mbox

C++ PATCH for c++/70735 (static locals and generic lambdas)

Message ID 6069d4f2-0d7e-2f7d-59f9-2290a532e9ac@redhat.com
State New
Headers show

Commit Message

Jason Merrill May 23, 2016, 7:01 p.m. UTC
Here we were failing to handle static locals referred to from a generic 
lambda properly: we decided that in that situation rather than try to 
look up the primary decl for the variable (since its function is 
probably out of scope when the lambda op() is instantiated), we can just 
build a new VAR_DECL and use that instead.  The problem with this was 
that we weren't setting DECL_CONTEXT on the new decl, so it mangled 
differently from the real decl, so references within the lambda were 
finding a different object.

Fixed for statics in non-template functions by just using the variable 
directly, and for statics in template functions by setting DECL_CONTEXT 
appropriately.

Tested x86_64-pc-linux-gnu, applying to trunk.

Comments

Paolo Carlini May 24, 2016, 10:35 p.m. UTC | #1
Hi,

On 23/05/2016 21:01, Jason Merrill wrote:
> +// PR c++/70735
> +// { dg-do run { target c++1y } }
> +
[...]
> @@ -0,0 +1,19 @@
> +// PR c++/70735
> +// { dg-do run { target c++1y } }
I'm changing these c++1y to c++14.

Paolo.
Mike Stump May 24, 2016, 11:28 p.m. UTC | #2
On May 24, 2016, at 3:35 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> On 23/05/2016 21:01, Jason Merrill wrote:
>> +// PR c++/70735
>> +// { dg-do run { target c++1y } }
>> +
> [...]
>> @@ -0,0 +1,19 @@
>> +// PR c++/70735
>> +// { dg-do run { target c++1y } }
> I'm changing these c++1y to c++14.

Thanks.  :-)  

I think:

  g++.dg/pr65295.C

can be updated to use c++14 as well.  It is the last one that needs updating.
diff mbox

Patch

commit 120812acdc3feda6cd79f634a4ac26ae0db8c087
Author: Jason Merrill <jason@redhat.com>
Date:   Fri May 20 14:00:38 2016 -0400

    	PR c++/70735 - generic lambda and local static variable
    
    	* 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.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2bba571..59d6a95 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12280,6 +12280,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
@@ -13991,7 +13999,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)
@@ -14035,14 +14044,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
index 0000000..a1667a2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static1.C
@@ -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
index 0000000..51bf75f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static2.C
@@ -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>();
+}