https://gcc.gnu.org/g:c95f6ebcc60a57b4c9559a39f2fad7ca37883fa8
commit r17-1684-gc95f6ebcc60a57b4c9559a39f2fad7ca37883fa8 Author: Eric Botcazou <[email protected]> Date: Wed Jun 17 10:07:41 2026 +0200 Fix wrong optimization of array manipulation at -O2 or above This occurs when the array is declared in a subprogram and manipulated from within a second subprogram nested in the first: in this case, the array is allocated in the special frame structure of the first subprogram as a field with the DECL_NONADDRESSABLE_P flag set if the TREE_ADDRESSABLE flag is not set for the original array variable. But the array may contain addressable (sub)components whose address can be taken, thus fooling the computation of alias sets when strict aliasing is enabled. The fix is in keeping with the usage of DECL_NONADDRESSABLE_P on fields of record types by the Ada compiler, which is the main user of both the flag and the machinery implemented in the tree-nested.cc file. gcc/ * tree-nested.cc (lookup_field_for_decl): In the non-pointer case, clear DECL_NONADDRESSABLE_P if the DECL is of an aggregate type. gcc/testsuite/ * gnat.dg/opt108.adb: New test. * gnat.dg/opt108_pkg.ads, gnat.dg/opt108_pkg.adb: New helper. Diff: --- gcc/testsuite/gnat.dg/opt108.adb | 10 ++++++++++ gcc/testsuite/gnat.dg/opt108_pkg.adb | 38 ++++++++++++++++++++++++++++++++++++ gcc/testsuite/gnat.dg/opt108_pkg.ads | 21 ++++++++++++++++++++ gcc/tree-nested.cc | 6 +++++- 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/gcc/testsuite/gnat.dg/opt108.adb b/gcc/testsuite/gnat.dg/opt108.adb new file mode 100644 index 000000000000..ed6034122d36 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt108.adb @@ -0,0 +1,10 @@ +-- { dg-do run } +-- { dg-options "-O2 -gnatp" } + +with Opt108_Pkg; use Opt108_Pkg; + +procedure Opt108 is +begin + Set; + Put; +end; diff --git a/gcc/testsuite/gnat.dg/opt108_pkg.adb b/gcc/testsuite/gnat.dg/opt108_pkg.adb new file mode 100644 index 000000000000..c80e124295dd --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt108_pkg.adb @@ -0,0 +1,38 @@ +with Interfaces; + +package body Opt108_Pkg is + + procedure Put is + begin + if Val.X /= 1 then + raise Program_Error; + end if; + end; + + procedure Set is + type Array_Type is array (Index_Type) of Test_Type; + + New_Val : Array_Type := (others => (X => 0)); + + procedure Next + (Index : Index_Type; + T : in out Test_Type) + is + begin + T := (X => T.X + 1); + New_Val (Index) := T; + end Next; + + Cur : Test_Type; + + begin + Cur := (X => 0); + + if not Flag then + Next (Index => Cur_Index, T => Cur); + end if; + + Val := New_Val (1); + end; + +end Opt108_Pkg; diff --git a/gcc/testsuite/gnat.dg/opt108_pkg.ads b/gcc/testsuite/gnat.dg/opt108_pkg.ads new file mode 100644 index 000000000000..3464e84b0660 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt108_pkg.ads @@ -0,0 +1,21 @@ +package Opt108_Pkg is + + procedure Set; + + procedure Put; + +private + + type Test_Type is record + X : Integer; + end record; + + type Index_Type is range 1 .. 1; + + Cur_Index : Index_Type := 1; + + Flag : Boolean := False; + + Val : Test_Type; + +end Opt108_Pkg; diff --git a/gcc/tree-nested.cc b/gcc/tree-nested.cc index cdccc51d33e1..2a57a84e1208 100644 --- a/gcc/tree-nested.cc +++ b/gcc/tree-nested.cc @@ -411,7 +411,11 @@ lookup_field_for_decl (struct nesting_info *info, tree decl, SET_DECL_ALIGN (field, DECL_ALIGN (decl)); DECL_USER_ALIGN (field) = DECL_USER_ALIGN (decl); DECL_IGNORED_P (field) = DECL_IGNORED_P (decl); - DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (decl); + /* Even if the address of the DECL is not needed, when it is of an + aggregate type, it may contain addressable fields whose address + will be taken later. */ + DECL_NONADDRESSABLE_P (field) + = !TREE_ADDRESSABLE (decl) && !AGGREGATE_TYPE_P (TREE_TYPE (decl)); TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (decl); copy_warning (field, decl);
