]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Ada: Fix missing error for dangling pointer from access discriminant
authorEric Botcazou <ebotcazou@adacore.com>
Thu, 12 Mar 2026 17:11:34 +0000 (18:11 +0100)
committerEric Botcazou <ebotcazou@adacore.com>
Thu, 12 Mar 2026 17:30:51 +0000 (18:30 +0100)
This restores the original computation of the scope depth of the innermost
enclosing master of a given node and performs a couple of other cleanups.

Note that this has uncovered an issue in the ACATS c3a0025 test and the
change contains the modification that has been submitted to the ACAA.

gcc/ada/
PR ada/124369
* accessibility.adb (Accessibility_Message): Give an error instead
of a warning in an instance when No_Dynamic_Accessibility_Checks is
in effect.
(Innermost_Master_Scope_Depth): Restore the original computation of
the nearest enclosing dynamic scope.
* sem_attr.adb (Resolve_Attribute) <Attribute_Access>: Call the
Accessibility_Message routine in all cases to give accessibility
errors and do not return.  Call the Static_Accessibility_Level
function in all cases to compute static accessibility levels.
Add guard before calling Prefix_With_Safe_Accessibility_Level.

gcc/testsuite/
* ada/acats-3/tests/c3/c3a0025.a: Tweak.
* ada/acats-4/tests/c3/c3a0025.a: Likewise.
* gnat.dg/access12.adb: New test.

gcc/ada/accessibility.adb
gcc/ada/sem_attr.adb
gcc/testsuite/ada/acats-3/tests/c3/c3a0025.a
gcc/testsuite/ada/acats-4/tests/c3/c3a0025.a
gcc/testsuite/gnat.dg/access12.adb [new file with mode: 0644]

index a6518c216118c2acc03a2d7d12e5c76a1994fa6e..2e1406be9a615adba85454b7bcfa755e415ffaac 100644 (file)
@@ -64,10 +64,13 @@ package body Accessibility is
 
    begin
       --  In an instance, this is a runtime check, but one we know will fail,
-      --  so generate an appropriate warning.
+      --  so generate an appropriate warning. As usual, this kind of warning
+      --  is an error in SPARK mode or if No_Dynamic_Accessibility_Checks.
 
       if In_Instance_Body then
-         Error_Msg_Warn := SPARK_Mode /= On;
+         Error_Msg_Warn := SPARK_Mode /= On
+                             and then not
+                               No_Dynamic_Accessibility_Checks_Enabled (P);
          Error_Msg_F
            ("non-local pointer cannot point to local object<<", P);
          Error_Msg_F ("\Program_Error [<<", P);
@@ -152,7 +155,7 @@ package body Accessibility is
       begin
          --  Locate the nearest enclosing node (by traversing Parents)
          --  that Defining_Entity can be applied to, and return the
-         --  depth of that entity's nearest enclosing scope.
+         --  depth of that entity's nearest enclosing dynamic scope.
 
          --  The RM 7.6.1(3) definition of "master" includes statements
          --  and conditions for loops among other things. Are these cases
@@ -162,19 +165,7 @@ package body Accessibility is
             Ent := Defining_Entity_Or_Empty (Node_Par);
 
             if Present (Ent) then
-               --  X'Old is nested within the current subprogram, so we do not
-               --  want Find_Enclosing_Scope of that subprogram. If this is an
-               --  allocator, then we're looking for the innermost master of
-               --  the call, so again we do not want Find_Enclosing_Scope.
-
-               if (Nkind (N) = N_Attribute_Reference
-                    and then Attribute_Name (N) = Name_Old)
-                 or else Nkind (N) = N_Allocator
-               then
-                  Encl_Scop := Ent;
-               else
-                  Encl_Scop := Find_Enclosing_Scope (Ent);
-               end if;
+               Encl_Scop := Nearest_Dynamic_Scope (Ent);
 
                --  Ignore transient scopes made during expansion while also
                --  taking into account certain expansions - like iterators
index 90eb682a09446c71b841798964f16da836425fc4..161e5cd16c059782f2b0dd97838fed813c0fbaf7 100644 (file)
@@ -12043,29 +12043,7 @@ package body Sem_Attr is
                    Static_Accessibility_Level (N, Zero_On_Dynamic_Level) >
                      Deepest_Type_Access_Level (Btyp)
                then
-                  --  In an instance, this is a runtime check, but one we know
-                  --  will fail, so generate an appropriate warning. As usual,
-                  --  this kind of warning is an error in SPARK mode.
-
-                  if In_Instance_Body then
-                     Error_Msg_Warn :=
-                       SPARK_Mode /= On
-                         and then
-                           not No_Dynamic_Accessibility_Checks_Enabled (P);
-
-                     Error_Msg_F
-                       ("non-local pointer cannot point to local object<<", P);
-                     Error_Msg_F ("\Program_Error [<<", P);
-
-                     Rewrite (N,
-                       Make_Raise_Program_Error (Loc,
-                         Reason => PE_Accessibility_Check_Failed));
-                     Set_Etype (N, Typ);
-
-                  else
-                     Error_Msg_F
-                       ("non-local pointer cannot point to local object", P);
-                  end if;
+                  Accessibility_Message (N, Typ);
                end if;
 
                if Attr_Id /= Attribute_Unrestricted_Access
@@ -12233,22 +12211,11 @@ package body Sem_Attr is
                                    and then Ekind (Btyp)
                                               = E_Anonymous_Access_Type)
 
-                    --  Call Accessibility_Level directly to avoid returning
-                    --  zero on cases where the prefix is an explicitly aliased
-                    --  parameter in a return statement, instead of using the
-                    --  normal Static_Accessibility_Level function.
-
-                    --  Shouldn't this be handled somehow in
-                    --  Static_Accessibility_Level ???
-
-                    and then Nkind (Accessibility_Level (P, Dynamic_Level))
-                               = N_Integer_Literal
                     and then
-                      Intval (Accessibility_Level (P, Dynamic_Level))
-                        Deepest_Type_Access_Level (Btyp)
+                      Static_Accessibility_Level (N, Zero_On_Dynamic_Level) >
+                        Deepest_Type_Access_Level (Btyp)
                   then
                      Accessibility_Message (N, Typ);
-                     return;
                   end if;
                end;
             end if;
@@ -12274,7 +12241,6 @@ package body Sem_Attr is
                  and then Attr_Id /= Attribute_Unrestricted_Access
                then
                   Accessibility_Message (N, Typ);
-                  return;
 
                --  AI05-0225: If the context is not an access to protected
                --  function, the prefix must be a variable, given that it may
@@ -12424,9 +12390,10 @@ package body Sem_Attr is
             --  array type since a value conversion is like an aggregate with
             --  respect to determining accessibility level (RM 3.10.2).
 
-            if not Prefix_With_Safe_Accessibility_Level (N, Typ) then
+            if Nkind (N) /= N_Raise_Program_Error
+              and then not Prefix_With_Safe_Accessibility_Level (N, Typ)
+            then
                Accessibility_Message (N, Typ);
-               return;
             end if;
 
             --  Mark that address of entity is taken in case of
index ea2cb2911e470ab89815ec59a0ccd53131368e28..5d497860f814e32f0256ef0d4358ed9af64c1109 100644 (file)
@@ -324,8 +324,11 @@ begin
          when Constraint_Error =>
             null;
       end;
-      Obj := Func_1 (Non_Null_Init);
-      if Obj /= Non_Null_Init then
+      --  Temporary deviation from the original test:
+      --    Obj := Func_1 (Non_Null_Init);
+      --    if Obj /= Non_Null_Init then
+
+      if Func_1 (Non_Null_Init) /= Non_Null_Init then
          Report.Failed ("Func_1_OK: Wrong value");
       end if;
    end;
@@ -347,8 +350,11 @@ begin
          when Constraint_Error =>
             null;
       end;
-      Obj := Func_2 (Non_Null_Init);
-      if Obj /= Non_Null_Init then
+      --  Temporary deviation from the original test:
+      --    Obj := Func_2 (Non_Null_Init);
+      --    if Obj /= Non_Null_Init then
+
+      if Func_2 (Non_Null_Init) /= Non_Null_Init then
          Report.Failed ("Func_2_OK: Wrong value");
       end if;
    end;
index ea2cb2911e470ab89815ec59a0ccd53131368e28..5d497860f814e32f0256ef0d4358ed9af64c1109 100644 (file)
@@ -324,8 +324,11 @@ begin
          when Constraint_Error =>
             null;
       end;
-      Obj := Func_1 (Non_Null_Init);
-      if Obj /= Non_Null_Init then
+      --  Temporary deviation from the original test:
+      --    Obj := Func_1 (Non_Null_Init);
+      --    if Obj /= Non_Null_Init then
+
+      if Func_1 (Non_Null_Init) /= Non_Null_Init then
          Report.Failed ("Func_1_OK: Wrong value");
       end if;
    end;
@@ -347,8 +350,11 @@ begin
          when Constraint_Error =>
             null;
       end;
-      Obj := Func_2 (Non_Null_Init);
-      if Obj /= Non_Null_Init then
+      --  Temporary deviation from the original test:
+      --    Obj := Func_2 (Non_Null_Init);
+      --    if Obj /= Non_Null_Init then
+
+      if Func_2 (Non_Null_Init) /= Non_Null_Init then
          Report.Failed ("Func_2_OK: Wrong value");
       end if;
    end;
diff --git a/gcc/testsuite/gnat.dg/access12.adb b/gcc/testsuite/gnat.dg/access12.adb
new file mode 100644 (file)
index 0000000..5820b91
--- /dev/null
@@ -0,0 +1,26 @@
+-- { dg-do compile }
+
+procedure Access12 is
+
+   type Rec (Element : access Integer) is null record;
+
+   function Make_Rec (X : access Integer) return Rec is (Element => X);
+
+   type Acc is access all Integer;
+
+   A : Acc;
+
+begin
+   for I in 1 .. 10 loop
+      declare
+         X : aliased Integer;
+         R : Rec := Make_Rec (X'Access);
+      begin
+         if I = 1 then
+            X := 0;
+         end if;
+         A := R.Element.all'Access; -- { dg-error "non-local pointer" }
+         X := I;
+      end;
+   end loop;
+end;