aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2013-02-15 14:22:14 -0500
committerJason Merrill <jason@gcc.gnu.org>2013-02-15 14:22:14 -0500
commit9fd30fece6891bcd427a5b793d8020a657959760 (patch)
tree61d03cb82a12362afce84796980c24dea58b2707
parent479189517610591e746369fc4d80302f5cebdbd7 (diff)
downloadgcc-9fd30fece6891bcd427a5b793d8020a657959760.zip
gcc-9fd30fece6891bcd427a5b793d8020a657959760.tar.gz
gcc-9fd30fece6891bcd427a5b793d8020a657959760.tar.bz2
re PR c++/54276 (Lambda in a Template Function Undefined Reference to local static)
PR c++/54276 * semantics.c (finish_id_expression): Also return the identifier for an outer local static. From-SVN: r196091
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/semantics.c27
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template9.C15
3 files changed, 41 insertions, 5 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2dab029..921c6a4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
2013-02-15 Jason Merrill <jason@redhat.com>
+ PR c++/54276
+ * semantics.c (finish_id_expression): Also return the identifier
+ for an outer local static.
+
PR c++/56343
* class.c (check_bases_and_members): Deduce noexcept after
checking bases.
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);
+}