In this testcase the compiler is confused by the local class and thinks that the lambda is in the context of the enclosing function. Fixed by recognizing when a lambda is directly within a local class.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit f5ba54d8bcbd15d6d9519b0140a5e430e9822dcb
Author: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Tue Jan 6 20:44:39 2015 +0000

    	PR c++/64496
    	* semantics.c (process_outer_var_ref): Diagnose lambda in local
    	class NSDMI.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@219266 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 44d9a2e..551bad1 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3141,8 +3141,12 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain)
     while (context != containing_function
 	   && LAMBDA_FUNCTION_P (containing_function))
       {
-	lambda_expr = CLASSTYPE_LAMBDA_EXPR
-	  (DECL_CONTEXT (containing_function));
+	tree closure = DECL_CONTEXT (containing_function);
+	lambda_expr = CLASSTYPE_LAMBDA_EXPR (closure);
+
+	if (TYPE_CLASS_SCOPE_P (closure))
+	  /* A lambda in an NSDMI (c++/64496).  */
+	  break;
 
 	if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr)
 	    == CPLD_NONE)
@@ -3172,7 +3176,19 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain)
   else if (lambda_expr)
     {
       if (complain & tf_error)
-	error ("%qD is not captured", decl);
+	{
+	  error ("%qD is not captured", decl);
+	  tree closure = LAMBDA_EXPR_CLOSURE (lambda_expr);
+	  if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr)
+	      == CPLD_NONE)
+	    inform (location_of (closure),
+		    "the lambda has no capture-default");
+	  else if (TYPE_CLASS_SCOPE_P (closure))
+	    inform (0, "lambda in local class %q+T cannot "
+		    "capture variables from the enclosing context",
+		    TYPE_CONTEXT (closure));
+	  inform (input_location, "%q+#D declared here", decl);
+	}
       return error_mark_node;
     }
   else
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi7.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi7.C
new file mode 100644
index 0000000..30595ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi7.C
@@ -0,0 +1,25 @@
+// PR c++/64496
+// { dg-do compile { target c++11 } }
+
+template <typename> class B;
+template <typename W, typename... X>
+struct B<W(X...)> { template <typename F> B(F); };
+template <typename W, typename... X>
+template <typename F>
+B<W(X...)>::B(F) {}
+
+int
+main()
+{
+  int a;
+  struct A			// { dg-message "lambda in local class" }
+  {
+    B<void()> l = [=] {
+      a;			// { dg-error "not captured" }
+    };
+  };
+  [] {				// { dg-message "capture-default" }
+    a;				// { dg-error "not captured" }
+  };
+  A t;
+}

Reply via email to