PR c++/88752 - ICE with lambda and constexpr if.
In this testcase, we look for an instantiation of the outer lambda from within the inner lambda. enclosing_instantiation_of didn't handle this properly, as it assumed that any references would be from the same lambda nesting depth. Fixed thus. * cp-tree.h (LAMBDA_EXPR_INSTANTIATED): New. * pt.c (tsubst_lambda_expr): Set it. (instantiated_lambda_fn_p): Check it. (enclosing_instantiation_of): Use it. From-SVN: r268424
This commit is contained in:
parent
f942ef18b8
commit
636ecb78a3
4 changed files with 62 additions and 1 deletions
|
@ -1,3 +1,11 @@
|
|||
2019-01-30 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/88752 - ICE with lambda and constexpr if.
|
||||
* cp-tree.h (LAMBDA_EXPR_INSTANTIATED): New.
|
||||
* pt.c (tsubst_lambda_expr): Set it.
|
||||
(instantiated_lambda_fn_p): Check it.
|
||||
(enclosing_instantiation_of): Use it.
|
||||
|
||||
2019-01-31 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR libstdc++/88170
|
||||
|
|
|
@ -453,6 +453,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
|
|||
DECLTYPE_FOR_REF_CAPTURE (in DECLTYPE_TYPE)
|
||||
CONSTRUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR)
|
||||
OVL_NESTED_P (in OVERLOAD)
|
||||
LAMBDA_EXPR_INSTANTIATED (in LAMBDA_EXPR)
|
||||
4: IDENTIFIER_MARKED (IDENTIFIER_NODEs)
|
||||
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
|
||||
CALL_EXPR, or FIELD_DECL).
|
||||
|
@ -1334,6 +1335,10 @@ enum cp_lambda_default_capture_mode_type {
|
|||
#define LAMBDA_EXPR_CAPTURE_OPTIMIZED(NODE) \
|
||||
TREE_LANG_FLAG_2 (LAMBDA_EXPR_CHECK (NODE))
|
||||
|
||||
/* True iff this LAMBDA_EXPR was generated in tsubst_lambda_expr. */
|
||||
#define LAMBDA_EXPR_INSTANTIATED(NODE) \
|
||||
TREE_LANG_FLAG_3 (LAMBDA_EXPR_CHECK (NODE))
|
||||
|
||||
/* True if this TREE_LIST in LAMBDA_EXPR_CAPTURE_LIST is for an explicit
|
||||
capture. */
|
||||
#define LAMBDA_CAPTURE_EXPLICIT_P(NODE) \
|
||||
|
|
22
gcc/cp/pt.c
22
gcc/cp/pt.c
|
@ -13298,6 +13298,19 @@ lambda_fn_in_template_p (tree fn)
|
|||
return CLASSTYPE_TEMPLATE_INFO (closure) != NULL_TREE;
|
||||
}
|
||||
|
||||
/* True if FN is the substitution (via tsubst_lambda_expr) of a function for
|
||||
which the above is true. */
|
||||
|
||||
bool
|
||||
instantiated_lambda_fn_p (tree fn)
|
||||
{
|
||||
if (!fn || !LAMBDA_FUNCTION_P (fn))
|
||||
return false;
|
||||
tree closure = DECL_CONTEXT (fn);
|
||||
tree lam = CLASSTYPE_LAMBDA_EXPR (closure);
|
||||
return LAMBDA_EXPR_INSTANTIATED (lam);
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
@ -13317,13 +13330,19 @@ enclosing_instantiation_of (tree otctx)
|
|||
{
|
||||
tree ofn = fn;
|
||||
int flambda_count = 0;
|
||||
for (; flambda_count < lambda_count && fn && LAMBDA_FUNCTION_P (fn);
|
||||
for (; fn && instantiated_lambda_fn_p (fn);
|
||||
fn = decl_function_context (fn))
|
||||
++flambda_count;
|
||||
if ((fn && DECL_TEMPLATE_INFO (fn))
|
||||
? most_general_template (fn) != most_general_template (tctx)
|
||||
: fn != tctx)
|
||||
continue;
|
||||
if (flambda_count != lambda_count)
|
||||
{
|
||||
gcc_assert (flambda_count > lambda_count);
|
||||
for (; flambda_count > lambda_count; --flambda_count)
|
||||
ofn = decl_function_context (ofn);
|
||||
}
|
||||
gcc_assert (DECL_NAME (ofn) == DECL_NAME (otctx)
|
||||
|| DECL_CONV_FN_P (ofn));
|
||||
return ofn;
|
||||
|
@ -17870,6 +17889,7 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
|||
LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (r)
|
||||
= LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (t);
|
||||
LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);
|
||||
LAMBDA_EXPR_INSTANTIATED (r) = true;
|
||||
|
||||
if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE)
|
||||
/* A lambda in a default argument outside a class gets no
|
||||
|
|
28
gcc/testsuite/g++.dg/cpp1z/constexpr-if26.C
Normal file
28
gcc/testsuite/g++.dg/cpp1z/constexpr-if26.C
Normal file
|
@ -0,0 +1,28 @@
|
|||
// PR c++/88752
|
||||
// { dg-do compile { target c++17 } }
|
||||
|
||||
template <int a> struct b { static constexpr int c = a; };
|
||||
class d;
|
||||
template <typename> struct e { typedef d f; };
|
||||
template <typename g> using h = typename e<g>::f;
|
||||
template <typename> constexpr bool i = b<true>::c;
|
||||
class d {
|
||||
public:
|
||||
using j = float;
|
||||
};
|
||||
template <typename> void k();
|
||||
int main() { k<d>(); }
|
||||
template <class l> l m;
|
||||
template <class, class r> void n(r o) {
|
||||
[](int) {}(o(m<d>));
|
||||
}
|
||||
template <typename> void k() {
|
||||
n<int>([](auto inputs) {
|
||||
auto p(inputs);
|
||||
using s = h<decltype(p)>;
|
||||
s q;
|
||||
if constexpr (i<typename s::j>)
|
||||
[&] { return q; }();
|
||||
return 42;
|
||||
});
|
||||
}
|
Loading…
Add table
Reference in a new issue