[Ada] New warning on not fully initialized box aggregate
authorArnaud Charlet <charlet@adacore.com>
Thu, 16 Jul 2020 16:38:10 +0000 (12:38 -0400)
committerPierre-Marie de Rodat <derodat@adacore.com>
Tue, 20 Oct 2020 07:21:41 +0000 (03:21 -0400)
gcc/ada/

* sem_aggr.adb (Resolve_Aggregate): Warn on not fully
initialized box aggregate.
* sem_aggr.ads: Fix typo.
* sem_res.adb (Resolve_Actuals): Fix typo in error message
format marking it incorrectly as a continuation message.
* sem_elab.adb (Check_Internal_Call_Continue): Similarly, add
missing primary message in case of a call to an actual generic
subprogram.
* sem_warn.adb (Check_References): Do not warn on read but never
assigned variables if the type is partially initialized.
* libgnat/a-except.ads, libgnat/a-ststun.ads,
libgnat/g-sechas.ads, libgnat/a-cbdlli.ads,
libgnat/a-cfdlli.ads, libgnat/a-cobove.ads,
libgnat/a-cohata.ads, libgnat/a-crbltr.ads,
libgnat/a-cbmutr.ads, libgnat/a-crdlli.ads,
libgnat/a-cbsyqu.ads: Address new warning.
* doc/gnat_ugn/building_executable_programs_with_gnat.rst:
Update doc on -gnatwv.
* gnat_ugn.texi: Regenerate.

gcc/testsuite/

* gnat.dg/opt11.adb: Add new expected warning.

19 files changed:
gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
gcc/ada/gnat_ugn.texi
gcc/ada/libgnat/a-cbdlli.ads
gcc/ada/libgnat/a-cbmutr.ads
gcc/ada/libgnat/a-cbsyqu.ads
gcc/ada/libgnat/a-cfdlli.ads
gcc/ada/libgnat/a-cobove.ads
gcc/ada/libgnat/a-cohata.ads
gcc/ada/libgnat/a-crbltr.ads
gcc/ada/libgnat/a-crdlli.ads
gcc/ada/libgnat/a-except.ads
gcc/ada/libgnat/a-ststun.ads
gcc/ada/libgnat/g-sechas.ads
gcc/ada/sem_aggr.adb
gcc/ada/sem_aggr.ads
gcc/ada/sem_elab.adb
gcc/ada/sem_res.adb
gcc/ada/sem_warn.adb
gcc/testsuite/gnat.dg/opt11.adb

index 7afe76df10ca36bbce7ebec036df5d0262d8818e..1dec48754c4214e46f637b84895058562eebb9d4 100644 (file)
@@ -3865,8 +3865,14 @@ of the pragma in the :title:`GNAT_Reference_manual`).
 
   This switch activates warnings for access to variables which
   may not be properly initialized. The default is that
-  such warnings are generated.
+  such warnings are generated. This switch will also be emitted when
+  initializing an array or record object via the following aggregate:
 
+  .. code-block:: ada
+
+       Array_Or_Record : XXX := (others => <>);
+
+  unless the relevant type fully initializes all components.
 
 .. index:: -gnatwV  (gcc)
 
@@ -3875,17 +3881,6 @@ of the pragma in the :title:`GNAT_Reference_manual`).
 
   This switch suppresses warnings for access to variables which
   may not be properly initialized.
-  For variables of a composite type, the warning can also be suppressed in
-  Ada 2005 by using a default initialization with a box. For example, if
-  Table is an array of records whose components are only partially uninitialized,
-  then the following code:
-
-  .. code-block:: ada
-
-       Tab : Table := (others => <>);
-
-  will suppress warnings on subsequent statements that access components
-  of variable Tab.
 
 
 .. index:: -gnatw.v  (gcc)
index c98fe761480ccb61b32a461b75ebd585d2d19561..47618f64135f81049e43f7b0cc6b283a4ebe68d8 100644 (file)
@@ -12224,7 +12224,14 @@ that no warnings are given for comparisons or subranges for any type.
 
 This switch activates warnings for access to variables which
 may not be properly initialized. The default is that
-such warnings are generated.
+such warnings are generated. This switch will also be emitted when
+initializing an array or record object via the following aggregate:
+
+@example
+Array_Or_Record : XXX := (others => <>);
+@end example
+
+unless the relevant type fully initializes all components.
 @end table
 
 @geindex -gnatwV (gcc)
@@ -12238,17 +12245,6 @@ such warnings are generated.
 
 This switch suppresses warnings for access to variables which
 may not be properly initialized.
-For variables of a composite type, the warning can also be suppressed in
-Ada 2005 by using a default initialization with a box. For example, if
-Table is an array of records whose components are only partially uninitialized,
-then the following code:
-
-@example
-Tab : Table := (others => <>);
-@end example
-
-will suppress warnings on subsequent statements that access components
-of variable Tab.
 @end table
 
 @geindex -gnatw.v (gcc)
index 7f16368a59902208168e70b57bc371e0f841cb1e..7e8627aeca8a907cb7e3637427f97f74013f3484 100644 (file)
@@ -274,7 +274,7 @@ private
    type Node_Array is array (Count_Type range <>) of Node_Type;
 
    type List (Capacity : Count_Type) is tagged record
-      Nodes  : Node_Array (1 .. Capacity) := (others => <>);
+      Nodes  : Node_Array (1 .. Capacity);
       Free   : Count_Type'Base := -1;
       First  : Count_Type := 0;
       Last   : Count_Type := 0;
index 82b3d60c9778ee522a583fed131528b1752b704c..a9fb55ac9736966768cddeedc80d41667d8d02f0 100644 (file)
@@ -303,8 +303,8 @@ private
    type Element_Array is array (Count_Type range <>) of aliased Element_Type;
 
    type Tree (Capacity : Count_Type) is tagged record
-      Nodes    : Tree_Node_Array (0 .. Capacity) := (others => <>);
-      Elements : Element_Array (1 .. Capacity) := (others => <>);
+      Nodes    : Tree_Node_Array (0 .. Capacity);
+      Elements : Element_Array (1 .. Capacity);
       Free     : Count_Type'Base := No_Node;
       TC       : aliased Tamper_Counts;
       Count    : Count_Type := 0;
index 61504fa33e72bd30645af463c2137b39f556eea9..225db2184086f0431341d93a06f02ea3900ea7d9 100644 (file)
@@ -78,7 +78,7 @@ is
          First, Last : Count_Type := 0;
          Length      : Count_Type := 0;
          Max_Length  : Count_Type := 0;
-         Elements    : Element_Array (1 .. Capacity) := (others => <>);
+         Elements    : Element_Array (1 .. Capacity);
       end record;
 
    end Implementation;
index 61312396c6370dc10d79a4ed558b0eb44f6e0117..f7dbf042b7c394140de2e263ec53f96fe4697763 100644 (file)
@@ -1617,7 +1617,7 @@ private
       Length : Count_Type := 0;
       First  : Count_Type := 0;
       Last   : Count_Type := 0;
-      Nodes  : Node_Array (1 .. Capacity) := (others => <>);
+      Nodes  : Node_Array (1 .. Capacity);
    end record;
 
    Empty_List : constant List := (0, others => <>);
index 4c8905cf51e6d2ae4bd95b5ef4da9d4402313585..d0a125103056ded64fa59b154caa03568add8491 100644 (file)
@@ -390,7 +390,7 @@ private
    function "=" (L, R : Elements_Array) return Boolean is abstract;
 
    type Vector (Capacity : Count_Type) is tagged record
-      Elements : Elements_Array (1 .. Capacity) := (others => <>);
+      Elements : Elements_Array (1 .. Capacity);
       Last     : Extended_Index := No_Index;
       TC       : aliased Tamper_Counts;
    end record with Put_Image => Put_Image;
index 9033c52a51864d2e81f044bddb0dc1f748a1a4c2..2b98928a59ba7dfdfd71a6d30dce441057a6983d 100644 (file)
@@ -72,7 +72,7 @@ package Ada.Containers.Hash_Tables is
          Length  : Count_Type                  := 0;
          TC      : aliased Helpers.Tamper_Counts;
          Free    : Count_Type'Base             := -1;
-         Nodes   : Nodes_Type (1 .. Capacity)  := (others => <>);
+         Nodes   : Nodes_Type (1 .. Capacity);
          Buckets : Buckets_Type (1 .. Modulus) := (others => 0);
       end record;
 
index 0ae2abd3bac1da520a121aad153fac56dbcd8875..4f00bd6ce619d93180b666007607b5502410fdc0 100644 (file)
@@ -60,9 +60,7 @@ package Ada.Containers.Red_Black_Trees is
       --  Note that objects of type Tree_Type are logically initialized (in the
       --  sense that representation invariants of type are satisfied by dint of
       --  default initialization), even without the Nodes component also having
-      --  its own initialization expression. We only initializae the Nodes
-      --  component here in order to prevent spurious compiler warnings about
-      --  the container object not being fully initialized.
+      --  its own initialization expression.
 
       type Tree_Type (Capacity : Count_Type) is tagged record
          First  : Count_Type := 0;
@@ -71,7 +69,7 @@ package Ada.Containers.Red_Black_Trees is
          Length : Count_Type := 0;
          TC     : aliased Helpers.Tamper_Counts;
          Free   : Count_Type'Base := -1;
-         Nodes  : Nodes_Type (1 .. Capacity) := (others => <>);
+         Nodes  : Nodes_Type (1 .. Capacity);
       end record;
 
       package Implementation is new Helpers.Generic_Implementation;
index 7f274979b8fc5be455c6d55808434ed29431f16a..b30d35398b5b32000ca6359a50422954ae514d72 100644 (file)
@@ -314,7 +314,7 @@ private
    type Node_Array is array (Count_Type range <>) of Node_Type;
 
    type List (Capacity : Count_Type) is tagged limited record
-      Nodes  : Node_Array (1 .. Capacity) := (others => <>);
+      Nodes  : Node_Array (1 .. Capacity);
       Free   : Count_Type'Base := -1;
       First  : Count_Type := 0;
       Last   : Count_Type := 0;
index 22b7be94effff6b61d1c7c32f2d4a4289ff54186..4d36a84fd75119da4105fb6daaacf6566bcc1ef1 100644 (file)
@@ -301,6 +301,8 @@ private
    pragma Stream_Convert (Exception_Occurrence, String_To_EO, EO_To_String);
    --  Functions for implementing Exception_Occurrence stream attributes
 
+   pragma Warnings (Off, "aggregate not fully initialized");
    Null_Occurrence : constant Exception_Occurrence := (others => <>);
+   pragma Warnings (On, "aggregate not fully initialized");
 
 end Ada.Exceptions;
index 95aca9b9269627a522797372b8f7b29b164c32ea..2945bca78f9021bd121fed12133d33f5c31a428f 100644 (file)
@@ -71,7 +71,7 @@ private
       EA : Stream_Element_Array (1 .. Last);
    end record;
 
-   Empty_Elements : aliased Elements_Type := (Last => 0, EA => (others => <>));
+   Empty_Elements : aliased Elements_Type (0);
 
    type Elements_Access is access all Elements_Type;
 
index 2edc2e358ac3fda92f7f518b0bf60bbf1894bbcc..566a6967beedd6468bb9c8cb77fa13efea6b68da 100644 (file)
@@ -218,7 +218,9 @@ package GNAT.Secure_Hashes is
          --  HMAC key
       end record;
 
+      pragma Warnings (Off, "aggregate not fully initialized");
       Initial_Context : constant Context (KL => 0) := (others => <>);
+      pragma Warnings (On, "aggregate not fully initialized");
       --  Initial values are provided by default initialization of Context
 
       type Hash_Stream (C : access Context) is
index eb695617566b97bd24edf87d59b9ea5dbba3a394..e5cdb4f9b118598abb4610a7b4335d89ab34ddd8 100644 (file)
@@ -791,6 +791,31 @@ package body Sem_Aggr is
       --  The actual aggregate subtype. This is not necessarily the same as Typ
       --  which is the subtype of the context in which the aggregate was found.
 
+      Others_Box : Boolean := False;
+      --  Set to True if N represents a simple aggregate with only
+      --  (others => <>), not nested as part of another aggregate.
+
+      function Within_Aggregate (N : Node_Id) return Boolean;
+      --  Return True if N is part of an N_Aggregate
+
+      ----------------------
+      -- Within_Aggregate --
+      ----------------------
+
+      function Within_Aggregate (N : Node_Id) return Boolean is
+         P : Node_Id := Parent (N);
+      begin
+         while Present (P) loop
+            if Nkind (P) = N_Aggregate then
+               return True;
+            end if;
+
+            P := Parent (P);
+         end loop;
+
+         return False;
+      end Within_Aggregate;
+
    begin
       --  Ignore junk empty aggregate resulting from parser error
 
@@ -811,16 +836,26 @@ package body Sem_Aggr is
         and then Present (Component_Associations (N))
       then
          declare
-            Comp : Node_Id;
+            Comp       : Node_Id;
+            First_Comp : Boolean := True;
 
          begin
             Comp := First (Component_Associations (N));
             while Present (Comp) loop
                if Box_Present (Comp) then
+                  if First_Comp
+                    and then No (Expressions (N))
+                    and then Nkind (First (Choices (Comp))) = N_Others_Choice
+                    and then not Within_Aggregate (N)
+                  then
+                     Others_Box := True;
+                  end if;
+
                   Insert_Actions (N, Freeze_Entity (Typ, N));
                   exit;
                end if;
 
+               First_Comp := False;
                Next (Comp);
             end loop;
          end;
@@ -1045,6 +1080,13 @@ package body Sem_Aggr is
          Set_Analyzed (N);
       end if;
 
+      if Warn_On_No_Value_Assigned
+        and then Others_Box
+        and then not Is_Fully_Initialized_Type (Etype (N))
+      then
+         Error_Msg_N ("?v?aggregate not fully initialized", N);
+      end if;
+
       Check_Function_Writable_Actuals (N);
    end Resolve_Aggregate;
 
index b0b4e147fe575fe8db66ad887856690ba8432a9f..cbbc71d4d0be3f916e02f07ea2a3eb12445eb22c 100644 (file)
@@ -39,7 +39,7 @@ package Sem_Aggr is
    --  Returns True is aggregate Aggr consists of a single OTHERS choice
 
    function Is_Single_Aggregate (Aggr : Node_Id) return Boolean;
-   --  Returns True is aggregate Aggr consists of a single choice
+   --  Returns True if aggregate Aggr consists of a single choice
 
    --  WARNING: There is a matching C declaration of this subprogram in fe.h
 
index 78108e99956d03cd5cfa7cac63561633adcc632a..d7a8bb0fd5e3f1a2f46c19224d0bcdafed934ad9 100644 (file)
@@ -18633,16 +18633,17 @@ package body Sem_Elab is
             elsif Nkind (N) = N_Attribute_Reference then
                Error_Msg_NE
                  ("Access attribute of & before body seen<<", N, Orig_Ent);
-               Error_Msg_N ("\possible Program_Error on later references<", N);
+               Error_Msg_N
+                 ("\possible Program_Error on later references<<", N);
                Insert_Check := False;
 
             elsif Nkind (Unit_Declaration_Node (Orig_Ent)) /=
                     N_Subprogram_Renaming_Declaration
+              or else Is_Generic_Actual_Subprogram (Orig_Ent)
             then
                Error_Msg_NE
                  ("cannot call& before body seen<<", N, Orig_Ent);
-
-            elsif not Is_Generic_Actual_Subprogram (Orig_Ent) then
+            else
                Insert_Check := False;
             end if;
 
index ae7c5b7ac893f60b4ac8672dcbb56723de302315..66ad1e49f5a53f5768233ec563694304a690183b 100644 (file)
@@ -4143,11 +4143,11 @@ package body Sem_Res is
                         --  types.
 
                         if Is_By_Reference_Type (Etype (F))
-                           or else Is_By_Reference_Type (Expr_Typ)
+                          or else Is_By_Reference_Type (Expr_Typ)
                         then
                            Error_Msg_N
                              ("view conversion between unrelated by reference "
-                              & "array types not allowed (\'A'I-00246)", A);
+                              & "array types not allowed ('A'I-00246)", A);
 
                         --  In Ada 2005 mode, check view conversion component
                         --  type cannot be private, tagged, or volatile. Note
index b67bb7d5865668c1bccf97f365f0187ae5d407ca..89e5696ef014c500afb5a78dbf620666f4a0464e 100644 (file)
@@ -1416,8 +1416,14 @@ package body Sem_Warn is
                           and then not Warnings_Off_E1
                           and then not Has_Junk_Name (E1)
                         then
-                           Output_Reference_Error
-                             ("?v?variable& is read but never assigned!");
+                           if Is_Access_Type (E1T)
+                             or else
+                               not Is_Partially_Initialized_Type (E1T, False)
+                           then
+                              Output_Reference_Error
+                                ("?v?variable& is read but never assigned!");
+                           end if;
+
                            May_Need_Initialized_Actual (E1);
                         end if;
 
index 918981410e951f653149ca02947db3a528400b7f..e02e4260c45924da2213d7b3423540d852a0c283 100644 (file)
@@ -6,7 +6,7 @@ package body Opt11 is
    procedure Proc is
       R : Rec;
    begin
-      R := (others => <>);
+      R := (others => <>);  --  { dg-warning "aggregate not fully initialized" }
    end;
 
 end Opt11;