Like 52026, the problem here is that we have a reference to an outer
variable in the lambda and can't instantiate it properly. And like
52026, the solution is to look up the variable again at instantiation time.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 43d4443096a0dbb9e9424370f010372ef79717e8
Author: Jason Merrill <ja...@redhat.com>
Date: Fri Feb 15 13:52:14 2013 -0500
PR c++/54276
* semantics.c (finish_id_expression): Also return the identifier
for an outer local static.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0e09d04..458ed26 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2876,18 +2876,26 @@ baselink_for_fns (tree fns)
return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE);
}
-/* Returns true iff DECL is an automatic variable from a function outside
+/* Returns true iff DECL is a variable from a function outside
the current one. */
static bool
-outer_automatic_var_p (tree decl)
+outer_var_p (tree decl)
{
return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
&& DECL_FUNCTION_SCOPE_P (decl)
- && !TREE_STATIC (decl)
&& DECL_CONTEXT (decl) != current_function_decl);
}
+/* As above, but also checks that DECL is automatic. */
+
+static bool
+outer_automatic_var_p (tree decl)
+{
+ return (outer_var_p (decl)
+ && !TREE_STATIC (decl));
+}
+
/* ID_EXPRESSION is a representation of parsed, but unprocessed,
id-expression. (See cp_parser_id_expression for details.) SCOPE,
if non-NULL, is the type or namespace used to explicitly qualify
@@ -2994,9 +3002,18 @@ finish_id_expression (tree id_expression,
/* Disallow uses of local variables from containing functions, except
within lambda-expressions. */
- if (outer_automatic_var_p (decl)
+ if (!outer_var_p (decl)
/* It's not a use (3.2) if we're in an unevaluated context. */
- && !cp_unevaluated_operand)
+ || cp_unevaluated_operand)
+ /* OK. */;
+ else if (TREE_STATIC (decl))
+ {
+ if (processing_template_decl)
+ /* For a use of an outer static var, return the identifier so
+ that we'll look it up again in the instantiation. */
+ return id_expression;
+ }
+ else
{
tree context = DECL_CONTEXT (decl);
tree containing_function = current_function_decl;
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template9.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template9.C
new file mode 100644
index 0000000..c1d010b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template9.C
@@ -0,0 +1,15 @@
+// PR c++/54276
+// { dg-do link { target c++11 } }
+
+template <typename T>
+void foo(T)
+{
+ static int x = 1;
+ auto f = [] { return x + 1; };
+ f();
+}
+
+int main()
+{
+ foo(4);
+}