On Wed, Mar 04, 2026 at 09:27:01AM +0100, Jakub Jelinek wrote:
> The following testcase is miscompiled, we throw exception only during
> the first bar () call and not during the second and in that case reach
> the inline asm.
> The problem is that the TARGET_EXPR handling calls
>             ctx->global->put_value (new_ctx.object, new_ctx.ctor);
> first for aggregate/vectors, then
>         if (is_complex)
>           /* In case no initialization actually happens, clear out any
>              void_node from a previous evaluation.  */
>           ctx->global->put_value (slot, NULL_TREE);
> and then recurses on TARGET_EXPR_INITIAL.
> If that throws, we keep it as is and return.  If (!is_complex), we
> can in that case keep a value cached for the TARGET_EXPR_SLOT.  For
> *non_constant_p I think that is a non-issue, but for *jump_target
> it can still be a constant expression.
> 
> The following patch fixes it by calling put_value in that case for
> the !is_complex case.

I'm leaning towards calling it regardless of the is_complex value, but
don't have a testcase right now (would need to have say some TARGET_EXPR
with VOID_TYPE TARGET_EXPR_INITIAL which calls a function to initialize
the slot and perhaps stores something into it but then throws).

I've been worrying also about something like:
struct S { int s; };

constexpr S
foo (int x)
{
  return S { x };
}

constexpr int
bar (int x)
{
  return foo (x).s;
}

constexpr bool
baz ()
{
  if (bar (42) != 42)
    throw 1;

  if (bar (43) != 43)
    throw 2;
  return true;
}

static_assert (baz ());
but that works fine - if TARGET_EXPR_INITIAL doesn't throw (and isn't
non-constant), and it is wrapped into a CLEANUP_POINT_EXPR, that
CLEANUP_POINT_EXPR sets ctx->save_expr and TARGET_EXPR handling will
if (ctx->save_expr)
  ctx->save_exprs->safe_push (slot);
and then CLEANUP_POINT_EXPR handling will
        /* Forget SAVE_EXPRs and TARGET_EXPRs created by this
           full-expression.  */
        for (tree save_expr : save_exprs)
          destroy_value_checked (ctx, save_expr, non_constant_p);
Anyway, that means another way to fix this would be to move
        if (ctx->save_exprs)
          ctx->save_exprs->safe_push (slot);
before
        if (*jump_target)
          return NULL_TREE;

        Jakub

Reply via email to