On 01/31/2017 10:04 AM, Jason Merrill wrote:
Agreed. As I was suggesting in response to one of Adam's patches, I think we need to defer creating the closure until f is instantiated; at that point we can resolve all names from f and so we should be able to always push to top when instantiating the lambda.
Yup.
Perhaps if (!fn_context || fn_context != current_function_decl)
That works fine, thanks. It also makes it clearer that 'nested' must be true if !push_to_top (but not vice-versa), which allowed a little more simplification.
Committed the attached to trunk. nathan -- Nathan Sidwell
2017-01-31 Nathan Sidwell <nat...@acm.org> PR c++/67273 PR c++/79253 * pt.c: (instantiate_decl): Push to top level when current function scope doesn't match. Only push lmabda scope stack when pushing to top. PR c++/67273 PR c++/79253 * g++.dg/cpp1y/pr67273.C: New. * g++.dg/cpp1y/pr79253.C: New. Index: cp/pt.c =================================================================== --- cp/pt.c (revision 245066) +++ cp/pt.c (working copy) @@ -22666,20 +22666,21 @@ instantiate_decl (tree d, bool defer_ok, goto out; } - bool nested; + bool push_to_top, nested; tree fn_context; fn_context = decl_function_context (d); - nested = (current_function_decl != NULL_TREE); + nested = current_function_decl != NULL_TREE; + push_to_top = !(nested && fn_context == current_function_decl); + vec<tree> omp_privatization_save; if (nested) save_omp_privatization_clauses (omp_privatization_save); - if (!fn_context) + if (push_to_top) push_to_top_level (); else { - if (nested) - push_function_context (); + push_function_context (); cp_unevaluated_operand = 0; c_inhibit_evaluation_warnings = 0; } @@ -22756,7 +22757,7 @@ instantiate_decl (tree d, bool defer_ok, block = push_stmt_list (); else { - if (LAMBDA_FUNCTION_P (d)) + if (push_to_top && LAMBDA_FUNCTION_P (d)) { /* When instantiating a lambda's templated function operator, we need to push the non-lambda class scope @@ -22849,9 +22850,9 @@ instantiate_decl (tree d, bool defer_ok, /* We're not deferring instantiation any more. */ TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (d)) = 0; - if (!fn_context) + if (push_to_top) pop_from_top_level (); - else if (nested) + else pop_function_context (); if (nested) Index: testsuite/g++.dg/cpp1y/pr67273.C =================================================================== --- testsuite/g++.dg/cpp1y/pr67273.C (revision 0) +++ testsuite/g++.dg/cpp1y/pr67273.C (working copy) @@ -0,0 +1,16 @@ +// { dg-do compile { target c++14 } } +// { dg-additional-options "-Wshadow" } + +// pr67273 bogus warning about shadowing. + + +template <typename T> void Foo (T &&lambda) +{ + int ARG = 2; + lambda (1); +} + +void Baz () +{ + Foo ([] (auto &&ARG) {}); +} Index: testsuite/g++.dg/cpp1y/pr79253.C =================================================================== --- testsuite/g++.dg/cpp1y/pr79253.C (revision 0) +++ testsuite/g++.dg/cpp1y/pr79253.C (working copy) @@ -0,0 +1,33 @@ +// { dg-do compile { target c++14 } } +// PR 79253 ICE instantiating lambda body. + +template <typename> struct A; +template <typename = A<int>> class B {}; +template <class T, class U, class V> void foo (U, V) { T (0, 0); } +struct C {}; +template <template <bool, bool, bool> class F, class> +void +bar () +{ + F<0, 0, 0>::baz; +} +struct G { int l; }; +template <int, int, int> struct E : C +{ + E (int, int) : e (0) + { + auto &m = this->m (); + auto c = [&] { m.l; }; + } + G &m (); + int e; +}; +struct D +{ + void + baz () { bar<F, B<>>; } + template <bool, bool, bool> struct F + { + static B<> baz () { foo<E<0, 0, 0>> (0, 0); } + }; +};