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);

Reply via email to