+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
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).
#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) \
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
{
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;
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
--- /dev/null
+// 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;
+ });
+}