https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123597

--- Comment #13 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
The bug is in all the BIND_EXPR optimizations that commit added.
I mean
  /* Remove redundant BIND_EXPRs with no bindings even when not specifically
     trying to flatten.  */
  else if (TREE_CODE (*tp) == BIND_EXPR
           && BIND_EXPR_BODY (*tp) == sit->orig
           && !BIND_EXPR_VARS (*tp)
           && (sit->flatten || TREE_CODE (sit->repl) == BIND_EXPR))
and
  else if (sit->flatten
           && TREE_CODE (*tp) == BIND_EXPR
           && TREE_CODE (sit->repl) == BIND_EXPR)
in substitute_in_tree_walker and
  if (TREE_CODE (repl) == BIND_EXPR && !BIND_EXPR_VARS (repl))
    repl = BIND_EXPR_BODY (repl);
in substitute_in_tree.

BIND_EXPRs in the FE are usually created by do_poplevel:
  if (!processing_template_decl)
    {
      stmt_list = c_build_bind_expr (input_location, block, stmt_list);
      /* ??? See c_end_compound_stmt re statement expressions.  */
    }
and by poplevel:
      /* If this is a temporary binding created for a cleanup, then we'll
         have pushed a statement list level.  Pop that, create a new
         BIND_EXPR for the block, and insert it into the stream.  */
      stmt = pop_stmt_list (current_binding_level->statement_list);
      stmt = c_build_bind_expr (input_location, block, stmt);
where c_build_bind_expr doesn't always force a BIND_EXPR, but creates it only
when
needed:
  if (decls || block)
    {
      bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
      TREE_SIDE_EFFECTS (bind) = 1;
      SET_EXPR_LOCATION (bind, loc);
    }
  else
    bind = body;
In do_poplevel it is clearly never called for processing_template_decl and in
poplevel
I think it isn't either, because maybe_push_cleanup_level I think is never
called for processing_template_decl, so there are no sk_cleanup scopes.
And then there is in begin_compound_stmt
  /* When processing a template, we need to remember where the braces were,
     so that we can set up identical scopes when instantiating the template
     later.  BIND_EXPR is a handy candidate for this.
     Note that do_poplevel won't create a BIND_EXPR itself here (and thus
     result in nested BIND_EXPRs), since we don't build BLOCK nodes when
     processing templates.  */
  if (processing_template_decl)
    {
      r = build3 (BIND_EXPR, NULL, NULL, r, NULL);
      BIND_EXPR_TRY_BLOCK (r) = (flags & BCS_TRY_BLOCK) != 0;
      BIND_EXPR_BODY_BLOCK (r) = (flags & BCS_FN_BODY) != 0;
      TREE_SIDE_EFFECTS (r) = 1;
    }
So, BIND_EXPRs are created in templates for a different reason to
non-templates, and
BIND_EXPRs in templates will I think always have BIND_EXPR_VARS NULL.

Reply via email to