https://gcc.gnu.org/g:cb9d160c4dab693a3fc214736db2441ebbee6c35

commit r17-4631-gcb9d160c4dab693a3fc214736db2441ebbee6c35
Author: Jakub Jelinek <[email protected]>
Date:   Thu Sep 24 18:42:28 2026 +0200

    middle-end: Fix up C++26 P2795R5 - Erroneous behavior for uninitialized 
reads [PR126848]
    
    As the following new testcases show, I've messed up the
    C++26 P2795R5 - Erroneous behavior for uninitialized reads
    implementation.  What the paper requires for C++26 and later
    (unless user opts out of it with -ftrivial-auto-var-init=uninitialized,
    which effectively pretends everything that accepts [[indeterminate]]
    attribute has that attribute) is that multiple reads of the same
    uninitialized variable yield the same value (whatever it is) and
    as QoI that such uses are diagnosed with -Wuninitialized
    or -Wmaybe-uninitialized.
    The implementation implemented it as a new mode (not directly requestable
    by users using an option) of -ftrivial-auto-var-init= (the new mode used
    just for the case where -ftrivial-auto-var-init={zero,pattern} isn't used),
    with extra code in the FE to deal with vacuous initialization in switch
    bodies etc. for C++26 and some small changes during gimplification for
    the new AUTO_INIT_CXX26 mode.
    On various testcases it worked fine, but this bugreport shows that
    in the middle-end optimizations we actually need to treat it differently.
    In order to fullfill the C++26 requirements, we can't treat .DEFERRED_INIT
    for C++26 and later as something returning something uninitialized where
    optimizations happily optimize say a PHI with such uninitialized value and
    some other value as that other value, or some passes consider the result
    as UNDEFINED rather than VARYING.
    There is an option to come up with a different internal function for these
    C++26 uses of .DEFERRED_INIT, but because it has also many similarities
    with .DEFERRED_INIT (e.g. same expansion) and because the internal function
    already has an argument which is the flag_trivial_auto_var_init value,
    this patch just changes AUTO_INIT_CXX26 value from 3 to 4 so that it can
    be used as a mask, so now we have 6 different modes:
    AUTO_INIT_UNINITIALIZED (the default for non-C++ or C++ < 26)
    AUTO_INIT_ZERO (-ftrivial-auto-var-init=zero for non-C++ or C++ < 26)
    AUTO_INIT_PATTERN (-ftrivial-auto-var-init=pattern for non-C++ or C++ < 26)
    AUTO_INIT_CXX26 (the default for C++ >= 26)
    AUTO_INIT_ZERO | AUTO_INIT_CXX26 (-ftrivial-auto-var-init=zero for C++ >= 
26)
    AUTO_INIT_PATTERN | AUTO_INIT_CXX26 (-ftrivial-auto-var-init=pattern for 
C++ >= 26)
    The option handling ensures to or in AUTO_INIT_CXX26 for C++26/29 unless
    -ftrivial-auto-var-init=uninitialized is used explicitly, and
    the ccp pass and ssa_undefined_value_p is changed so that it treats the
    AUTO_INIT_CXX26 modes of .DEFERRED_INIT differently (basically as a source
    of VARYING value).  Because the uninit pass uses ssa_undefined_value_p, I
    had to change also has_undefined_value_p because for -Wuninitialized
    purposes we want to treat all .DEFERRED_INIT calls the same.
    
    2026-09-24  Jakub Jelinek  <[email protected]>
    
            PR c++/126848
    gcc/
            * flag-types.h (enum auto_init_type): Change AUTO_INIT_CXX26
            value from 3 to 4.
            * gimplify.cc (gimplify_decl_expr): Mask off AUTO_INIT_CXX26 bit
            before comparing to AUTO_INIT_PATTERN.
            (gimplify_target_expr): Likewise.
            * internal-fn.cc (expand_DEFERRED_INIT): Likewise.  Formatting fix.
            * opts.cc (finish_options): For -fhardened or in AUTO_INIT_CXX26
            bit from previous value if it was set.  Mask off AUTO_INIT_CXX26 bit
            before comparing to AUTO_INIT_ZERO.
            * tree-ssa-ccp.cc (likely_value): Return VARYING rather than 
UNDEFINED
            for .DEFERRED_INIT call with AUTO_INIT_CXX26 bit set in the second
            argument.
            * tree-ssa.cc (ssa_undefined_value_p): Return false rather than true
            for .DEFERRED_INIT call with AUTO_INIT_CXX26 bit set in the second
            argument.
            * tree-ssa-uninit.cc (has_undefined_value_p): Return true for
            SSA_NAMEs with .DEFERRED_INIT call as SSA_NAME_DEF_STMT.
    gcc/c-family/
            * c-opts.cc (c_common_post_options): For 
-ftrivial-auto-var-init=zero
            or -ftrivial-auto-var-init=pattern in C++26 or later mode set
            AUTO_INIT_CXX26 bit in flag_auto_var_init.
    gcc/testsuite/
            * c-c++-common/auto-init-1.c: Use [15] instead of 1 or [26] instead 
of
            2 in regexps matching second .DEFERRED_INIT arguments.
            * c-c++-common/auto-init-2.c: Likewise.
            * c-c++-common/auto-init-3.c: Likewise.
            * c-c++-common/auto-init-4.c: Likewise.
            * c-c++-common/auto-init-5.c: Likewise.
            * c-c++-common/auto-init-6.c: Likewise.
            * c-c++-common/auto-init-7.c: Likewise.
            * c-c++-common/auto-init-8.c: Likewise.
            * c-c++-common/auto-init-9.c: Likewise.
            * c-c++-common/auto-init-10.c: Likewise.
            * c-c++-common/auto-init-11.c: Likewise.
            * c-c++-common/auto-init-12.c: Likewise.
            * c-c++-common/auto-init-13.c: Likewise.
            * c-c++-common/auto-init-14.c: Likewise.
            * c-c++-common/auto-init-15.c: Likewise.
            * c-c++-common/auto-init-16.c: Likewise.
            * c-c++-common/auto-init-esra.c: Likewise.
            * c-c++-common/auto-init-padding-1.c: Likewise.
            * g++.dg/cpp26/erroneous7.C: New test.
            * g++.dg/cpp26/erroneous8.C: New test.
            * g++.dg/cpp26/erroneous9.C: New test.
    
    Reviewed-by: Richard Biener <[email protected]>
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/c-family/c-opts.cc                           |  9 +++++++--
 gcc/flag-types.h                                 |  2 +-
 gcc/gimplify.cc                                  |  4 ++--
 gcc/internal-fn.cc                               | 10 +++++-----
 gcc/opts.cc                                      |  6 ++++--
 gcc/testsuite/c-c++-common/auto-init-1.c         | 20 ++++++++++----------
 gcc/testsuite/c-c++-common/auto-init-10.c        |  2 +-
 gcc/testsuite/c-c++-common/auto-init-11.c        |  2 +-
 gcc/testsuite/c-c++-common/auto-init-12.c        |  2 +-
 gcc/testsuite/c-c++-common/auto-init-13.c        |  4 ++--
 gcc/testsuite/c-c++-common/auto-init-14.c        |  4 ++--
 gcc/testsuite/c-c++-common/auto-init-15.c        |  2 +-
 gcc/testsuite/c-c++-common/auto-init-16.c        |  2 +-
 gcc/testsuite/c-c++-common/auto-init-2.c         | 20 ++++++++++----------
 gcc/testsuite/c-c++-common/auto-init-3.c         |  6 +++---
 gcc/testsuite/c-c++-common/auto-init-4.c         |  6 +++---
 gcc/testsuite/c-c++-common/auto-init-5.c         |  6 +++---
 gcc/testsuite/c-c++-common/auto-init-6.c         |  6 +++---
 gcc/testsuite/c-c++-common/auto-init-7.c         |  8 ++++----
 gcc/testsuite/c-c++-common/auto-init-8.c         |  8 ++++----
 gcc/testsuite/c-c++-common/auto-init-9.c         |  4 ++--
 gcc/testsuite/c-c++-common/auto-init-esra.c      |  4 ++--
 gcc/testsuite/c-c++-common/auto-init-padding-1.c |  2 +-
 gcc/testsuite/g++.dg/cpp26/erroneous7.C          | 20 ++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp26/erroneous8.C          | 19 +++++++++++++++++++
 gcc/testsuite/g++.dg/cpp26/erroneous9.C          | 19 +++++++++++++++++++
 gcc/tree-ssa-ccp.cc                              | 11 +++++++++--
 gcc/tree-ssa-uninit.cc                           |  1 +
 gcc/tree-ssa.cc                                  | 10 ++++++++--
 29 files changed, 149 insertions(+), 70 deletions(-)

diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index 0e2d8bdcfdd7..d27cf3fa6d5f 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -925,8 +925,13 @@ c_common_post_options (const char **pfilename)
     flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_C11;
 
   if (cxx_dialect >= cxx26)
-    SET_OPTION_IF_UNSET (&global_options, &global_options_set,
-                        flag_auto_var_init, AUTO_INIT_CXX26);
+    {
+      SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+                          flag_auto_var_init, AUTO_INIT_CXX26);
+      if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED)
+       flag_auto_var_init
+         = auto_init_type (flag_auto_var_init | AUTO_INIT_CXX26);
+    }
 
   /* The -Wtrivial-auto-var-init warning is useless for C++, where we always
      add .DEFERRED_INIT calls when some (vacuous) initializers are bypassed
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index df983d9d947f..e14dd36707a6 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -289,7 +289,7 @@ enum auto_init_type {
   AUTO_INIT_UNINITIALIZED = 0,
   AUTO_INIT_PATTERN = 1,
   AUTO_INIT_ZERO = 2,
-  AUTO_INIT_CXX26 = 3
+  AUTO_INIT_CXX26 = 4
 };
 
 /* Initialization of padding bits with zeros.  */
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 0f8bf533ba75..19cabec33a81 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -2113,7 +2113,7 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
             since __builtin_clear_padding will take the address of the
             variable.  As a result, if a long double/_Complex long double
             variable will spilled into stack later, its padding is 0XFE.  */
-         if (flag_auto_var_init == AUTO_INIT_PATTERN
+         if ((flag_auto_var_init & ~AUTO_INIT_CXX26) == AUTO_INIT_PATTERN
              && !is_gimple_reg (decl)
              && clear_padding_type_may_have_padding_p (TREE_TYPE (decl)))
            gimple_add_padding_init_for_auto_var (decl, is_vla, seq_p);
@@ -8478,7 +8478,7 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, 
gimple_seq *post_p)
       if (var_needs_auto_init_p (temp) && VOID_TYPE_P (TREE_TYPE (init)))
        {
          gimple_add_init_for_auto_var (temp, flag_auto_var_init, &init_pre_p);
-         if (flag_auto_var_init == AUTO_INIT_PATTERN
+         if ((flag_auto_var_init & ~AUTO_INIT_CXX26) == AUTO_INIT_PATTERN
              && !is_gimple_reg (temp)
              && clear_padding_type_may_have_padding_p (TREE_TYPE (temp)))
            gimple_add_padding_init_for_auto_var (temp, is_vla, &init_pre_p);
diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
index 9bfca87588b3..597ccaeb9fef 100644
--- a/gcc/internal-fn.cc
+++ b/gcc/internal-fn.cc
@@ -3527,7 +3527,7 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
       mark_addressable (lhs);
       tree var_addr = build_fold_addr_expr (lhs);
 
-      tree value = (init_type == AUTO_INIT_PATTERN)
+      tree value = ((init_type & ~AUTO_INIT_CXX26) == AUTO_INIT_PATTERN)
                    ? build_int_cst (integer_type_node,
                                     INIT_PATTERN_VALUE)
                    : integer_zero_node;
@@ -3544,7 +3544,7 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
       scalar_int_mode var_mode;
       if (TREE_CODE (TREE_TYPE (lhs)) != BOOLEAN_TYPE
          && tree_fits_uhwi_p (var_size)
-         && (init_type == AUTO_INIT_PATTERN
+         && ((init_type & ~AUTO_INIT_CXX26) == AUTO_INIT_PATTERN
              || !is_gimple_reg_type (var_type))
          && int_mode_for_size (tree_to_uhwi (var_size) * BITS_PER_UNIT,
                                0).exists (&var_mode)
@@ -3552,10 +3552,10 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
        {
          unsigned HOST_WIDE_INT total_bytes = tree_to_uhwi (var_size);
          unsigned char *buf = XALLOCAVEC (unsigned char, total_bytes);
-         memset (buf, (init_type == AUTO_INIT_PATTERN
+         memset (buf, ((init_type & ~AUTO_INIT_CXX26) == AUTO_INIT_PATTERN
                        ? INIT_PATTERN_VALUE : 0), total_bytes);
-         tree itype = build_nonstandard_integer_type
-                        (total_bytes * BITS_PER_UNIT, 1);
+         tree itype
+           = build_nonstandard_integer_type (total_bytes * BITS_PER_UNIT, 1);
          wide_int w = wi::from_buffer (buf, total_bytes);
          init = wide_int_to_tree (itype, w);
          /* Pun the LHS to make sure its type has constant size
diff --git a/gcc/opts.cc b/gcc/opts.cc
index 8048264b6099..21a773f8da75 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -1164,8 +1164,10 @@ finish_options (struct gcc_options *opts, struct 
gcc_options *opts_set,
   if (opts->x_flag_hardened)
     {
       if (!opts_set->x_flag_auto_var_init)
-       opts->x_flag_auto_var_init = AUTO_INIT_ZERO;
-      else if (opts->x_flag_auto_var_init != AUTO_INIT_ZERO)
+       opts->x_flag_auto_var_init
+         = auto_init_type (opts->x_flag_auto_var_init | AUTO_INIT_ZERO);
+      else if ((opts->x_flag_auto_var_init & ~AUTO_INIT_CXX26)
+              != AUTO_INIT_ZERO)
        warning_at (loc, OPT_Whardened,
                    "%<-ftrivial-auto-var-init=zero%> is not enabled by "
                    "%<-fhardened%> because it was specified on the command "
diff --git a/gcc/testsuite/c-c++-common/auto-init-1.c 
b/gcc/testsuite/c-c++-common/auto-init-1.c
index 3e6a4984eea2..96dd4be32a8d 100644
--- a/gcc/testsuite/c-c++-common/auto-init-1.c
+++ b/gcc/testsuite/c-c++-common/auto-init-1.c
@@ -29,13 +29,13 @@ void foo()
   return;
 }
 
-/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(1, 2, \&\"temp1\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(2, 2, \&\"temp2\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(4, 2, \&\"temp3\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(4, 2, \&\"temp4\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(4, 2, \&\"temp5\"" 
"gimple" { target ilp32 } } } */
-/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(8, 2, \&\"temp5\"" 
"gimple" { target lp64 } } } */
-/* { dg-final { scan-tree-dump "temp6 = .DEFERRED_INIT \\(8, 2, \&\"temp6\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(4, 2, \&\"temp7\"" 
"gimple" { target ilp32 } } } */
-/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(8, 2, \&\"temp7\"" 
"gimple" { target lp64 } } } */
-/* { dg-final { scan-tree-dump "temp8 = .DEFERRED_INIT \\(1, 2, \&\"temp8\"" 
"gimple" } } */
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(1, \[26], 
\&\"temp1\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(2, \[26], 
\&\"temp2\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(4, \[26], 
\&\"temp3\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(4, \[26], 
\&\"temp4\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(4, \[26], 
\&\"temp5\"" "gimple" { target ilp32 } } } */
+/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(8, \[26], 
\&\"temp5\"" "gimple" { target lp64 } } } */
+/* { dg-final { scan-tree-dump "temp6 = .DEFERRED_INIT \\(8, \[26], 
\&\"temp6\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(4, \[26], 
\&\"temp7\"" "gimple" { target ilp32 } } } */
+/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(8, \[26], 
\&\"temp7\"" "gimple" { target lp64 } } } */
+/* { dg-final { scan-tree-dump "temp8 = .DEFERRED_INIT \\(1, \[26], 
\&\"temp8\"" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-10.c 
b/gcc/testsuite/c-c++-common/auto-init-10.c
index dda7ea1e0324..4ec0a2594070 100644
--- a/gcc/testsuite/c-c++-common/auto-init-10.c
+++ b/gcc/testsuite/c-c++-common/auto-init-10.c
@@ -18,5 +18,5 @@ void foo()
   return;
 }
 
-/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(2, 1, \&\"temp1\"" 
"gimple" } } */
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(2, \[15], 
\&\"temp1\"" "gimple" } } */
 /* { dg-final { scan-tree-dump-not "temp2 = .DEFERRED_INIT \\(" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-11.c 
b/gcc/testsuite/c-c++-common/auto-init-11.c
index 6eb468785ce1..2114474e68aa 100644
--- a/gcc/testsuite/c-c++-common/auto-init-11.c
+++ b/gcc/testsuite/c-c++-common/auto-init-11.c
@@ -11,4 +11,4 @@ void foo(int n)
   return;
 }
 
-/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, 2, \&\"arr\"" 
"gimple" } } */
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, \[26], \&\"arr\"" 
"gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-12.c 
b/gcc/testsuite/c-c++-common/auto-init-12.c
index 964291c5bd94..4eb0f6e50764 100644
--- a/gcc/testsuite/c-c++-common/auto-init-12.c
+++ b/gcc/testsuite/c-c++-common/auto-init-12.c
@@ -11,4 +11,4 @@ void foo(int n)
   return;
 }
 
-/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, 1, \&\"arr\"" 
"gimple" } } */
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, \[15], \&\"arr\"" 
"gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-13.c 
b/gcc/testsuite/c-c++-common/auto-init-13.c
index aa5883af770f..b53b2b98e877 100644
--- a/gcc/testsuite/c-c++-common/auto-init-13.c
+++ b/gcc/testsuite/c-c++-common/auto-init-13.c
@@ -19,5 +19,5 @@ int foo()
   return d.b + var.bar.b;
 }
 
-/* { dg-final { scan-tree-dump "d = .DEFERRED_INIT \\(4, 1, \&\"d\"" "gimple" 
} } */
-/* { dg-final { scan-tree-dump "var = .DEFERRED_INIT \\(4, 1, \&\"var\"" 
"gimple" } } */
+/* { dg-final { scan-tree-dump "d = .DEFERRED_INIT \\(4, \[15], \&\"d\"" 
"gimple" } } */
+/* { dg-final { scan-tree-dump "var = .DEFERRED_INIT \\(4, \[15], \&\"var\"" 
"gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-14.c 
b/gcc/testsuite/c-c++-common/auto-init-14.c
index dd1ff3e339d2..90fd57a537f4 100644
--- a/gcc/testsuite/c-c++-common/auto-init-14.c
+++ b/gcc/testsuite/c-c++-common/auto-init-14.c
@@ -19,5 +19,5 @@ int foo()
   return d.b + var.bar.b;
 }
 
-/* { dg-final { scan-tree-dump "d = .DEFERRED_INIT \\(4, 2, \&\"d\"" "gimple" 
} } */
-/* { dg-final { scan-tree-dump "var = .DEFERRED_INIT \\(4, 2, \&\"var\"" 
"gimple" } } */
+/* { dg-final { scan-tree-dump "d = .DEFERRED_INIT \\(4, \[26], \&\"d\"" 
"gimple" } } */
+/* { dg-final { scan-tree-dump "var = .DEFERRED_INIT \\(4, \[26], \&\"var\"" 
"gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-15.c 
b/gcc/testsuite/c-c++-common/auto-init-15.c
index 5857287ecbef..f389b5aa544f 100644
--- a/gcc/testsuite/c-c++-common/auto-init-15.c
+++ b/gcc/testsuite/c-c++-common/auto-init-15.c
@@ -10,4 +10,4 @@ void foo(int a)
   g(x);
 }
 
-/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, 2, \&\"x\"" "gimple" 
} } */
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, \[26], \&\"x\"" 
"gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-16.c 
b/gcc/testsuite/c-c++-common/auto-init-16.c
index 1e309959fc5c..b6cc7506c3c2 100644
--- a/gcc/testsuite/c-c++-common/auto-init-16.c
+++ b/gcc/testsuite/c-c++-common/auto-init-16.c
@@ -10,4 +10,4 @@ void foo(int a)
   g(x);
 }
 
-/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, 1, \&\"x\"" "gimple" 
} } */
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(D.\\d*, \[15], \&\"x\"" 
"gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-2.c 
b/gcc/testsuite/c-c++-common/auto-init-2.c
index d356e508b836..a1f66358e6e2 100644
--- a/gcc/testsuite/c-c++-common/auto-init-2.c
+++ b/gcc/testsuite/c-c++-common/auto-init-2.c
@@ -29,13 +29,13 @@ void foo()
   return;
 }
 
-/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(1, 1, \&\"temp1\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(2, 1, \&\"temp2\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(4, 1, \&\"temp3\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(4, 1, \&\"temp4\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(4, 1, \&\"temp5\"" 
"gimple" { target ilp32 } } } */
-/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(8, 1, \&\"temp5\"" 
"gimple" { target lp64 } } } */
-/* { dg-final { scan-tree-dump "temp6 = .DEFERRED_INIT \\(8, 1, \&\"temp6\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(4, 1, \&\"temp7\"" 
"gimple" { target ilp32 } } } */
-/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(8, 1, \&\"temp7\"" 
"gimple" { target lp64 } } } */
-/* { dg-final { scan-tree-dump "temp8 = .DEFERRED_INIT \\(1, 1, \&\"temp8\"" 
"gimple" } } */
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(1, \[15], 
\&\"temp1\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(2, \[15], 
\&\"temp2\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(4, \[15], 
\&\"temp3\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\(4, \[15], 
\&\"temp4\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(4, \[15], 
\&\"temp5\"" "gimple" { target ilp32 } } } */
+/* { dg-final { scan-tree-dump "temp5 = .DEFERRED_INIT \\(8, \[15], 
\&\"temp5\"" "gimple" { target lp64 } } } */
+/* { dg-final { scan-tree-dump "temp6 = .DEFERRED_INIT \\(8, \[15], 
\&\"temp6\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(4, \[15], 
\&\"temp7\"" "gimple" { target ilp32 } } } */
+/* { dg-final { scan-tree-dump "temp7 = .DEFERRED_INIT \\(8, \[15], 
\&\"temp7\"" "gimple" { target lp64 } } } */
+/* { dg-final { scan-tree-dump "temp8 = .DEFERRED_INIT \\(1, \[15], 
\&\"temp8\"" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-3.c 
b/gcc/testsuite/c-c++-common/auto-init-3.c
index 9d9c86d8dd08..c2e310f23643 100644
--- a/gcc/testsuite/c-c++-common/auto-init-3.c
+++ b/gcc/testsuite/c-c++-common/auto-init-3.c
@@ -14,6 +14,6 @@ long double foo()
   return result;
 }
 
-/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(4, 2, \&\"temp1\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(8, 2, \&\"temp2\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\((8|12|16), 2, 
\&\"temp3\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(4, \[26], 
\&\"temp1\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(8, \[26], 
\&\"temp2\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\((8|12|16), \[26], 
\&\"temp3\"" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-4.c 
b/gcc/testsuite/c-c++-common/auto-init-4.c
index 848df2a0e264..cff11ef3e167 100644
--- a/gcc/testsuite/c-c++-common/auto-init-4.c
+++ b/gcc/testsuite/c-c++-common/auto-init-4.c
@@ -14,6 +14,6 @@ long double foo()
   return result;
 }
 
-/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(4, 1, \&\"temp1\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(8, 1, \&\"temp2\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\((8|12|16), 1, 
\&\"temp3\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(4, \[15], 
\&\"temp1\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(8, \[15], 
\&\"temp2\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\((8|12|16), \[15], 
\&\"temp3\"" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-5.c 
b/gcc/testsuite/c-c++-common/auto-init-5.c
index 9c4de6121826..1be200c4428e 100644
--- a/gcc/testsuite/c-c++-common/auto-init-5.c
+++ b/gcc/testsuite/c-c++-common/auto-init-5.c
@@ -15,7 +15,7 @@ _Complex long double foo()
   return result;
 }
 
-/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(8, 2, \&\"temp1\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(16, 2, \&\"temp2\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\((16|24|32), 2, 
\&\"temp3\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(8, \[26], 
\&\"temp1\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(16, \[26], 
\&\"temp2\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\((16|24|32), \[26], 
\&\"temp3\"" "gimple" } } */
 
diff --git a/gcc/testsuite/c-c++-common/auto-init-6.c 
b/gcc/testsuite/c-c++-common/auto-init-6.c
index 6a406447f3d9..8f09007c358a 100644
--- a/gcc/testsuite/c-c++-common/auto-init-6.c
+++ b/gcc/testsuite/c-c++-common/auto-init-6.c
@@ -15,7 +15,7 @@ _Complex long double foo()
   return result;
 }
 
-/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(8, 1, \&\"temp1\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(16, 1, \&\"temp2\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\((16|24|32), 1, 
\&\"temp3\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(8, \[15], 
\&\"temp1\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(16, \[15], 
\&\"temp2\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\((16|24|32), \[15], 
\&\"temp3\"" "gimple" } } */
 
diff --git a/gcc/testsuite/c-c++-common/auto-init-7.c 
b/gcc/testsuite/c-c++-common/auto-init-7.c
index dd48d691596f..346676304016 100644
--- a/gcc/testsuite/c-c++-common/auto-init-7.c
+++ b/gcc/testsuite/c-c++-common/auto-init-7.c
@@ -29,7 +29,7 @@ double foo()
   return result;
 }
 
-/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(12, 2, \&\"temp1\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(24, 2, \&\"temp2\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(28, 2, \&\"temp3\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\((8|5), 2, 
\&\"temp4\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(12, \[26], 
\&\"temp1\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(24, \[26], 
\&\"temp2\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(28, \[26], 
\&\"temp3\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\((8|5), \[26], 
\&\"temp4\"" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-8.c 
b/gcc/testsuite/c-c++-common/auto-init-8.c
index 863f2ba87d7d..93d37ee6c9ca 100644
--- a/gcc/testsuite/c-c++-common/auto-init-8.c
+++ b/gcc/testsuite/c-c++-common/auto-init-8.c
@@ -29,7 +29,7 @@ double foo()
   return result;
 }
 
-/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(12, 1, \&\"temp1\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(24, 1, \&\"temp2\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(28, 1, \&\"temp3\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\((8|5), 1, 
\&\"temp4\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(12, \[15], 
\&\"temp1\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp2 = .DEFERRED_INIT \\(24, \[15], 
\&\"temp2\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp3 = .DEFERRED_INIT \\(28, \[15], 
\&\"temp3\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp4 = .DEFERRED_INIT \\((8|5), \[15], 
\&\"temp4\"" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-9.c 
b/gcc/testsuite/c-c++-common/auto-init-9.c
index 113107ffd5c0..66204285616c 100644
--- a/gcc/testsuite/c-c++-common/auto-init-9.c
+++ b/gcc/testsuite/c-c++-common/auto-init-9.c
@@ -16,5 +16,5 @@ void foo()
   return;
 }
 
-/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(2, 2, \&\"temp1\"" 
"gimple" } } */
-/* { dg-final { scan-tree-dump-not "temp2 = .DEFERRED_INIT \\(8, 2, 
\&\"temp2\"" "gimple" } } */
+/* { dg-final { scan-tree-dump "temp1 = .DEFERRED_INIT \\(2, \[26], 
\&\"temp1\"" "gimple" } } */
+/* { dg-final { scan-tree-dump-not "temp2 = .DEFERRED_INIT \\(8, \[26], 
\&\"temp2\"" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-esra.c 
b/gcc/testsuite/c-c++-common/auto-init-esra.c
index ce6779f20fcd..3471a21aa808 100644
--- a/gcc/testsuite/c-c++-common/auto-init-esra.c
+++ b/gcc/testsuite/c-c++-common/auto-init-esra.c
@@ -31,5 +31,5 @@ void VCross(VECTOR a, const VECTOR b, const VECTOR c)
  Assign_Vector(a, tmp);
 }
 
-/* { dg-final { scan-tree-dump-times "tmp = .DEFERRED_INIT \\(24, 2, 
\&\"tmp\"" 1 "gimple" } } */
-/* { dg-final { scan-tree-dump-times ".DEFERRED_INIT \\(8, 2, \&\"tmp\"" 3 
"esra" } } */
+/* { dg-final { scan-tree-dump-times "tmp = .DEFERRED_INIT \\(24, \[26], 
\&\"tmp\"" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times ".DEFERRED_INIT \\(8, \[26], \&\"tmp\"" 3 
"esra" } } */
diff --git a/gcc/testsuite/c-c++-common/auto-init-padding-1.c 
b/gcc/testsuite/c-c++-common/auto-init-padding-1.c
index d2e322717f0e..dddff37a68bf 100644
--- a/gcc/testsuite/c-c++-common/auto-init-padding-1.c
+++ b/gcc/testsuite/c-c++-common/auto-init-padding-1.c
@@ -19,5 +19,5 @@ void foo(int a)
   g(s);
 }
 
-/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(24, 1, \&\"s\"" "gimple" } } 
*/
+/* { dg-final { scan-tree-dump ".DEFERRED_INIT \\(24, \[15], \&\"s\"" "gimple" 
} } */
 /* { dg-final { scan-tree-dump "__builtin_clear_padding" "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/cpp26/erroneous7.C 
b/gcc/testsuite/g++.dg/cpp26/erroneous7.C
new file mode 100644
index 000000000000..b68b3952768c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/erroneous7.C
@@ -0,0 +1,20 @@
+// PR c++/126848
+// { dg-do run { target c++26 } }
+// { dg-skip-if "" { *-*-* } { "-ftrivial-auto-var-init=*" } { "" } }
+// { dg-options "-O2 -Wuninitialized" }
+
+[[gnu::noipa]]
+int
+foo (int x)
+{
+  int a;
+  int b = x ? a : 1;
+  return b - a;                // { dg-warning "'a' is used uninitialized" }
+}
+
+int
+main ()
+{
+  if (foo (1) != 0)
+    __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/erroneous8.C 
b/gcc/testsuite/g++.dg/cpp26/erroneous8.C
new file mode 100644
index 000000000000..8cc6ccada5b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/erroneous8.C
@@ -0,0 +1,19 @@
+// PR c++/126848
+// { dg-do run { target c++26 } }
+// { dg-options "-O2 -ftrivial-auto-var-init=zero -Wuninitialized" }
+
+[[gnu::noipa]]
+int
+foo (int x)
+{
+  int a;
+  int b = x ? a : 1;
+  return b - a;                // { dg-warning "'a' is used uninitialized" }
+}
+
+int
+main ()
+{
+  if (foo (1) != 0)
+    __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/erroneous9.C 
b/gcc/testsuite/g++.dg/cpp26/erroneous9.C
new file mode 100644
index 000000000000..2f95fadd99a7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/erroneous9.C
@@ -0,0 +1,19 @@
+// PR c++/126848
+// { dg-do run { target c++26 } }
+// { dg-options "-O2 -ftrivial-auto-var-init=pattern -Wuninitialized" }
+
+[[gnu::noipa]]
+int
+foo (int x)
+{
+  int a;
+  int b = x ? a : 1;
+  return b - a;                // { dg-warning "'a' is used uninitialized" }
+}
+
+int
+main ()
+{
+  if (foo (1) != 0)
+    __builtin_abort ();
+}
diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc
index cc1da6540e34..9930d78956fe 100644
--- a/gcc/tree-ssa-ccp.cc
+++ b/gcc/tree-ssa-ccp.cc
@@ -727,9 +727,16 @@ likely_value (gimple *stmt)
   if (gimple_has_volatile_ops (stmt))
     return VARYING;
 
-  /* .DEFERRED_INIT produces undefined.  */
+  /* .DEFERRED_INIT produces undefined except for AUTO_INIT_CXX26
+     which produces varying because it is undefined that needs to have
+     the same value in all uses.  */
   if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
-    return UNDEFINED;
+    {
+      if (tree_to_uhwi (gimple_call_arg (stmt, 1)) & AUTO_INIT_CXX26)
+       return VARYING;
+      else
+       return UNDEFINED;
+    }
 
   /* Arrive here for more complex cases.  */
   has_constant_operand = false;
diff --git a/gcc/tree-ssa-uninit.cc b/gcc/tree-ssa-uninit.cc
index 1072e1e270bb..7d242ab7530a 100644
--- a/gcc/tree-ssa-uninit.cc
+++ b/gcc/tree-ssa-uninit.cc
@@ -81,6 +81,7 @@ static bool
 has_undefined_value_p (tree t)
 {
   return (ssa_undefined_value_p (t)
+         || gimple_call_internal_p (SSA_NAME_DEF_STMT (t), IFN_DEFERRED_INIT)
          || (possibly_undefined_names
              && possibly_undefined_names->contains (t)));
 }
diff --git a/gcc/tree-ssa.cc b/gcc/tree-ssa.cc
index 5248c0903d45..4f94edb2f4b5 100644
--- a/gcc/tree-ssa.cc
+++ b/gcc/tree-ssa.cc
@@ -1348,9 +1348,15 @@ ssa_undefined_value_p (tree t, bool partial)
     return true;
 
   /* The value is undefined if the definition statement is a call
-     to .DEFERRED_INIT function.  */
+     to .DEFERRED_INIT function.  Except for AUTO_INIT_CXX26 which is
+     undefined but needs to have the same value in all uses.  */
   if (gimple_call_internal_p (def_stmt, IFN_DEFERRED_INIT))
-    return true;
+    {
+      if (tree_to_uhwi (gimple_call_arg (def_stmt, 1)) & AUTO_INIT_CXX26)
+       return false;
+      else
+       return true;
+    }
 
   /* The value is partially undefined if the definition statement is
      a REALPART_EXPR or IMAGPART_EXPR and its operand is defined by

Reply via email to