diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6201bdaa036..232acc6772b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2016-05-23 Jason Merrill + + PR c++/70735 + * pt.c (tsubst_copy): Just return a local variable from + non-template context. Don't call rest_of_decl_compilation for + duplicated static locals. + (tsubst_decl): Set DECL_CONTEXT of local static from another + function. + 2016-05-23 Paolo Carlini PR c++/70972 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2ce8f40f791..3e07fb0b6e0 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12281,6 +12281,14 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) local_p = true; /* Subsequent calls to pushdecl will fill this in. */ ctx = NULL_TREE; + /* Unless this is a reference to a static variable from an + enclosing function, in which case we need to fill it in now. */ + if (TREE_STATIC (t)) + { + tree fn = tsubst (DECL_CONTEXT (t), args, complain, in_decl); + if (fn != current_function_decl) + ctx = fn; + } spec = retrieve_local_specialization (t); } /* If we already have the specialization we need, there is @@ -13992,7 +14000,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) case FUNCTION_DECL: if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)) r = tsubst (t, args, complain, in_decl); - else if (local_variable_p (t)) + else if (local_variable_p (t) + && uses_template_parms (DECL_CONTEXT (t))) { r = retrieve_local_specialization (t); if (r == NULL_TREE) @@ -14036,14 +14045,9 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) gcc_assert (cp_unevaluated_operand || TREE_STATIC (r) || decl_constant_var_p (r) || errorcount || sorrycount); - if (!processing_template_decl) - { - if (TREE_STATIC (r)) - rest_of_decl_compilation (r, toplevel_bindings_p (), - at_eof); - else - r = process_outer_var_ref (r, complain); - } + if (!processing_template_decl + && !TREE_STATIC (r)) + r = process_outer_var_ref (r, complain); } /* Remember this for subsequent uses. */ if (local_specializations) diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static1.C new file mode 100644 index 00000000000..a1667a2de47 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static1.C @@ -0,0 +1,13 @@ +// PR c++/70735 +// { dg-do run { target c++1y } } + +int main() +{ + static int a; + auto f = [](auto) { return a; }; + if (f(0) != 0) + __builtin_abort(); + a = 1; + if (f(0) != 1) + __builtin_abort(); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static2.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static2.C new file mode 100644 index 00000000000..51bf75f20ba --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static2.C @@ -0,0 +1,19 @@ +// PR c++/70735 +// { dg-do run { target c++1y } } + +template +static void g() +{ + static int a; + auto f = [](auto) { return a; }; + if (f(0) != 0) + __builtin_abort(); + a = 1; + if (f(0) != 1) + __builtin_abort(); +} + +int main() +{ + g(); +}