On Wed, Feb 27, 2019 at 4:54 PM Jason Merrill <ja...@redhat.com> wrote:
>
> Immediately capturing a VLA means we need to create a dependent VLA capture
> type, and not in the context of the lambda op(), since trying to look up the
> instantiation of the op() while we're substituting into the capture list
> would crash.  So I force TYPE_CONTEXT and the binding level out to the
> enclosing function before pushtag, avoid adding a TAG_DEFN, and instead
> force the type to be complete in tsubst_lambda_expr.

...or we could delay doing the special VLA handling until its type
becomes non-dependent, which is a lot simpler and less kludgey.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit eb6c46bbc819c27e1730c935248a23e3a6746a9b
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu Feb 28 16:10:12 2019 -0500

            PR c++/86969 - ICE with constexpr if and recursive generic lambdas.
    
            * class.c, lambda.c, pt.c: Revert earlier change.
            * lambda.c (add_capture): Don't special-case capture of dependent
            VLA.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 830ede56af8..f44acfd62b5 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -7246,7 +7246,6 @@ finish_struct (tree t, tree attributes)
     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));
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index c25df2fbc0e..e7f0fda65be 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -479,31 +479,9 @@ static GTY(()) tree max_id;
    an array of runtime length.  */
 
 static tree
-vla_capture_type (tree array_type, tree lambda)
+vla_capture_type (tree array_type)
 {
-  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;
+  tree type = xref_tag (record_type, make_anon_name (), ts_current, false);
   xref_basetypes (type, NULL_TREE);
   type = begin_class_definition (type);
   if (!ptr_id)
@@ -549,7 +527,7 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
   if (type == error_mark_node)
     return error_mark_node;
 
-  if (array_of_runtime_bound_p (type))
+  if (!dependent_type_p (type) && array_of_runtime_bound_p (type))
     {
       vla = true;
       if (!by_reference_p)
@@ -563,7 +541,7 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
       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, lambda);
+      type = vla_capture_type (type);
     }
   else if (!dependent_type_p (type)
 	   && variably_modified_type_p (type, NULL_TREE))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 673ea8e2258..d678e278078 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -17989,10 +17989,6 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       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))
 	{

Reply via email to