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;
+}