+2019-02-27 Jason Merrill <jason@redhat.com>
+
+ PR c++/86969 - ICE with constexpr if and recursive generic lambdas.
+ * semantics.c (process_outer_var_ref): Do capture dependent vars.
+ * class.c (finish_struct): Only add TAG_DEFN if T is in
+ current_function_decl.
+ * lambda.c (vla_capture_type): Force the capture type out into the
+ lambda's enclosing function.
+ (add_capture): Pass in the lambda.
+ * pt.c (tsubst_lambda_expr): complete_type a VLA capture type.
+
2019-02-27 Marek Polacek <polacek@redhat.com>
PR c++/89511 - ICE with using-declaration and unscoped enumerator.
error ("trying to finish struct, but kicked out due to previous parse errors");
if (processing_template_decl && at_function_scope_p ()
+ && TYPE_CONTEXT (t) == current_function_decl
/* Lambdas are defined by the LAMBDA_EXPR. */
&& !LAMBDA_TYPE_P (t))
add_stmt (build_min (TAG_DEFN, t));
an array of runtime length. */
static tree
-vla_capture_type (tree array_type)
+vla_capture_type (tree array_type, tree lambda)
{
- tree type = xref_tag (record_type, make_anon_name (), ts_current, false);
+ tree closure = LAMBDA_EXPR_CLOSURE (lambda);
+ tree type = make_class_type (RECORD_TYPE);
+ cp_binding_level *slev = current_binding_level;
+ if (closure)
+ {
+ /* If we're already inside the lambda body, force the capture type out
+ into the enclosing context, so we don't crash trying to instantiate
+ the capture field in tsubst_lambda_expr. We won't have a TAG_DEFN
+ from finish_struct in the enclosing context, which we work around in
+ tsubst_lambda_expr. */
+ TYPE_CONTEXT (type) = TYPE_CONTEXT (closure);
+ cp_binding_level *b = current_binding_level;
+ for (;; b = b->level_chain)
+ if (b->this_entity == closure)
+ {
+ while (b->this_entity == closure)
+ b = b->level_chain;
+ break;
+ }
+ current_binding_level = b;
+ }
+ type = pushtag (make_anon_name (), type, ts_current);
+ current_binding_level = slev;
xref_basetypes (type, NULL_TREE);
type = begin_class_definition (type);
if (!ptr_id)
initializer = build_constructor_va (init_list_type_node, 2,
NULL_TREE, build_address (elt),
NULL_TREE, array_type_nelts (type));
- type = vla_capture_type (type);
+ type = vla_capture_type (type, lambda);
}
else if (!dependent_type_p (type)
&& variably_modified_type_p (type, NULL_TREE))
if (PACK_EXPANSION_P (ofield))
ofield = PACK_EXPANSION_PATTERN (ofield);
tree field = tsubst_decl (ofield, args, complain);
+ if (DECL_VLA_CAPTURE_P (ofield))
+ /* The type of a VLA capture might not have a TAG_DEFN in the enclosing
+ context, so complete it here. */
+ complete_type (TREE_TYPE (field));
if (DECL_PACK_P (ofield) && !DECL_NORMAL_CAPTURE_P (ofield))
{
= decl_function_context (containing_function);
}
- /* In a lambda within a template, wait until instantiation
- time to implicitly capture a dependent type. */
+ /* In a lambda within a template, wait until instantiation time to implicitly
+ capture a parameter pack. We want to wait because we don't know if we're
+ capturing the whole pack or a single element, and it's OK to wait because
+ find_parameter_packs_r walks into the lambda body. */
if (context == containing_function
- && dependent_type_p (TREE_TYPE (decl)))
+ && DECL_PACK_P (decl))
return decl;
if (lambda_expr && VAR_P (decl)
--- /dev/null
+// PR c++/86969
+// { dg-do compile { target c++17 } }
+
+auto compose = [](auto... fs) {
+ if constexpr (sizeof...(fs) == 0) {
+ return [](auto x) { return x; };
+ } else {
+ auto fn = [](auto self, auto f, auto... fs) {
+ if constexpr (sizeof...(fs) == 0) return f;
+ else return [=](auto x) {
+ return f(self(self, fs...)(x));
+ };
+ };
+ return fn(fn, fs...);
+ }
+};
+
+static_assert(compose(
+ [](auto x) { return x * 3; },
+ [](auto x) { return x + 1; },
+ [](auto x) { return x / 2; }
+ )(6) == 12);