diff options
author | Jason Merrill <jason@redhat.com> | 2017-08-31 11:39:04 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2017-08-31 11:39:04 -0400 |
commit | b54d4018b17c8e7be96cedd211e7c9dd5d1c3e43 (patch) | |
tree | b4c0272397b660cccc114bdba77600bbaa9f0269 /gcc | |
parent | 28f4ff35247bb085d5de9816c6ced4dc4e14269e (diff) | |
download | gcc-b54d4018b17c8e7be96cedd211e7c9dd5d1c3e43.zip gcc-b54d4018b17c8e7be96cedd211e7c9dd5d1c3e43.tar.gz gcc-b54d4018b17c8e7be96cedd211e7c9dd5d1c3e43.tar.bz2 |
PR c++/82029 - __PRETTY_FUNCTION__ in lambda in template
* pt.c (enclosing_instantiation_of, lambda_fn_in_template_p)
(regenerated_lambda_fn_p): New.
(tsubst_decl) [VAR_DECL]: Use enclosing_instantiation_of.
(tsubst_copy) [VAR_DECL]: Likewise.
From-SVN: r251567
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/pt.c | 63 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C | 13 |
3 files changed, 78 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a8c1367..4a791dd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2017-08-30 Jason Merrill <jason@redhat.com> + PR c++/82029 - __PRETTY_FUNCTION__ in lambda in template + * pt.c (enclosing_instantiation_of, lambda_fn_in_template_p) + (regenerated_lambda_fn_p): New. + (tsubst_decl) [VAR_DECL]: Use enclosing_instantiation_of. + (tsubst_copy) [VAR_DECL]: Likewise. + PR c++/82030 - ICE inheriting from multiple lambdas PR c++/80767 * call.c (compare_ics): Handle null candidate. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f4868ab..d5ab939 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12587,6 +12587,63 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain, return r; } +/* True if FN is the op() for a lambda in an uninstantiated template. */ + +bool +lambda_fn_in_template_p (tree fn) +{ + if (!LAMBDA_FUNCTION_P (fn)) + return false; + tree closure = DECL_CONTEXT (fn); + return CLASSTYPE_TEMPLATE_INFO (closure) != NULL_TREE; +} + +/* True if FN is the op() for a lambda regenerated from a lambda in an + uninstantiated template. */ + +bool +regenerated_lambda_fn_p (tree fn) +{ + return (LAMBDA_FUNCTION_P (fn) + && !DECL_TEMPLATE_INSTANTIATION (fn)); +} + +/* We're instantiating a variable from template function TCTX. Return the + corresponding current enclosing scope. This gets complicated because lambda + functions in templates are regenerated rather than instantiated, but generic + lambda functions are subsequently instantiated. */ + +static tree +enclosing_instantiation_of (tree tctx) +{ + tree fn = current_function_decl; + int lambda_count = 0; + + for (; tctx && lambda_fn_in_template_p (tctx); + tctx = decl_function_context (tctx)) + ++lambda_count; + for (; fn; fn = decl_function_context (fn)) + { + tree lambda = fn; + int flambda_count = 0; + for (; fn && regenerated_lambda_fn_p (fn); + fn = decl_function_context (fn)) + ++flambda_count; + if (DECL_TEMPLATE_INFO (fn) + ? most_general_template (fn) != most_general_template (tctx) + : fn != tctx) + continue; + if (lambda_count) + { + fn = lambda; + while (flambda_count-- > lambda_count) + fn = decl_function_context (fn); + } + return fn; + } + gcc_unreachable (); +} + /* Substitute the ARGS into the T, which is a _DECL. Return the result of the substitution. Issue error and warning messages under control of COMPLAIN. */ @@ -12955,7 +13012,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) 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); + tree fn = enclosing_instantiation_of (DECL_CONTEXT (t)); if (fn != current_function_decl) ctx = fn; } @@ -14734,9 +14791,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (r && !is_capture_proxy (r)) { /* Make sure that the one we found is the one we want. */ - tree ctx = DECL_CONTEXT (t); - if (DECL_LANG_SPECIFIC (ctx) && DECL_TEMPLATE_INFO (ctx)) - ctx = tsubst (ctx, args, complain, in_decl); + tree ctx = enclosing_instantiation_of (DECL_CONTEXT (t)); if (ctx != DECL_CONTEXT (r)) r = NULL_TREE; } diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C new file mode 100644 index 0000000..bc0e3b2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C @@ -0,0 +1,13 @@ +// PR c++/82029 +// { dg-do compile { target c++11 } } + +template <typename> struct A { + void m_fn1() { + [] { return __func__; }(); + } +}; +struct B { + A<int> a; + void m_fn2(); +}; +void B::m_fn2() { a.m_fn1(); } |