From: Eric Botcazou <ebotca...@adacore.com>

This extends the processing done for the Address aspect to other delayed
aspects.  The External_Name aspect is also reclassified as a representation
aspect and the three representation aspects External_Name, Link_Name and
Linker_Section are moved from the Always_Delay to the Rep_Aspect category,
which makes it possible not to delay them in most cases with a small tweak.

gcc/ada/ChangeLog:

        * aspects.ads (Is_Representation_Aspect): True for External_Name.
        (Aspect_Delay): Use Rep_Aspect for External_Name, Link_Name and
        Linker_Section.
        * einfo.ads (Initialization_Statements): Document extended usage.
        * exp_util.adb (Needs_Initialization_Statements): Return True for
        all delayed aspects.
        * freeze.adb (Check_Address_Clause): Do not move the initialization
        expression here...
        (Freeze_Object_Declaration): ...but here instead, as well as for all
        delayed aspects.  Remove test for pragma Linker_Section.
        * sem_ch13.adb (Analyze_One_Aspect): Do not delay in the Rep_Aspect
        case if the expression is a string literal.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/aspects.ads  |   8 +--
 gcc/ada/einfo.ads    |   6 +--
 gcc/ada/exp_util.adb |   2 +-
 gcc/ada/freeze.adb   | 119 +++++++++++++++++--------------------------
 gcc/ada/sem_ch13.adb |   5 +-
 5 files changed, 58 insertions(+), 82 deletions(-)

diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads
index ebf09602ea5..100ab4d55a8 100644
--- a/gcc/ada/aspects.ads
+++ b/gcc/ada/aspects.ads
@@ -543,7 +543,7 @@ package Aspects is
       Aspect_Exclusive_Functions          => False,
       Aspect_Extended_Access              => True,
       Aspect_External_Initialization      => False,
-      Aspect_External_Name                => False,
+      Aspect_External_Name                => True,
       Aspect_External_Tag                 => False,
       Aspect_Finalizable                  => False,
       Aspect_First_Controlling_Parameter  => False,
@@ -973,7 +973,6 @@ package Aspects is
       Aspect_Dynamic_Predicate            => Always_Delay,
       Aspect_Elaborate_Body               => Always_Delay,
       Aspect_Exclusive_Functions          => Always_Delay,
-      Aspect_External_Name                => Always_Delay,
       Aspect_External_Tag                 => Always_Delay,
       Aspect_Favor_Top_Level              => Always_Delay,
       Aspect_Finalizable                  => Always_Delay,
@@ -990,8 +989,6 @@ package Aspects is
       Aspect_Invariant                    => Always_Delay,
       Aspect_Iterable                     => Always_Delay,
       Aspect_Iterator_Element             => Always_Delay,
-      Aspect_Link_Name                    => Always_Delay,
-      Aspect_Linker_Section               => Always_Delay,
       Aspect_Lock_Free                    => Always_Delay,
       Aspect_No_Inline                    => Always_Delay,
       Aspect_No_Raise                     => Always_Delay,
@@ -1100,7 +1097,10 @@ package Aspects is
       Aspect_Bit_Order                    => Rep_Aspect,
       Aspect_Component_Size               => Rep_Aspect,
       Aspect_Extended_Access              => Rep_Aspect,
+      Aspect_External_Name                => Rep_Aspect,
       Aspect_Full_Access_Only             => Rep_Aspect,
+      Aspect_Link_Name                    => Rep_Aspect,
+      Aspect_Linker_Section               => Rep_Aspect,
       Aspect_Machine_Radix                => Rep_Aspect,
       Aspect_Object_Size                  => Rep_Aspect,
       Aspect_Pack                         => Rep_Aspect,
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index f929c26571d..1a8760c0dbb 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -2274,9 +2274,9 @@ package Einfo is
 --       source and initialized with an aggregate or a call expanded in place,
 --       points to a compound statement containing the assignment(s). This is
 --       used for a couple of purposes: 1) to defer the initialization to the
---       freeze point if an address aspect/clause is present for the object,
---       2) to cancel the initialization of imported objects generated by
---       Initialize_Scalars or Normalize_Scalars before the pragma Import is
+--       freeze point if an address clause or a delayed aspect is present for
+--       the object, 2) to cancel initialization of imported objects generated
+--       by Initialize_Scalars or Normalize_Scalars before the pragma Import is
 --       encountered for the object.
 
 --    Inner_Instances
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index dd284e2a20d..e9a683f8255 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -11700,7 +11700,7 @@ package body Exp_Util is
       --  See the documentation of Initialization_Statements in Einfo
 
       return Comes_From_Source (Decl)
-        and then (Has_Aspect (Obj_Id, Aspect_Address)
+        and then (Has_Delayed_Aspects (Obj_Id)
                    or else Present (Following_Address_Clause (Decl))
                    or else Init_Or_Norm_Scalars);
    end Needs_Initialization_Statements;
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index b2f1c3913a7..dae1d9afcde 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -98,8 +98,7 @@ package body Freeze is
 
    procedure Check_Address_Clause (E : Entity_Id);
    --  Apply legality checks to address clauses for object declarations,
-   --  at the point the object is frozen. Also ensure any initialization is
-   --  performed only after the object has been frozen.
+   --  at the point the object is frozen.
 
    procedure Check_Component_Storage_Order
      (Encl_Type        : Entity_Id;
@@ -636,11 +635,9 @@ package body Freeze is
       Addr       : constant Node_Id   := Address_Clause (E);
       Typ        : constant Entity_Id := Etype (E);
 
-      Assign : Node_Id;
-      Decl   : Node_Id;
-      Expr   : Node_Id;
-      Init   : Node_Id;
-      Lhs    : Node_Id;
+      Decl : Node_Id;
+      Expr : Node_Id;
+      Init : Node_Id;
 
    begin
       if Present (Addr) then
@@ -744,47 +741,6 @@ package body Freeze is
                end if;
             end;
          end if;
-
-         --  Remove side effects from initial expression, except in the case of
-         --  limited build-in-place calls and aggregates, which have their own
-         --  expansion elsewhere. This exception is necessary to avoid copying
-         --  limited objects.
-
-         if Present (Init)
-           and then not Is_Inherently_Limited_Type (Typ)
-         then
-            --  Capture initialization value at point of declaration, and make
-            --  explicit assignment legal, because object may be a constant.
-
-            Remove_Side_Effects (Init);
-            Lhs := New_Occurrence_Of (E, Sloc (Decl));
-            Set_Assignment_OK (Lhs);
-
-            Assign :=
-              Make_Assignment_Statement (Sloc (Decl),
-                Name       => Lhs,
-                Expression => Init);
-
-            Set_No_Initialization (Decl);
-
-            --  If the initialization expression is an aggregate, we do not
-            --  adjust after the assignment but, in either case, we do not
-            --  finalize before since the object is now uninitialized. Note
-            --  that Make_Tag_Ctrl_Assignment will also automatically insert
-            --  the tag assignment in the tagged case.
-
-            if Nkind (Unqualify (Init)) = N_Aggregate then
-               Set_No_Ctrl_Actions (Assign);
-            else
-               Set_No_Finalize_Actions (Assign);
-            end if;
-
-            --  Move initialization to freeze actions, once the object has
-            --  been frozen and the address clause alignment check has been
-            --  performed.
-
-            Append_Freeze_Action (E, Assign);
-         end if;
       end if;
    end Check_Address_Clause;
 
@@ -4229,6 +4185,8 @@ package body Freeze is
       -------------------------------
 
       procedure Freeze_Object_Declaration (E : Entity_Id) is
+         Decl : constant Node_Id := Declaration_Node (E);
+
          procedure Check_Large_Modular_Array (Typ : Entity_Id);
          --  Check that the size of array type Typ can be computed without
          --  overflow, and generates a Storage_Error otherwise. This is only
@@ -4307,11 +4265,11 @@ package body Freeze is
                                   Make_Itype_Reference (Obj_Loc);
                   begin
                      Set_Itype (Ref_Node, Etype (E));
-                     Insert_Action (Declaration_Node (E), Ref_Node);
+                     Insert_Action (Decl, Ref_Node);
                   end;
                end if;
 
-               Insert_Action (Declaration_Node (E),
+               Insert_Action (Decl,
                  Make_Raise_Storage_Error (Obj_Loc,
                    Condition =>
                      Make_Op_Ge (Obj_Loc,
@@ -4494,45 +4452,63 @@ package body Freeze is
          --  checks to freeze time since pragma Import inhibits default
          --  initialization and thus pragma Import affects these checks.
 
-         Validate_Object_Declaration (Declaration_Node (E));
+         Validate_Object_Declaration (Decl);
 
-         --  If there is an address clause, check that it is valid and if need
-         --  be move initialization to the freeze node.
+         --  If there is an address clause, check that it is valid
 
          Check_Address_Clause (E);
 
-         --  Similar processing is needed for aspects that may affect object
-         --  layout, like Address, if there is an initialization expression.
-         --  We don't do this if there is a pragma Linker_Section, because it
-         --  would prevent the back end from statically initializing the
-         --  object; we don't want elaboration code in that case.
+         --  If the object has an address clause or a delayed aspect, remove
+         --  the side effects from initial expression, except in the case of
+         --  limited build-in-place calls and aggregates, which have their own
+         --  expansion elsewhere. This exception is necessary to avoid copying
+         --  limited objects.
 
-         if Has_Delayed_Aspects (E)
-           and then Expander_Active
-           and then Is_Array_Type (Typ)
-           and then Present (Expression (Declaration_Node (E)))
-           and then No (Linker_Section_Pragma (E))
+         if Expander_Active
+           and then
+             (Present (Address_Clause (E)) or else Has_Delayed_Aspects (E))
+           and then Present (Expression (Decl))
+           and then not No_Initialization (Decl)
+           and then not Is_Inherently_Limited_Type (Typ)
          then
             declare
-               Decl : constant Node_Id := Declaration_Node (E);
+               Init : constant Node_Id := Expression (Decl);
                Lhs  : constant Node_Id := New_Occurrence_Of (E, Loc);
 
+               Assign : Node_Id;
+
             begin
                --  Capture initialization value at point of declaration, and
                --  make explicit assignment legal, because object may be a
                --  constant.
 
-               Remove_Side_Effects (Expression (Decl));
+               Remove_Side_Effects (Init);
                Set_Assignment_OK (Lhs);
 
-               --  Move initialization to freeze actions
-
-               Append_Freeze_Action (E,
-                 Make_Assignment_Statement (Loc,
+               Assign :=
+                 Make_Assignment_Statement (Sloc (Decl),
                    Name       => Lhs,
-                   Expression => Expression (Decl)));
+                   Expression => Init);
 
                Set_No_Initialization (Decl);
+
+               --  If the initialization expression is an aggregate, we do not
+               --  adjust after the assignment but, in either case, we do not
+               --  finalize before since the object is now uninitialized. Note
+               --  that Make_Tag_Ctrl_Assignment will also automatically insert
+               --  the tag assignment in the tagged case.
+
+               if Nkind (Unqualify (Init)) = N_Aggregate then
+                  Set_No_Ctrl_Actions (Assign);
+               else
+                  Set_No_Finalize_Actions (Assign);
+               end if;
+
+               --  Move initialization to freeze actions, once the object has
+               --  been frozen and the address clause alignment check has been
+               --  performed.
+
+               Append_Freeze_Action (E, Assign);
             end;
          end if;
 
@@ -4574,8 +4550,7 @@ package body Freeze is
             null;
 
          elsif Has_Default_Initialization (E) then
-            Check_Restriction
-              (No_Default_Initialization, Declaration_Node (E));
+            Check_Restriction (No_Default_Initialization, Decl);
          end if;
 
          --  Ensure that a variable subject to pragma Thread_Local_Storage
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 2d13ecc2f98..1a3a16ac9ee 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -2868,11 +2868,12 @@ package body Sem_Ch13 is
                   --  For non-Boolean aspects, if the expression has the form
                   --  of an integer literal, then do not delay, since we know
                   --  the value cannot change. This optimization catches most
-                  --  rep clause cases.
+                  --  rep clause cases. Likewise for a string literal.
 
                   elsif A_Id not in Boolean_Aspects
                     and then Present (Expr)
-                    and then Nkind (Expr) = N_Integer_Literal
+                    and then
+                      Nkind (Expr) in N_Integer_Literal | N_String_Literal
                   then
                      Delay_Required := False;
 
-- 
2.43.0

Reply via email to