From: Eric Botcazou Date: Wed, 14 Nov 2018 11:42:37 +0000 (+0000) Subject: [Ada] Fix small regression with others choice in array aggregate X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f1e2bf6571b64c39c1bd458b3a26f929a5f39ad9;p=gcc.git [Ada] Fix small regression with others choice in array aggregate This change is aimed at fixing a fallout of bumping the default value of the Max_Others_Replicate parameter of the Convert_To_Positional routine. This parameter is responsible for taming the duplication of the expression of an others choice in an array aggregate so that it doesn't result in a code size explosion. Unfortunately a fine-grained control based on the analysis of the expression is not really possible because this analysis has not been done yet by the time the decision is made in most cases, so the usual syntactic ambiguities of the language come into play and make the process a bit cumbersome. For example, it is not possible to distinguish a simple reference to a static constant declared in another unit from a call to a parameterless function. Therefore the change errs on the side of caution and allows the duplication only if the expression is unambiguously static and sufficiently simple. For the following three aggregates, the duplication must be blocked and the elaboration of the aggregates must be done by means of a loop: with Q; use Q; procedure P is A : Arr := (others => Get_Value); B : Arr := (others => Get_Other_Value (0)); C : Arr := (others => Q.Get_Other_Value (1)); begin null; end; package Q is type Arr is array (1 .. 32) of Integer; function Get_Value return Integer; function Get_Other_Value (I : integer) return Integer; end Q; 2018-11-14 Eric Botcazou gcc/ada/ * exp_aggr.adb (Is_Static_Element): New predicate extracted from... (Check_Static_Components): ...here. Call Is_Static_Element on each element of the component association list, if any. (Flatten): Duplicate the expression of an others choice only if it is static or is an aggregate which can itself be flattened. From-SVN: r266135 --- diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index d6881d93afb..776d0d92d7f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2018-11-14 Eric Botcazou + + * exp_aggr.adb (Is_Static_Element): New predicate extracted + from... + (Check_Static_Components): ...here. Call Is_Static_Element on + each element of the component association list, if any. + (Flatten): Duplicate the expression of an others choice only if + it is static or is an aggregate which can itself be flattened. + 2018-11-14 Olivier Hainque * sigtramp-vxworks-target.inc: Fix stack checking test errors in diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index 7fc7a87f91a..2eff7512c76 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -4302,8 +4302,6 @@ package body Exp_Aggr is -- Check whether all components of the aggregate are compile-time known -- values, and can be passed as is to the back-end without further -- expansion. - -- An Iterated_Component_Association is treated as nonstatic, but there - -- are possibilities for optimization here. function Flatten (N : Node_Id; @@ -4317,6 +4315,14 @@ package body Exp_Aggr is -- Return True iff the array N is flat (which is not trivial in the case -- of multidimensional aggregates). + function Is_Static_Element (N : Node_Id) return Boolean; + -- Return True if N, an element of a component association list, i.e. + -- N_Component_Association or N_Iterated_Component_Association, has a + -- compile-time known value and can be passed as is to the back-end + -- without further expansion. + -- An Iterated_Component_Association is treated as nonstatic in most + -- cases for now, so there are possibilities for optimization. + ----------------------------- -- Check_Static_Components -- ----------------------------- @@ -4324,7 +4330,8 @@ package body Exp_Aggr is -- Could use some comments in this body ??? procedure Check_Static_Components is - Expr : Node_Id; + Assoc : Node_Id; + Expr : Node_Id; begin Static_Components := True; @@ -4350,30 +4357,14 @@ package body Exp_Aggr is if Nkind (N) = N_Aggregate and then Present (Component_Associations (N)) then - Expr := First (Component_Associations (N)); - while Present (Expr) loop - if Nkind_In (Expression (Expr), N_Integer_Literal, - N_Real_Literal) - then - null; - - elsif Is_Entity_Name (Expression (Expr)) - and then Present (Entity (Expression (Expr))) - and then Ekind (Entity (Expression (Expr))) = - E_Enumeration_Literal - then - null; - - elsif Nkind (Expression (Expr)) /= N_Aggregate - or else not Compile_Time_Known_Aggregate (Expression (Expr)) - or else Expansion_Delayed (Expression (Expr)) - or else Nkind (Expr) = N_Iterated_Component_Association - then + Assoc := First (Component_Associations (N)); + while Present (Assoc) loop + if not Is_Static_Element (Assoc) then Static_Components := False; exit; end if; - Next (Expr); + Next (Assoc); end loop; end if; end Check_Static_Components; @@ -4553,8 +4544,8 @@ package body Exp_Aggr is Cunit_Entity (Current_Sem_Unit); begin - -- Check if duplication OK and if so continue - -- processing. + -- Check if duplication is always OK and, if so, + -- continue processing. if Restriction_Active (No_Elaboration_Code) or else Restriction_Active (No_Implicit_Loops) @@ -4571,17 +4562,23 @@ package body Exp_Aggr is then null; - -- If duplication not OK, then we return False - -- if the replication count is too high + -- If duplication is not always OK, continue + -- only if either the element is static or is + -- an aggregate which can itself be flattened, + -- and the replication count is not too high. - elsif Rep_Count > Max_Others_Replicate then - return False; + elsif (Is_Static_Element (Elmt) + or else + (Nkind (Expression (Elmt)) = N_Aggregate + and then Present (Next_Index (Ix)))) + and then Rep_Count <= Max_Others_Replicate + then + null; - -- Continue on if duplication not OK, but the - -- replication count is not excessive. + -- Return False in all the other cases else - null; + return False; end if; end; end if; @@ -4706,6 +4703,37 @@ package body Exp_Aggr is end if; end Is_Flat; + ------------------------- + -- Is_Static_Element -- + ------------------------- + + function Is_Static_Element (N : Node_Id) return Boolean is + Expr : constant Node_Id := Expression (N); + + begin + if Nkind_In (Expr, N_Integer_Literal, N_Real_Literal) then + return True; + + elsif Is_Entity_Name (Expr) + and then Present (Entity (Expr)) + and then Ekind (Entity (Expr)) = E_Enumeration_Literal + then + return True; + + elsif Nkind (N) = N_Iterated_Component_Association then + return False; + + elsif Nkind (Expr) = N_Aggregate + and then Compile_Time_Known_Aggregate (Expr) + and then not Expansion_Delayed (Expr) + then + return True; + + else + return False; + end if; + end Is_Static_Element; + -- Start of processing for Convert_To_Positional begin