This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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.
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>();
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]