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

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Even better testcase that has nested COND_EXPRs:
template<typename T> using id = T;
struct S { S () { s++; } ~S () { s--; } S (int) { s++; } static int s; };
int S::s = 0;

void
bar (bool cond, bool cond2)
{
  if (S::s != (cond ? cond2 ? 7 : 5 : cond2 ? 8 : 9))
    __builtin_abort ();
}

void
foo (bool cond, bool cond2)
{
  int i = 1;
  // temporary array has same lifetime as a
  S&& a = id<S[3]>{1, 2, 3}[i];
  // temporary S has same lifetime as b
  const S& b = static_cast<const S&>(0);
  // exactly one of the four temporaries is lifetime-extended
  S&& c = cond ? cond2 ? id<S[3]>{1, 2, 3}[i] : static_cast<S&&>(0)
               : cond2 ? id<S[4]>{1, 2, 3, 4}[i] : id<S[5]>{1, 2, 3, 4, 5}[i];
  bar (cond, cond2);
}

int
main ()
{
  foo (true, true);
  foo (true, false);
  foo (false, true);
  foo (false, false);
}

--- gcc/cp/call.c.jj    2019-12-05 10:03:04.110181312 +0100
+++ gcc/cp/call.c       2019-12-05 20:35:08.386092965 +0100
@@ -12153,12 +12153,19 @@ extend_ref_init_temps_1 (tree decl, tree
         = extend_ref_init_temps_1 (decl, TREE_OPERAND (sub, 1), cleanups);
       return init;
     }
+  if (TREE_CODE (sub) == COND_EXPR)
+    {
+      TREE_OPERAND (sub, 1)
+       = extend_ref_init_temps_1 (decl, TREE_OPERAND (sub, 1), cleanups);
+      TREE_OPERAND (sub, 2)
+       = extend_ref_init_temps_1 (decl, TREE_OPERAND (sub, 2), cleanups);
+      return init;
+    }
   if (TREE_CODE (sub) != ADDR_EXPR)
     return init;
   /* Deal with binding to a subobject.  */
   for (p = &TREE_OPERAND (sub, 0);
-       (TREE_CODE (*p) == COMPONENT_REF
-       || TREE_CODE (*p) == ARRAY_REF); )
+       TREE_CODE (*p) == COMPONENT_REF || TREE_CODE (*p) == ARRAY_REF; )
     p = &TREE_OPERAND (*p, 0);
   if (TREE_CODE (*p) == TARGET_EXPR)
     {
isn't sufficient, because if there are any cleanups added by either of the
recursive calls, we need to conditionalize those cleanups on whether the
particular COND_EXPR's first operand evaluated to true or false.  I think
cp_save_expr won't do it for the nested cases though, because the SAVE_EXPR
might end up not being initialized.  So we need to arrange for a bool temporary
that will be initialized to say false early, before the first COND_EXPR is
encountered, set it to true at the start of corresponding init code and wrap
cleanups with that guard.
Any better ideas?

Reply via email to