PR c++/86740, ICE with constexpr if and nested generic lambdas.

When we partially instantiate the constexpr if, we walk through its body to
see what it uses from the enclosing local_specializations.  That walk was
overlooking the use of 'count' in the captures of the innermost lambda,
because we weren't walking into the capture list.

	* tree.c (cp_walk_subtrees): Handle LAMBDA_EXPR.

From-SVN: r268046
This commit is contained in:
Jason Merrill 2019-01-17 15:36:31 -05:00 committed by Jason Merrill
parent ba29ed0f57
commit f18aa3a407
3 changed files with 40 additions and 0 deletions

View File

@ -1,3 +1,8 @@
2019-01-17 Jason Merrill <jason@redhat.com>
PR c++/86740, ICE with constexpr if and nested generic lambdas.
* tree.c (cp_walk_subtrees): Handle LAMBDA_EXPR.
2019-01-17 Paolo Carlini <paolo.carlini@oracle.com> 2019-01-17 Paolo Carlini <paolo.carlini@oracle.com>
* decl.c (grokdeclarator): Use typespec_loc in error messages * decl.c (grokdeclarator): Use typespec_loc in error messages

View File

@ -4933,6 +4933,14 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
} }
break; break;
case LAMBDA_EXPR:
/* Don't walk into the body of the lambda, but the capture initializers
are part of the enclosing context. */
for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (*tp); cap;
cap = TREE_CHAIN (cap))
WALK_SUBTREE (TREE_VALUE (cap));
break;
default: default:
return NULL_TREE; return NULL_TREE;
} }

View File

@ -0,0 +1,27 @@
// PR c++/86740
// { dg-do compile { target c++17 } }
struct Constant
{
static constexpr int value = 0;
};
template<typename F>
void invokeWithConstant(F &&f)
{
f(Constant{});
}
int foo()
{
int count = 0;
invokeWithConstant
([&] (auto id1)
{
invokeWithConstant
([&] (auto id2)
{
if constexpr (id1.value == 0 && id2.value == 0)
[&] { count = 1; } ();
});
});
return count;
}