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
This commit is contained in:
parent
28f4ff3524
commit
b54d4018b1
3 changed files with 78 additions and 4 deletions
|
@ -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.
|
||||
|
|
63
gcc/cp/pt.c
63
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;
|
||||
}
|
||||
|
|
13
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C
Normal file
13
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-__func__2.C
Normal file
|
@ -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(); }
|
Loading…
Add table
Reference in a new issue