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
This commit is contained in:
Jason Merrill 2013-02-15 14:22:14 -05:00 committed by Jason Merrill
parent 4791895176
commit 9fd30fece6
3 changed files with 43 additions and 7 deletions

View File

@ -1,5 +1,9 @@
2013-02-15 Jason Merrill <jason@redhat.com> 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 PR c++/56343
* class.c (check_bases_and_members): Deduce noexcept after * class.c (check_bases_and_members): Deduce noexcept after
checking bases. checking bases.

View File

@ -2876,16 +2876,24 @@ baselink_for_fns (tree fns)
return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE); 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. */ the current one. */
static bool
outer_var_p (tree decl)
{
return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
&& DECL_FUNCTION_SCOPE_P (decl)
&& DECL_CONTEXT (decl) != current_function_decl);
}
/* As above, but also checks that DECL is automatic. */
static bool static bool
outer_automatic_var_p (tree decl) outer_automatic_var_p (tree decl)
{ {
return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL) return (outer_var_p (decl)
&& DECL_FUNCTION_SCOPE_P (decl) && !TREE_STATIC (decl));
&& !TREE_STATIC (decl)
&& DECL_CONTEXT (decl) != current_function_decl);
} }
/* ID_EXPRESSION is a representation of parsed, but unprocessed, /* ID_EXPRESSION is a representation of parsed, but unprocessed,
@ -2994,9 +3002,18 @@ finish_id_expression (tree id_expression,
/* Disallow uses of local variables from containing functions, except /* Disallow uses of local variables from containing functions, except
within lambda-expressions. */ 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. */ /* 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 context = DECL_CONTEXT (decl);
tree containing_function = current_function_decl; tree containing_function = current_function_decl;

View File

@ -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);
}