]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Constraint error not raised in ACATS test c413007
authorJavier Miranda <miranda@adacore.com>
Tue, 17 Sep 2024 11:53:06 +0000 (11:53 +0000)
committerMarc Poulhiès <dkm@gcc.gnu.org>
Fri, 25 Oct 2024 09:09:00 +0000 (11:09 +0200)
The Constraint_Error exception is not raised when a subprogram
is called using prefix notation, and the prefix of the call is
an access-to-subprogram type with a null value. This new check
is enabled by switch -gnatd_P

gcc/ada/ChangeLog:

* gen_il-fields.ads: New node field (Is_Expanded_Prefixed_Call).
* gen_il-gen-gen_nodes.adb: New semantic field for N_Function_Call
and N_Procedure_Call_Statement nodes.
* sem_ch4.adb (Complete_Object_Operation): Mark the rewritten node
with the Is_Expanded_Prefixed_Call flag.
* sem_res.adb (Check_Prefixed_Call): Code cleanup and addition of
documentation.
(Resolve_Actuals): Add a null-exclusion check on the
prefix of the call when it is an access-type.
* sinfo.ads: Adding new semantic flag (Is_Expanded_Prefixed_Call)
to N_Function_Call and N_Procedure_Call_Statement nodes.
* debug.adb: Adding documentation for switch d_P.

gcc/ada/debug.adb
gcc/ada/gen_il-fields.ads
gcc/ada/gen_il-gen-gen_nodes.adb
gcc/ada/sem_ch4.adb
gcc/ada/sem_res.adb
gcc/ada/sinfo.ads

index 3dbf3a7b3976977fc92d81f9b9e6ab2f689ecaf8..9daa0110233bc2d0cc411aae64f86a06a7a79aea 100644 (file)
@@ -180,7 +180,7 @@ package body Debug is
    --  d_M  Ignore Source_File_Name and Source_File_Name_Project pragmas
    --  d_N
    --  d_O
-   --  d_P
+   --  d_P  Enable runtime check for null prefix of prefixed subprogram call
    --  d_Q
    --  d_R  For LLVM, dump the representation of records
    --  d_S
@@ -1040,6 +1040,14 @@ package body Debug is
    --       it is checked, and the progress of the recursive trace through
    --       elaboration calls at compile time.
 
+   --  d_P  For prefixed subprogram calls with an access-type prefix, generate
+   --       a null-excluding runtime check on the prefix, even when the called
+   --       subprogram has a first access parameter that does not exclude null
+   --       (that is the case only for class-wide parameter, as controlling
+   --       parameters are automatically null-excluding). In such a case,
+   --       P.Proc is equivalent to Proc(P.all'Access); see RM 6.4(9.1/5).
+   --       This includes a dereference, and thus a null check.
+
    --  d_R  In the LLVM backend, output the internal representation of
    --       each record
 
index dcebab67d0c99645b630009f12de9f314a1e8486..5563a9d385cd5c0bf0721c827fd92f11a2fd6557 100644 (file)
@@ -255,6 +255,7 @@ package Gen_IL.Fields is
       Is_Elsif,
       Is_Entry_Barrier_Function,
       Is_Expanded_Build_In_Place_Call,
+      Is_Expanded_Prefixed_Call,
       Is_Folded_In_Parser,
       Is_Generic_Contract_Pragma,
       Is_Homogeneous_Aggregate,
index d211343a607749e3a15f5aad1c8029d1b4eb8d00..55d54358e4604b38463f735d559d1c1ac34934e9 100644 (file)
@@ -408,11 +408,13 @@ begin -- Gen_IL.Gen.Gen_Nodes
    Cc (N_Function_Call, N_Subprogram_Call,
        (Sy (Name, Node_Id, Default_Empty),
         Sy (Parameter_Associations, List_Id, Default_No_List),
-        Sm (Is_Expanded_Build_In_Place_Call, Flag)));
+        Sm (Is_Expanded_Build_In_Place_Call, Flag),
+        Sm (Is_Expanded_Prefixed_Call, Flag)));
 
    Cc (N_Procedure_Call_Statement, N_Subprogram_Call,
        (Sy (Name, Node_Id, Default_Empty),
-        Sy (Parameter_Associations, List_Id, Default_No_List)));
+        Sy (Parameter_Associations, List_Id, Default_No_List),
+        Sm (Is_Expanded_Prefixed_Call, Flag)));
 
    Ab (N_Raise_xxx_Error, N_Subexpr);
 
index bf0d7cfd1af954d14b14e961b14e4e3cc005d13f..c1f6622db1e45b307a533d7ad1710b05a8efea12 100644 (file)
@@ -9510,7 +9510,6 @@ package body Sem_Ch4 is
                Error_Msg_NE
                  ("expect variable in call to&", Prefix (N), Entity (Subprog));
             end if;
-
          --  Conversely, if the formal is an access parameter and the object is
          --  not an access type or a reference type (i.e. a type with the
          --  Implicit_Dereference aspect specified), replace the actual with a
@@ -9581,6 +9580,8 @@ package body Sem_Ch4 is
 
          Rewrite (Node_To_Replace, Call_Node);
 
+         Set_Is_Expanded_Prefixed_Call (Node_To_Replace);
+
          --  Propagate the interpretations collected in subprog to the new
          --  function call node, to be resolved from context.
 
@@ -10746,6 +10747,7 @@ package body Sem_Ch4 is
             Complete_Object_Operation
               (Call_Node       => New_Call_Node,
                Node_To_Replace => Node_To_Replace);
+
             return True;
          end if;
 
index 5f77ddabd09ef27249b89c4f94e13db368de1f98..6a2680b6b1da15cb1ecc2bc5b5d3901053d32bd7 100644 (file)
@@ -3889,54 +3889,48 @@ package body Sem_Res is
       -------------------------
 
       procedure Check_Prefixed_Call is
-         Act    : constant Node_Id   := First_Actual (N);
-         A_Type : constant Entity_Id := Etype (Act);
-         F_Type : constant Entity_Id := Etype (First_Formal (Nam));
-         Orig   : constant Node_Id := Original_Node (N);
-         New_A  : Node_Id;
+         Actual      : constant Node_Id   := First_Actual (N);
+         Actual_Type : constant Entity_Id := Etype (Actual);
+         Formal_Type : constant Entity_Id := Etype (First_Formal (Nam));
+         New_Actual  : Node_Id;
 
       begin
          --  Check whether the call is a prefixed call, with or without
          --  additional actuals.
 
-         if Nkind (Orig) = N_Selected_Component
-           or else
-             (Nkind (Orig) = N_Indexed_Component
-               and then Nkind (Prefix (Orig)) = N_Selected_Component
-               and then Is_Entity_Name (Prefix (Prefix (Orig)))
-               and then Is_Entity_Name (Act)
-               and then Chars (Act) = Chars (Prefix (Prefix (Orig))))
-         then
-            if Is_Access_Type (A_Type)
-              and then not Is_Access_Type (F_Type)
-            then
-               --  Introduce dereference on object in prefix
+         if Is_Expanded_Prefixed_Call (N) then
 
-               New_A :=
-                 Make_Explicit_Dereference (Sloc (Act),
-                   Prefix => Relocate_Node (Act));
-               Rewrite (Act, New_A);
-               Analyze (Act);
+            --  Introduce dereference on object in prefix
 
-            elsif Is_Access_Type (F_Type)
-              and then not Is_Access_Type (A_Type)
+            if Is_Access_Type (Actual_Type)
+              and then not Is_Access_Type (Formal_Type)
             then
-               --  Introduce an implicit 'Access in prefix
-
-               if not Is_Aliased_View (Act) then
-                  Error_Msg_NE
-                    ("object in prefixed call to& must be aliased "
-                     & "(RM 4.1.3 (13 1/2))",
-                    Prefix (Act), Nam);
-               end if;
-
-               Rewrite (Act,
+               New_Actual :=
+                 Make_Explicit_Dereference (Sloc (Actual),
+                   Prefix => Relocate_Node (Actual));
+               Rewrite (Actual, New_Actual);
+               Analyze (Actual);
+
+            --  Conversely, if the formal is an access parameter and the object
+            --  is not an access type or a reference type (i.e. a type with the
+            --  Implicit_Dereference aspect specified), add an implicit 'Access
+            --  to the prefix. Its analysis will check that the object is
+            --  aliased.
+
+            elsif Is_Access_Type (Formal_Type)
+              and then not Is_Access_Type (Actual_Type)
+              and then (not Has_Implicit_Dereference (Actual_Type)
+                or else
+                  not Is_Access_Type
+                        (Designated_Type
+                           (Etype (Get_Reference_Discriminant (Actual_Type)))))
+            then
+               Rewrite (Actual,
                  Make_Attribute_Reference (Loc,
                    Attribute_Name => Name_Access,
-                   Prefix         => Relocate_Node (Act)));
+                   Prefix         => Relocate_Node (Actual)));
+               Analyze (Actual);
             end if;
-
-            Analyze (Act);
          end if;
       end Check_Prefixed_Call;
 
@@ -4935,6 +4929,31 @@ package body Sem_Res is
                         Reason => CE_Null_Not_Allowed);
                   end if;
                end if;
+
+               --  In a prefixed call, if the prefix is an access type
+               --  it cannot be null.
+
+               if Is_Access_Type (F_Typ)
+                 and then A = First_Actual (N)
+                 and then Is_Expanded_Prefixed_Call (N)
+               then
+                  if not Is_Access_Type (A_Typ)
+                    and then not Is_Aliased_View (A)
+                  then
+                     Error_Msg_NE
+                       ("object in prefixed call to& must be aliased "
+                        & "(RM 4.1.3 (13 1/2))",
+                       A, Nam);
+                  end if;
+
+                  if Debug_Flag_Underscore_PP
+                    and then
+                      (Is_Controlling_Formal (F)
+                         or else Is_Class_Wide_Type (Designated_Type (F_Typ)))
+                  then
+                     Install_Null_Excluding_Check (A);
+                  end if;
+               end if;
             end if;
 
             --  Checks for OUT parameters and IN OUT parameters
index 746207a549a5edb0a5e35066833dceb7df79ae31..78cc236a73c3cacdfed9277156cde07d56c957c9 100644 (file)
@@ -1686,6 +1686,10 @@ package Sinfo is
    --    actuals to support a build-in-place style of call have been added to
    --    the call.
 
+   --  Is_Expanded_Prefixed_Call
+   --    This flag is set in N_Function_Call and N_Procedure_Call_Statement
+   --    nodes to indicate that it is an expanded prefixed call.
+
    --  Is_Generic_Contract_Pragma
    --    This flag is present in N_Pragma nodes. It is set when the pragma is
    --    a source construct, applies to a generic unit or its body, and denotes
@@ -5505,6 +5509,7 @@ package Sinfo is
       --  First_Named_Actual
       --  Controlling_Argument (set to Empty if not dispatching)
       --  Is_Elaboration_Checks_OK_Node
+      --  Is_Expanded_Prefixed_Call
       --  Is_SPARK_Mode_On_Node
       --  Is_Elaboration_Warnings_OK_Node
       --  No_Elaboration_Check
@@ -5541,6 +5546,7 @@ package Sinfo is
       --  Is_Elaboration_Warnings_OK_Node
       --  No_Elaboration_Check
       --  Is_Expanded_Build_In_Place_Call
+      --  Is_Expanded_Prefixed_Call
       --  Is_Known_Guaranteed_ABE
       --  plus fields for expression