--- gcc/gimplify.cc.jj 2025-08-06 10:41:32.359075693 +0200
+++ gcc/gimplify.cc 2025-09-04 15:56:12.569285030 +0200
@@ -2102,13 +2102,13 @@ gimple_add_padding_init_for_auto_var (tr
/* Return true if the DECL need to be automaticly initialized by the
compiler. */
static bool
-is_var_need_auto_init (tree decl)
+var_needs_auto_init_p (tree decl)
{
if (auto_var_p (decl)
- && (TREE_CODE (decl) != VAR_DECL
- || !DECL_HARD_REGISTER (decl))
- && (flag_auto_var_init > AUTO_INIT_UNINITIALIZED)
- && (!lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl)))
+ && (TREE_CODE (decl) != VAR_DECL || !DECL_HARD_REGISTER (decl))
+ && flag_auto_var_init > AUTO_INIT_UNINITIALIZED
+ && !lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl))
+ && !lookup_attribute ("indeterminate", DECL_ATTRIBUTES (decl))
&& !OPAQUE_TYPE_P (TREE_TYPE (decl))
&& !is_empty_type (TREE_TYPE (decl)))
return true;
@@ -2221,7 +2221,7 @@ gimplify_decl_expr (tree *stmt_p, gimple
/* When there is no explicit initializer, if the user requested,
We should insert an artifical initializer for this automatic
variable. */
- else if (is_var_need_auto_init (decl)
+ else if (var_needs_auto_init_p (decl)
&& !decl_had_value_expr_p)
{
gimple_add_init_for_auto_var (decl,
@@ -2315,14 +2315,14 @@ emit_warn_switch_unreachable (gimple *st
/* Don't warn for compiler-generated gotos. These occur
in Duff's devices, for example. */
return NULL;
- else if ((flag_auto_var_init > AUTO_INIT_UNINITIALIZED)
- && ((gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
- || (gimple_call_builtin_p (stmt, BUILT_IN_CLEAR_PADDING)
- && (bool) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1)))
- || (is_gimple_assign (stmt)
- && gimple_assign_single_p (stmt)
- && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
- && gimple_call_internal_p (
+ else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
+ && (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT)
+ || (gimple_call_builtin_p (stmt, BUILT_IN_CLEAR_PADDING)
+ && (bool) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1)))
+ || (is_gimple_assign (stmt)
+ && gimple_assign_single_p (stmt)
+ && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
+ && gimple_call_internal_p (
SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt)),
IFN_DEFERRED_INIT))))
/* Don't warn for compiler-generated initializations for
@@ -6753,7 +6753,8 @@ gimplify_init_constructor (tree *expr_p,
&& clear_padding_type_may_have_padding_p (type)
&& ((AGGREGATE_TYPE_P (type) && !cleared && !is_empty_ctor)
|| !AGGREGATE_TYPE_P (type))
- && is_var_need_auto_init (object))
+ && var_needs_auto_init_p (object)
+ && flag_auto_var_init != AUTO_INIT_CXX26)
gimple_add_padding_init_for_auto_var (object, false, pre_p);
return ret;
--- gcc/cp/tree.cc.jj 2025-09-04 10:36:30.478109748 +0200
+++ gcc/cp/tree.cc 2025-09-04 13:31:35.535889253 +0200
@@ -5578,6 +5578,23 @@ handle_maybe_unused_attribute (tree *nod
return ret;
}
+/* The C++26 [[indeterminate]] attribute. */
+
+static tree
+handle_indeterminate_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != PARM_DECL
+ && (!VAR_P (*node) || is_global_var (*node)))
+ {
+ pedwarn (input_location, OPT_Wattributes,
+ "%qE on declaration other than parameter or automatic variable",
+ name);
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+}
+
/* Table of valid C++ attributes. */
static const attribute_spec cxx_gnu_attributes[] =
{
@@ -5617,6 +5634,8 @@ static const attribute_spec std_attribut
handle_noreturn_attribute, attr_noreturn_exclusions },
{ "carries_dependency", 0, 0, true, false, false, false,
handle_carries_dependency_attribute, NULL },
+ { "indeterminate", 0, 0, true, false, false, false,
+ handle_indeterminate_attribute, NULL },
{ "pre", 0, -1, false, false, false, false,
handle_contract_attribute, NULL },
{ "post", 0, -1, false, false, false, false,
--- gcc/cp/decl.cc.jj 2025-09-04 10:36:30.295112184 +0200
+++ gcc/cp/decl.cc 2025-09-04 12:09:27.487617358 +0200
@@ -19313,7 +19313,8 @@ start_preparsed_function (tree decl1, tr
start_function_contracts (decl1);
if (!processing_template_decl
- && (flag_lifetime_dse > 1)
+ && flag_lifetime_dse > 1
+ && flag_auto_var_init == AUTO_INIT_UNINITIALIZED
&& DECL_CONSTRUCTOR_P (decl1)
&& !DECL_CLONED_FUNCTION_P (decl1)
/* Clobbering an empty base is harmful if it overlays real data. */
--- gcc/flag-types.h.jj 2025-08-23 15:00:04.410786022 +0200
+++ gcc/flag-types.h 2025-09-04 11:40:25.872551977 +0200
@@ -288,7 +288,8 @@ enum vect_cost_model {
enum auto_init_type {
AUTO_INIT_UNINITIALIZED = 0,
AUTO_INIT_PATTERN = 1,
- AUTO_INIT_ZERO = 2
+ AUTO_INIT_ZERO = 2,
+ AUTO_INIT_CXX26 = 3
};
/* Initialization of padding bits with zeros. */
--- gcc/testsuite/g++.dg/cpp26/attr-indeterminate1.C.jj 2025-09-04
15:28:43.143684890 +0200
+++ gcc/testsuite/g++.dg/cpp26/attr-indeterminate1.C 2025-09-04
15:50:32.883684485 +0200
@@ -0,0 +1,154 @@
+// C++ 26 P2795R5 - Erroneous behaviour for uninitialized reads
+// { dg-do compile { target c++11 } }
+
+int arr[2];
+struct S { int a, b; };
+S arr2[2];
+
+void
+foo ([[indeterminate]] int n, int n2 [[indeterminate]], int n3
[[indeterminate]] [2])
+{
+ [[indeterminate]] int x1, x11, x12, x13;
+ int x14, x15 [[indeterminate]];
+ [[indeterminate ("foobar")]] int x2; // { dg-error "'indeterminate'
attribute does not take any arguments" }
+ // { dg-error "expected primary-expression
before 'int'" "" { target *-*-* } .-1 }
+ [[indeterminate (0)]] int x3; // { dg-error
"'indeterminate' attribute does not take any arguments" }
+ // { dg-error "expected primary-expression
before 'int'" "" { target *-*-* } .-1 }
+ [[indeterminate ("foo", "bar", "baz")]] int x4;// { dg-error "'indeterminate'
attribute does not take any arguments" }
+ // { dg-error "expected primary-expression
before 'int'" "" { target *-*-* } .-1 }
+ [[indeterminate (0, 1, 2)]] int x5; // { dg-error "'indeterminate'
attribute does not take any arguments" }
+ // { dg-error "expected primary-expression
before 'int'" "" { target *-*-* } .-1 }
+
+ auto a = [] [[indeterminate]] () {}; // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+ auto b = [] constexpr [[indeterminate]] {}; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+ // { dg-error "parameter declaration before
lambda declaration specifiers only optional with" "" { target c++20_down } .-1 }
+ // { dg-error "'constexpr' lambda only
available with" "" { target c++14_down } .-2 }
+ auto c = [] noexcept [[indeterminate]] {}; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+ // { dg-error "parameter declaration before
lambda exception specification only optional with" "" { target c++20_down } .-1 }
+ auto d = [] () [[indeterminate]] {}; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+ auto e = new int [n] [[indeterminate]]; // { dg-warning "attributes ignored
on outermost array type in new expression" }
+ auto e2 = new int [n] [[indeterminate]] [42]; // { dg-warning "attributes
ignored on outermost array type in new expression" }
+ auto f = new int [n][42] [[indeterminate]]; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+ [[indeterminate]]; // { dg-warning "attributes at the
beginning of statement are ignored" }
+ [[indeterminate]] {} // { dg-warning "attributes at the
beginning of statement are ignored" }
+ [[indeterminate]] if (true) {} // { dg-warning "attributes at the
beginning of statement are ignored" }
+ [[indeterminate]] while (false) {} // { dg-warning "attributes at the
beginning of statement are ignored" }
+ [[indeterminate]] goto lab; // { dg-warning "attributes at the
beginning of statement are ignored" }
+ [[indeterminate]] lab:; // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+ [[indeterminate]] try {} catch (int) {} // { dg-warning "attributes at the
beginning of statement are ignored" }
+ if ([[indeterminate]] int x = 0) {}
+ switch (n)
+ {
+ [[indeterminate]] case 1: // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+ [[indeterminate]] break; // { dg-warning "attributes at the
beginning of statement are ignored" }
+ [[indeterminate]] default: // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+ break;
+ }
+ for ([[indeterminate]] auto a : arr) {}
+ for ([[indeterminate]] auto [a, b] : arr2) {} // { dg-error "structured bindings
only available with" "" { target c++14_down } }
+ [[indeterminate]] asm (""); // { dg-warning "attributes
ignored on 'asm' declaration" }
+ try {} catch ([[indeterminate]] int x) {}
+ try {} catch ([[indeterminate]] int) {}
+ try {} catch (int [[indeterminate]] x) {} // { dg-warning "attribute
ignored" }
+ try {} catch (int [[indeterminate]]) {} // { dg-warning "attribute
ignored" }
+ try {} catch (int x [[indeterminate]]) {}
+}
+
+[[indeterminate]] int bar (); // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+using foobar [[indeterminate]] = int; // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+[[indeterminate]] int a; // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+[[indeterminate]] auto [b, c] = arr; // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+ // { dg-error "structured bindings only
available with" "" { target c++14_down } .-1 }
+[[indeterminate]]; // { dg-warning "attribute
ignored" }
+inline [[indeterminate]] void baz () {} // { dg-warning "attribute
ignored" }
+ // { dg-error "standard attributes in middle
of decl-specifiers" "" { target *-*-* } .-1 }
+constexpr [[indeterminate]] int qux () { return 0; } // { dg-warning "attribute
ignored" }
+ // { dg-error "standard attributes in middle
of decl-specifiers" "" { target *-*-* } .-1 }
+int [[indeterminate]] d; // { dg-warning "attribute
ignored" }
+int const [[indeterminate]] e = 1; // { dg-warning "attribute
ignored" }
+struct A {} [[indeterminate]]; // { dg-warning "attribute ignored
in declaration of 'struct A'" }
+struct A [[indeterminate]]; // { dg-warning "attribute
ignored" }
+struct A [[indeterminate]] a1; // { dg-warning "attribute
ignored" }
+A [[indeterminate]] a2; // { dg-warning "attribute
ignored" }
+enum B { B0 } [[indeterminate]]; // { dg-warning "attribute ignored
in declaration of 'enum B'" }
+enum B [[indeterminate]]; // { dg-warning "attribute
ignored" }
+enum B [[indeterminate]] b1; // { dg-warning "attribute
ignored" }
+B [[indeterminate]] b2; // { dg-warning "attribute
ignored" }
+struct [[indeterminate]] C {}; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+int f [[indeterminate]]; // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+int g[2] [[indeterminate]]; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+int g2 [[indeterminate]] [2]; // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+int corge () [[indeterminate]]; // { dg-warning
"'indeterminate' attribute does not apply to types" }
+int *[[indeterminate]] h; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+int & [[indeterminate]] i = f; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+int && [[indeterminate]] j = 0; // { dg-warning
"'indeterminate' attribute does not apply to types" }
+int S::* [[indeterminate]] k; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+auto l = sizeof (int [2] [[indeterminate]]); // { dg-warning "'indeterminate'
attribute does not apply to types" }
+int freddy ([[indeterminate]] int a,
+ [[indeterminate]] int,
+ [[indeterminate]] int c = 0,
+ [[indeterminate]] int = 0);
+void
+corge ([[indeterminate]] int a,
+ [[indeterminate]] int,
+ [[indeterminate]] int c = 0,
+ [[indeterminate]] int = 0)
+{
+}
+[[indeterminate]] void
+garply () // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+{
+}
+int grault (int [[indeterminate]] a, // { dg-warning "attribute
ignored" }
+ int [[indeterminate]], // { dg-warning "attribute
ignored" }
+ int [[indeterminate]] c = 0, // { dg-warning "attribute
ignored" }
+ int [[indeterminate]] = 0); // { dg-warning "attribute
ignored" }
+void
+waldo (int [[indeterminate]] a, // { dg-warning "attribute
ignored" }
+ int [[indeterminate]], // { dg-warning "attribute
ignored" }
+ int [[indeterminate]] c = 0, // { dg-warning "attribute
ignored" }
+ int [[indeterminate]] = 0) // { dg-warning "attribute
ignored" }
+{
+}
+int plugh (int a [[indeterminate]],
+ int b [[indeterminate]] = 0);
+void
+thud (int a [[indeterminate]],
+ int b [[indeterminate]] = 0)
+{
+}
+enum [[indeterminate]] D { D0 }; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+enum class [[indeterminate]] E { E0 }; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+enum F {};
+enum [[indeterminate]] F; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+enum G {
+ G0 [[indeterminate]], // { dg-error
"'indeterminate' on declaration other than parameter or automatic variable" }
+ G1 [[indeterminate]] = 2 // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+};
+namespace [[indeterminate]] H { using H0 = int; }// { dg-warning "'indeterminate'
attribute directive ignored" }
+namespace [[indeterminate]] {} // { dg-warning "'indeterminate'
attribute directive ignored" }
+[[indeterminate]] using namespace H; // { dg-warning "'indeterminate'
attribute directive ignored" }
+struct [[indeterminate]] I // { dg-warning "'indeterminate'
attribute does not apply to types" }
+{
+ [[indeterminate]]; // { dg-error "declaration does not
declare anything" }
+ [[indeterminate]] int i; // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+ [[indeterminate]] int foo (); // { dg-error
"'indeterminate' on declaration other than parameter or automatic variable" }
+ [[indeterminate]] int bar () { return 1; } // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+ [[indeterminate]] int : 0; // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+ [[indeterminate]] int i2 : 5; // { dg-error
"'indeterminate' on declaration other than parameter or automatic variable" }
+ [[indeterminate]] static int i3; // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+ static int i4;
+};
+[[indeterminate]] int I::i4 = 0; // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+struct J : [[indeterminate]] C {}; // { dg-warning "attributes on base
specifiers are ignored" }
+#if __cpp_concepts >= 201907L
+template <typename T>
+concept K [[indeterminate]] = requires { true; };// { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" "" { target c++20 } }
+#endif
+typedef int L [[indeterminate]]; // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
+template <typename T>
+struct M {};
+template <>
+struct [[indeterminate]] M<int> { int m; }; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+typedef int N[2] [[indeterminate]]; // { dg-warning "'indeterminate'
attribute does not apply to types" }
+typedef int O [[indeterminate]] [2]; // { dg-error "'indeterminate' on
declaration other than parameter or automatic variable" }
--- gcc/c-family/c-opts.cc.jj 2025-08-11 12:25:20.493002827 +0200
+++ gcc/c-family/c-opts.cc 2025-09-04 12:23:40.373384906 +0200
@@ -913,6 +913,10 @@ c_common_post_options (const char **pfil
else
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);
+
/* C23 Annex F does not permit certain built-in functions to raise
"inexact". */
if (flag_isoc23)
Jakub