aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/exp_util.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/exp_util.adb')
-rw-r--r--gcc/ada/exp_util.adb537
1 files changed, 253 insertions, 284 deletions
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 7bd90e7..0f8505f 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2019, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -224,6 +224,10 @@ package body Exp_Util is
-- level, and False otherwise. Nested_Constructs is True when any nested
-- packages declared in L must be processed, and False otherwise.
+ function Side_Effect_Free_Attribute (Name : Name_Id) return Boolean;
+ -- Return True if the evaluation of the given attribute is considered
+ -- side-effect free, independently of its prefix and expressions.
+
-------------------------------------
-- Activate_Atomic_Synchronization --
-------------------------------------
@@ -1292,6 +1296,7 @@ package body Exp_Util is
-- of the type. In the case of an inherited condition for an
-- overriding operation, both the operation and the function
-- are given by primitive wrappers.
+ -- Move this check to sem???
if Ekind (New_E) = E_Function
and then Is_Primitive_Wrapper (New_E)
@@ -1322,6 +1327,7 @@ package body Exp_Util is
-- Check that there are no calls left to abstract operations if
-- the current subprogram is not abstract.
+ -- Move this check to sem???
if Nkind (Parent (N)) = N_Function_Call
and then N = Name (Parent (N))
@@ -1634,43 +1640,6 @@ package body Exp_Util is
DIC_Proc : constant Entity_Id := DIC_Procedure (DIC_Typ);
Obj_Id : constant Entity_Id := First_Formal (DIC_Proc);
- procedure Preanalyze_Own_DIC_For_ASIS;
- -- Preanalyze the original DIC expression of an aspect or a source
- -- pragma for ASIS.
-
- ---------------------------------
- -- Preanalyze_Own_DIC_For_ASIS --
- ---------------------------------
-
- procedure Preanalyze_Own_DIC_For_ASIS is
- Expr : Node_Id := Empty;
-
- begin
- -- The DIC pragma is a source construct, preanalyze the original
- -- expression of the pragma.
-
- if Comes_From_Source (DIC_Prag) then
- Expr := DIC_Expr;
-
- -- Otherwise preanalyze the expression of the corresponding aspect
-
- elsif Present (DIC_Asp) then
- Expr := Expression (DIC_Asp);
- end if;
-
- -- The expression must be subjected to the same substitutions as
- -- the copy used in the generation of the runtime check.
-
- if Present (Expr) then
- Replace_Type_References
- (Expr => Expr,
- Typ => DIC_Typ,
- Obj_Id => Obj_Id);
-
- Preanalyze_Assert_Expression (Expr, Any_Boolean);
- end if;
- end Preanalyze_Own_DIC_For_ASIS;
-
-- Local variables
Typ_Decl : constant Node_Id := Declaration_Node (DIC_Typ);
@@ -1717,12 +1686,6 @@ package body Exp_Util is
Set_Entity (Identifier (DIC_Asp), New_Copy_Tree (Expr));
end if;
- -- Preanalyze the original DIC expression for ASIS
-
- if ASIS_Mode then
- Preanalyze_Own_DIC_For_ASIS;
- end if;
-
-- Once the DIC assertion expression is fully processed, add a check
-- to the statements of the DIC procedure.
@@ -1951,11 +1914,11 @@ package body Exp_Util is
Set_Corresponding_Spec (Proc_Body, Proc_Id);
-- The body should not be inserted into the tree when the context
- -- is ASIS or a generic unit because it is not part of the template.
+ -- is a generic unit because it is not part of the template.
-- Note that the body must still be generated in order to resolve the
-- DIC assertion expression.
- if ASIS_Mode or Inside_A_Generic then
+ if Inside_A_Generic then
null;
-- Semi-insert the body into the tree for GNATprove by setting its
@@ -2000,9 +1963,6 @@ package body Exp_Util is
CRec_Typ : Entity_Id;
-- The corresponding record type of Full_Typ
- Full_Base : Entity_Id;
- -- The base type of Full_Typ
-
Full_Typ : Entity_Id;
-- The full view of working type
@@ -2012,6 +1972,9 @@ package body Exp_Util is
Priv_Typ : Entity_Id;
-- The partial view of working type
+ UFull_Typ : Entity_Id;
+ -- The underlying full view of Full_Typ
+
Work_Typ : Entity_Id;
-- The working type
@@ -2102,13 +2065,13 @@ package body Exp_Util is
-- Obtain all views of the input type
- Get_Views (Work_Typ, Priv_Typ, Full_Typ, Full_Base, CRec_Typ);
+ Get_Views (Work_Typ, Priv_Typ, Full_Typ, UFull_Typ, CRec_Typ);
- -- Associate the DIC procedure and various relevant flags with all views
+ -- Associate the DIC procedure and various flags with all views
Propagate_DIC_Attributes (Priv_Typ, From_Typ => Work_Typ);
Propagate_DIC_Attributes (Full_Typ, From_Typ => Work_Typ);
- Propagate_DIC_Attributes (Full_Base, From_Typ => Work_Typ);
+ Propagate_DIC_Attributes (UFull_Typ, From_Typ => Work_Typ);
Propagate_DIC_Attributes (CRec_Typ, From_Typ => Work_Typ);
-- The declaration of the DIC procedure must be inserted after the
@@ -2158,9 +2121,9 @@ package body Exp_Util is
New_Occurrence_Of (Work_Typ, Loc)))));
-- The declaration should not be inserted into the tree when the context
- -- is ASIS or a generic unit because it is not part of the template.
+ -- is a generic unit because it is not part of the template.
- if ASIS_Mode or Inside_A_Generic then
+ if Inside_A_Generic then
null;
-- Semi-insert the declaration into the tree for GNATprove by setting
@@ -2335,9 +2298,8 @@ package body Exp_Util is
-- Generate:
-- <Comp_Typ>Invariant (_object (<Indices>));
- -- Note that the invariant procedure may have a null body if
- -- assertions are disabled or Assertion_Policy Ignore is in
- -- effect.
+ -- The invariant procedure has a null body if assertions are
+ -- disabled or Assertion_Policy Ignore is in effect.
if not Has_Null_Body (Proc_Id) then
Append_New_To (Comp_Checks,
@@ -2775,7 +2737,6 @@ package body Exp_Util is
Checks : in out List_Id;
Priv_Item : Node_Id := Empty)
is
- ASIS_Expr : Node_Id;
Expr : Node_Id;
Prag : Node_Id;
Prag_Asp : Node_Id;
@@ -2854,23 +2815,6 @@ package body Exp_Util is
Set_Entity (Identifier (Prag_Asp), New_Copy_Tree (Expr));
end if;
- -- Analyze the original invariant expression for ASIS
-
- if ASIS_Mode then
- ASIS_Expr := Empty;
-
- if Comes_From_Source (Prag) then
- ASIS_Expr := Prag_Expr;
- elsif Present (Prag_Asp) then
- ASIS_Expr := Expression (Prag_Asp);
- end if;
-
- if Present (ASIS_Expr) then
- Replace_Type_References (ASIS_Expr, T, Obj_Id);
- Preanalyze_Assert_Expression (ASIS_Expr, Any_Boolean);
- end if;
- end if;
-
Add_Invariant_Check (Prag, Expr, Checks);
end if;
@@ -3069,7 +3013,7 @@ package body Exp_Util is
if Produced_Component_Check and then Has_Unchecked_Union (T) then
Error_Msg_NE
("invariants cannot be checked on components of "
- & "unchecked_union type &?", Comp_Id, T);
+ & "unchecked_union type &??", Comp_Id, T);
end if;
end Process_Record_Component;
@@ -3144,11 +3088,18 @@ package body Exp_Util is
begin
Work_Typ := Typ;
+ -- Do not process the underlying full view of a private type. There is
+ -- no way to get back to the partial view, plus the body will be built
+ -- by the full view or the base type.
+
+ if Is_Underlying_Full_View (Work_Typ) then
+ return;
+
-- The input type denotes the implementation base type of a constrained
-- array type. Work with the first subtype as all invariant pragmas are
-- on its rep item chain.
- if Ekind (Work_Typ) = E_Array_Type and then Is_Itype (Work_Typ) then
+ elsif Ekind (Work_Typ) = E_Array_Type and then Is_Itype (Work_Typ) then
Work_Typ := First_Subtype (Work_Typ);
-- The input type denotes the corresponding record type of a protected
@@ -3428,11 +3379,11 @@ package body Exp_Util is
Set_Corresponding_Spec (Proc_Body, Proc_Id);
-- The body should not be inserted into the tree when the context is
- -- ASIS or a generic unit because it is not part of the template. Note
+ -- a generic unit because it is not part of the template. Note
-- that the body must still be generated in order to resolve the
-- invariants.
- if ASIS_Mode or Inside_A_Generic then
+ if Inside_A_Generic then
null;
-- Semi-insert the body into the tree for GNATprove by setting its
@@ -3477,9 +3428,6 @@ package body Exp_Util is
CRec_Typ : Entity_Id;
-- The corresponding record type of Full_Typ
- Full_Base : Entity_Id;
- -- The base type of Full_Typ
-
Full_Typ : Entity_Id;
-- The full view of working type
@@ -3492,6 +3440,9 @@ package body Exp_Util is
Priv_Typ : Entity_Id;
-- The partial view of working type
+ UFull_Typ : Entity_Id;
+ -- The underlying full view of Full_Typ
+
Work_Typ : Entity_Id;
-- The working type
@@ -3577,13 +3528,13 @@ package body Exp_Util is
-- Obtain all views of the input type
- Get_Views (Work_Typ, Priv_Typ, Full_Typ, Full_Base, CRec_Typ);
+ Get_Views (Work_Typ, Priv_Typ, Full_Typ, UFull_Typ, CRec_Typ);
- -- Associate the invariant procedure with all views
+ -- Associate the invariant procedure and various flags with all views
Propagate_Invariant_Attributes (Priv_Typ, From_Typ => Work_Typ);
Propagate_Invariant_Attributes (Full_Typ, From_Typ => Work_Typ);
- Propagate_Invariant_Attributes (Full_Base, From_Typ => Work_Typ);
+ Propagate_Invariant_Attributes (UFull_Typ, From_Typ => Work_Typ);
Propagate_Invariant_Attributes (CRec_Typ, From_Typ => Work_Typ);
-- The declaration of the invariant procedure is inserted after the
@@ -3663,9 +3614,9 @@ package body Exp_Util is
Parameter_Type => New_Occurrence_Of (Obj_Typ, Loc)))));
-- The declaration should not be inserted into the tree when the context
- -- is ASIS or a generic unit because it is not part of the template.
+ -- is a generic unit because it is not part of the template.
- if ASIS_Mode or Inside_A_Generic then
+ if Inside_A_Generic then
null;
-- Semi-insert the declaration into the tree for GNATprove by setting
@@ -4967,11 +4918,16 @@ package body Exp_Util is
procedure Evaluate_Name (Nam : Node_Id) is
begin
- -- For an attribute reference or an indexed component, evaluate the
- -- prefix, which is itself a name, recursively, and then force the
- -- evaluation of all the subscripts (or attribute expressions).
-
case Nkind (Nam) is
+ -- For an aggregate, force its evaluation
+
+ when N_Aggregate =>
+ Force_Evaluation (Nam);
+
+ -- For an attribute reference or an indexed component, evaluate the
+ -- prefix, which is itself a name, recursively, and then force the
+ -- evaluation of all the subscripts (or attribute expressions).
+
when N_Attribute_Reference
| N_Indexed_Component
=>
@@ -5002,21 +4958,17 @@ package body Exp_Util is
when N_Explicit_Dereference =>
Force_Evaluation (Prefix (Nam));
- -- For a function call, we evaluate the call
+ -- For a function call, we evaluate the call; same for an operator
- when N_Function_Call =>
+ when N_Function_Call
+ | N_Op
+ =>
Force_Evaluation (Nam);
- -- For a qualified expression, we evaluate the underlying object
- -- name if any, otherwise we force the evaluation of the underlying
- -- expression.
+ -- For a qualified expression, we evaluate the expression
when N_Qualified_Expression =>
- if Is_Object_Reference (Expression (Nam)) then
- Evaluate_Name (Expression (Nam));
- else
- Force_Evaluation (Expression (Nam));
- end if;
+ Evaluate_Name (Expression (Nam));
-- For a selected component, we simply evaluate the prefix
@@ -5038,9 +4990,11 @@ package body Exp_Util is
when N_Type_Conversion =>
Evaluate_Name (Expression (Nam));
- -- The remaining cases are direct name, operator symbol and character
- -- literal. In all these cases, we do nothing, since we want to
- -- reevaluate each time the renamed object is used.
+ -- The remaining cases are direct name and character literal. In all
+ -- these cases, we do nothing, since we want to reevaluate each time
+ -- the renamed object is used. ??? There are more remaining cases, at
+ -- least in the GNATprove_Mode, where this routine is called in more
+ -- contexts than in GNAT.
when others =>
null;
@@ -5110,7 +5064,7 @@ package body Exp_Util is
-----------------------------------------
procedure Expand_Static_Predicates_In_Choices (N : Node_Id) is
- pragma Assert (Nkind_In (N, N_Case_Statement_Alternative, N_Variant));
+ pragma Assert (Nkind (N) in N_Case_Statement_Alternative | N_Variant);
Choices : constant List_Id := Discrete_Choices (N);
@@ -5888,7 +5842,7 @@ package body Exp_Util is
begin
S := Scop;
while Present (S) loop
- if Ekind_In (S, E_Entry, E_Entry_Family, E_Function, E_Procedure)
+ if Ekind (S) in E_Entry | E_Entry_Family | E_Function | E_Procedure
and then Present (Protection_Object (S))
then
return Protection_Object (S);
@@ -5966,8 +5920,8 @@ package body Exp_Util is
Par := N;
Top := N;
while Present (Par) loop
- if Nkind_In (Original_Node (Par), N_Case_Expression,
- N_If_Expression)
+ if Nkind (Original_Node (Par)) in
+ N_Case_Expression | N_If_Expression
then
Top := Par;
@@ -5988,13 +5942,13 @@ package body Exp_Util is
Par := Top;
while Present (Par) loop
if Is_List_Member (Par)
- and then not Nkind_In (Par, N_Component_Association,
- N_Discriminant_Association,
- N_Parameter_Association,
- N_Pragma_Argument_Association)
- and then not Nkind_In (Parent (Par), N_Function_Call,
- N_Procedure_Call_Statement,
- N_Entry_Call_Statement)
+ and then Nkind (Par) not in N_Component_Association
+ | N_Discriminant_Association
+ | N_Parameter_Association
+ | N_Pragma_Argument_Association
+ and then Nkind (Parent (Par)) not in N_Function_Call
+ | N_Procedure_Call_Statement
+ | N_Entry_Call_Statement
then
return Par;
@@ -6017,7 +5971,7 @@ package body Exp_Util is
-- Keep climbing past various operators
if Nkind (Parent (Par)) in N_Op
- or else Nkind_In (Parent (Par), N_And_Then, N_Or_Else)
+ or else Nkind (Parent (Par)) in N_And_Then | N_Or_Else
then
Par := Parent (Par);
else
@@ -6055,11 +6009,11 @@ package body Exp_Util is
while Present (Par) loop
if Par = Wrapped_Node
- or else Nkind_In (Par, N_Assignment_Statement,
- N_Object_Declaration,
- N_Pragma,
- N_Procedure_Call_Statement,
- N_Simple_Return_Statement)
+ or else Nkind (Par) in N_Assignment_Statement
+ | N_Object_Declaration
+ | N_Pragma
+ | N_Procedure_Call_Statement
+ | N_Simple_Return_Statement
then
return Par;
@@ -6322,10 +6276,9 @@ package body Exp_Util is
-- Deal with conversions, qualifications, and expressions with
-- actions.
- while Nkind_In (Cond,
- N_Type_Conversion,
- N_Qualified_Expression,
- N_Expression_With_Actions)
+ while Nkind (Cond) in N_Type_Conversion
+ | N_Qualified_Expression
+ | N_Expression_With_Actions
loop
Cond := Expression (Cond);
end loop;
@@ -6335,7 +6288,7 @@ package body Exp_Util is
-- Deal with AND THEN and AND cases
- if Nkind_In (Cond, N_And_Then, N_Op_And) then
+ if Nkind (Cond) in N_And_Then | N_Op_And then
-- Don't ever try to invert a condition that is of the form of an
-- AND or AND THEN (since we are not doing sufficiently general
@@ -6411,10 +6364,9 @@ package body Exp_Util is
return;
- elsif Nkind_In (Cond,
- N_Type_Conversion,
- N_Qualified_Expression,
- N_Expression_With_Actions)
+ elsif Nkind (Cond) in N_Type_Conversion
+ | N_Qualified_Expression
+ | N_Expression_With_Actions
then
Cond := Expression (Cond);
@@ -6442,7 +6394,7 @@ package body Exp_Util is
-- Immediate return, nothing doing, if this is not an object
- if Ekind (Ent) not in Object_Kind then
+ if not Is_Object (Ent) then
return;
end if;
@@ -6464,7 +6416,7 @@ package body Exp_Util is
if Loc < Sloc (CV) then
return;
- -- After end of IF statement
+ -- After end of IF statement
elsif Loc >= Sloc (CV) + Text_Ptr (UI_To_Int (End_Span (CV))) then
return;
@@ -6632,6 +6584,35 @@ package body Exp_Util is
end;
end Get_Current_Value_Condition;
+ -----------------------
+ -- Get_Index_Subtype --
+ -----------------------
+
+ function Get_Index_Subtype (N : Node_Id) return Node_Id is
+ P_Type : Entity_Id := Etype (Prefix (N));
+ Indx : Node_Id;
+ J : Int;
+
+ begin
+ if Is_Access_Type (P_Type) then
+ P_Type := Designated_Type (P_Type);
+ end if;
+
+ if No (Expressions (N)) then
+ J := 1;
+ else
+ J := UI_To_Int (Expr_Value (First (Expressions (N))));
+ end if;
+
+ Indx := First_Index (P_Type);
+ while J > 1 loop
+ Next_Index (Indx);
+ J := J - 1;
+ end loop;
+
+ return Etype (Indx);
+ end Get_Index_Subtype;
+
---------------------
-- Get_Stream_Size --
---------------------
@@ -7282,7 +7263,7 @@ package body Exp_Util is
-- actions should be inserted outside the complete record
-- declaration.
- elsif Nkind_In (Parent (P), N_Variant, N_Record_Definition) then
+ elsif Nkind (Parent (P)) in N_Variant | N_Record_Definition then
null;
-- Do not insert freeze nodes within the loop generated for
@@ -7363,6 +7344,7 @@ package body Exp_Util is
when N_Component_Association
| N_Iterated_Component_Association
+ | N_Iterated_Element_Association
=>
if Nkind (Parent (P)) = N_Aggregate
and then Present (Loop_Actions (P))
@@ -7669,8 +7651,8 @@ package body Exp_Util is
P := Parent (P);
if Is_List_Member (P) then
- exit when Nkind_In (Parent (P), N_Package_Specification,
- N_Subprogram_Body);
+ exit when Nkind (Parent (P)) in
+ N_Package_Specification | N_Subprogram_Body;
-- Special handling for handled sequence of statements, we must
-- insert in the statements not the exception handlers!
@@ -7890,8 +7872,8 @@ package body Exp_Util is
if Nkind (Result) = N_Explicit_Dereference then
Result := Prefix (Result);
- elsif Nkind_In (Result, N_Type_Conversion,
- N_Unchecked_Type_Conversion)
+ elsif Nkind (Result) in
+ N_Type_Conversion | N_Unchecked_Type_Conversion
then
Result := Expression (Result);
@@ -8141,7 +8123,7 @@ package body Exp_Util is
if Nkind (N) = N_Identifier
and then Present (Entity (N))
- and then Ekind_In (Entity (N), E_Constant, E_Variable)
+ and then Ekind (Entity (N)) in E_Constant | E_Variable
then
Ren_Obj := Entity (N);
return Abandon;
@@ -8348,7 +8330,7 @@ package body Exp_Util is
end if;
return
- Ekind_In (Obj_Id, E_Constant, E_Variable)
+ Ekind (Obj_Id) in E_Constant | E_Variable
and then Needs_Finalization (Desig)
and then Requires_Transient_Scope (Desig)
and then Nkind (Rel_Node) /= N_Simple_Return_Statement
@@ -8774,7 +8756,7 @@ package body Exp_Util is
return Is_Ref_To_Bit_Packed_Array (Renamed_Object (Entity (N)));
end if;
- if Nkind_In (N, N_Indexed_Component, N_Selected_Component) then
+ if Nkind (N) in N_Indexed_Component | N_Selected_Component then
if Is_Bit_Packed_Array (Etype (Prefix (N))) then
Result := True;
else
@@ -8816,7 +8798,7 @@ package body Exp_Util is
then
return True;
- elsif Nkind_In (N, N_Indexed_Component, N_Selected_Component) then
+ elsif Nkind (N) in N_Indexed_Component | N_Selected_Component then
return Is_Ref_To_Bit_Packed_Slice (Prefix (N));
else
@@ -8834,7 +8816,7 @@ package body Exp_Util is
begin
if Kind = N_Object_Renaming_Declaration then
return True;
- elsif Nkind_In (Kind, N_Indexed_Component, N_Selected_Component) then
+ elsif Kind in N_Indexed_Component | N_Selected_Component then
return Is_Renamed_Object (Pnod);
else
return False;
@@ -8846,7 +8828,6 @@ package body Exp_Util is
--------------------------------------
function Is_Secondary_Stack_BIP_Func_Call (Expr : Node_Id) return Boolean is
- Alloc_Nam : Name_Id := No_Name;
Actual : Node_Id;
Call : Node_Id := Expr;
Formal : Node_Id;
@@ -8873,20 +8854,10 @@ package body Exp_Util is
Formal := Selector_Name (Param);
Actual := Explicit_Actual_Parameter (Param);
- -- Construct the name of formal BIPalloc. It is much easier to
- -- extract the name of the function using an arbitrary formal's
- -- scope rather than the Name field of Call.
-
- if Alloc_Nam = No_Name and then Present (Entity (Formal)) then
- Alloc_Nam :=
- New_External_Name
- (Chars (Scope (Entity (Formal))),
- BIP_Formal_Suffix (BIP_Alloc_Form));
- end if;
-
-- A match for BIPalloc => 2 has been found
- if Chars (Formal) = Alloc_Nam
+ if Is_Build_In_Place_Entity (Formal)
+ and then BIP_Suffix_Kind (Formal) = BIP_Alloc_Form
and then Nkind (Actual) = N_Integer_Literal
and then Intval (Actual) = Uint_2
then
@@ -9003,7 +8974,7 @@ package body Exp_Util is
-- True if volatile component
- elsif Nkind_In (N, N_Indexed_Component, N_Selected_Component) then
+ elsif Nkind (N) in N_Indexed_Component | N_Selected_Component then
if (Is_Entity_Name (Prefix (N))
and then Has_Volatile_Components (Entity (Prefix (N))))
or else (Present (Etype (Prefix (N)))
@@ -9379,18 +9350,15 @@ package body Exp_Util is
function Make_Invariant_Call (Expr : Node_Id) return Node_Id is
Loc : constant Source_Ptr := Sloc (Expr);
Typ : constant Entity_Id := Base_Type (Etype (Expr));
-
- Proc_Id : Entity_Id;
-
- begin
pragma Assert (Has_Invariants (Typ));
-
- Proc_Id := Invariant_Procedure (Typ);
+ Proc_Id : constant Entity_Id := Invariant_Procedure (Typ);
pragma Assert (Present (Proc_Id));
+ begin
+ -- The invariant procedure has a null body if assertions are disabled or
+ -- Assertion_Policy Ignore is in effect. In that case, generate a null
+ -- statement instead of a call to the invariant procedure.
- -- Ignore the invariant if that policy is in effect
-
- if Invariants_Ignored (Typ) then
+ if Has_Null_Body (Proc_Id) then
return Make_Null_Statement (Loc);
else
return
@@ -9606,7 +9574,7 @@ package body Exp_Util is
(Next (First (Pragma_Argument_Associations (Item))));
end if;
- Item := Next_Rep_Item (Item);
+ Next_Rep_Item (Item);
end loop;
return Empty;
@@ -9666,11 +9634,6 @@ package body Exp_Util is
procedure Replace_Subtype_Reference (N : Node_Id) is
begin
Rewrite (N, New_Copy_Tree (Expr));
-
- -- We want to treat the node as if it comes from source, so that
- -- ASIS will not ignore it.
-
- Set_Comes_From_Source (N, True);
end Replace_Subtype_Reference;
procedure Replace_Subtype_References is
@@ -9717,10 +9680,9 @@ package body Exp_Util is
return Make_Null_Statement (Loc);
end if;
- -- Do not generate a check within an internal subprogram (stream
- -- functions and the like, including predicate functions).
+ -- Do not generate a check within stream functions and the like.
- if Within_Internal_Subprogram then
+ if not Predicate_Check_In_Scope (Expr) then
return Make_Null_Statement (Loc);
end if;
@@ -9896,7 +9858,7 @@ package body Exp_Util is
Low_Bound => New_Occurrence_Of (Low_Bound, Loc),
High_Bound => New_Occurrence_Of (High_Bound, Loc)));
- Index_Typ := Next_Index (Index_Typ);
+ Next_Index (Index_Typ);
end loop;
elsif Is_Class_Wide_Type (Unc_Typ) then
@@ -11041,7 +11003,7 @@ package body Exp_Util is
=>
-- Check the "then statements" for elsif parts and if statements
- if Nkind_In (N, N_Elsif_Part, N_If_Statement)
+ if Nkind (N) in N_Elsif_Part | N_If_Statement
and then not Is_Empty_List (Then_Statements (N))
and then not Are_Wrapped (Then_Statements (N))
and then Requires_Cleanup_Actions
@@ -11058,9 +11020,8 @@ package body Exp_Util is
-- Check the "else statements" for conditional entry calls, if
-- statements and selective accepts.
- if Nkind_In (N, N_Conditional_Entry_Call,
- N_If_Statement,
- N_Selective_Accept)
+ if Nkind (N) in
+ N_Conditional_Entry_Call | N_If_Statement | N_Selective_Accept
and then not Is_Empty_List (Else_Statements (N))
and then not Are_Wrapped (Else_Statements (N))
and then Requires_Cleanup_Actions
@@ -11372,6 +11333,21 @@ package body Exp_Util is
Scope_Suppress.Suppress := (others => True);
+ -- If this is a side-effect free attribute reference whose expressions
+ -- are also side-effect free and whose prefix is not a name, remove the
+ -- side effects of the prefix. A copy of the prefix is required in this
+ -- case and it is better not to make an additional one for the attribute
+ -- itself, because the return type of many of them is universal integer,
+ -- which is a very large type for a temporary.
+
+ if Nkind (Exp) = N_Attribute_Reference
+ and then Side_Effect_Free_Attribute (Attribute_Name (Exp))
+ and then Side_Effect_Free (Expressions (Exp), Name_Req, Variable_Ref)
+ and then not Is_Name_Reference (Prefix (Exp))
+ then
+ Remove_Side_Effects (Prefix (Exp), Name_Req, Variable_Ref);
+ goto Leave;
+
-- If this is an elementary or a small not-by-reference record type, and
-- we need to capture the value, just make a constant; this is cheap and
-- objects of both kinds of types can be bit aligned, so it might not be
@@ -11382,12 +11358,12 @@ package body Exp_Util is
-- anyway, see below). Also do it if we have a volatile reference and
-- Name_Req is not set (see comments for Side_Effect_Free).
- if (Is_Elementary_Type (Exp_Type)
- or else (Is_Record_Type (Exp_Type)
- and then Known_Static_RM_Size (Exp_Type)
- and then RM_Size (Exp_Type) <= 64
- and then not Has_Discriminants (Exp_Type)
- and then not Is_By_Reference_Type (Exp_Type)))
+ elsif (Is_Elementary_Type (Exp_Type)
+ or else (Is_Record_Type (Exp_Type)
+ and then Known_Static_RM_Size (Exp_Type)
+ and then RM_Size (Exp_Type) <= 64
+ and then not Has_Discriminants (Exp_Type)
+ and then not Is_By_Reference_Type (Exp_Type)))
and then (Variable_Ref
or else (not Is_Name_Reference (Exp)
and then Nkind (Exp) /= N_Type_Conversion)
@@ -11475,12 +11451,15 @@ package body Exp_Util is
goto Leave;
-- If this is a type conversion, leave the type conversion and remove
- -- the side effects in the expression. This is important in several
- -- circumstances: for change of representations, and also when this is a
- -- view conversion to a smaller object, where gigi can end up creating
- -- its own temporary of the wrong size.
-
- elsif Nkind (Exp) = N_Type_Conversion then
+ -- side effects in the expression, unless it is of universal integer,
+ -- which is a very large type for a temporary. This is important in
+ -- several circumstances: for change of representations and also when
+ -- this is a view conversion to a smaller object, where gigi can end
+ -- up creating its own temporary of the wrong size.
+
+ elsif Nkind (Exp) = N_Type_Conversion
+ and then Etype (Expression (Exp)) /= Universal_Integer
+ then
Remove_Side_Effects (Expression (Exp), Name_Req, Variable_Ref);
-- Generating C code the type conversion of an access to constrained
@@ -11574,7 +11553,7 @@ package body Exp_Util is
-- by the expression it renames, which would defeat the purpose of
-- removing the side effect.
- if Nkind_In (Exp, N_Selected_Component, N_Indexed_Component)
+ if Nkind (Exp) in N_Selected_Component | N_Indexed_Component
and then Has_Non_Standard_Rep (Etype (Prefix (Exp)))
then
null;
@@ -12001,8 +11980,8 @@ package body Exp_Util is
-- and view swaps, the parent type is taken from the formal
-- parameter of the subprogram being called.
- if Nkind_In (Context, N_Function_Call,
- N_Procedure_Call_Statement)
+ if Nkind (Context) in
+ N_Function_Call | N_Procedure_Call_Statement
and then No (Type_Map.Get (Entity (Name (Context))))
then
New_Ref :=
@@ -12117,13 +12096,8 @@ package body Exp_Util is
procedure Replace_Type_Ref (N : Node_Id) is
begin
-- Decorate the reference to Typ even though it may be rewritten
- -- further down. This is done for two reasons:
-
- -- * ASIS has all necessary semantic information in the original
- -- tree.
-
- -- * Routines which examine properties of the Original_Node have
- -- some semantic information.
+ -- further down. This is done so that routines which examine
+ -- properties of the Original_Node have some semantic information.
if Nkind (N) = N_Identifier then
Set_Entity (N, Typ);
@@ -12173,9 +12147,8 @@ package body Exp_Util is
Lib_Level : Boolean) return Boolean
is
At_Lib_Level : constant Boolean :=
- Lib_Level
- and then Nkind_In (N, N_Package_Body,
- N_Package_Specification);
+ Lib_Level
+ and then Nkind (N) in N_Package_Body | N_Package_Specification;
-- N is at the library level if the top-most context is a package and
-- the path taken to reach N does not include nonpackage constructs.
@@ -12552,8 +12525,8 @@ package body Exp_Util is
if (Nkind (Pexp) = N_Assignment_Statement
and then Expression (Pexp) = Exp)
- or else Nkind_In (Pexp, N_Object_Declaration,
- N_Object_Renaming_Declaration)
+ or else Nkind (Pexp)
+ in N_Object_Declaration | N_Object_Renaming_Declaration
then
return True;
@@ -12566,13 +12539,10 @@ package body Exp_Util is
elsif Nkind (Pexp) = N_Selected_Component
and then Prefix (Pexp) = Exp
then
- if No (Etype (Pexp)) then
- return True;
- else
- return
- not Has_Discriminants (Etype (Pexp))
- or else Is_Constrained (Etype (Pexp));
- end if;
+ return No (Etype (Pexp))
+ or else not Is_Type (Etype (Pexp))
+ or else not Has_Discriminants (Etype (Pexp))
+ or else Is_Constrained (Etype (Pexp));
end if;
-- Set the output type, this comes from Etype if it is set, otherwise we
@@ -12767,7 +12737,7 @@ package body Exp_Util is
-- they occur at the same level. If the second one is nested,
-- then the decision is neither right nor wrong (it would be
-- equally OK to leave the outer one in place, or take the new
- -- inner one. Really we should record both, but our data
+ -- inner one). Really we should record both, but our data
-- structures are not that elaborate.
if Nkind (Current_Value (Ent)) not in N_Subexpr then
@@ -12812,10 +12782,9 @@ package body Exp_Util is
Set_Entity_Current_Value (Right_Opnd (Cond));
end if;
- elsif Nkind_In (Cond,
- N_Type_Conversion,
- N_Qualified_Expression,
- N_Expression_With_Actions)
+ elsif Nkind (Cond) in N_Type_Conversion
+ | N_Qualified_Expression
+ | N_Expression_With_Actions
then
Set_Expression_Current_Value (Expression (Cond));
@@ -12888,7 +12857,7 @@ package body Exp_Util is
if Nkind (N) = N_Subprogram_Body
and then Address_Taken (Spec_Id)
and then
- Ekind_In (Scope (Spec_Id), E_Block, E_Procedure, E_Function)
+ Ekind (Scope (Spec_Id)) in E_Block | E_Procedure | E_Function
then
declare
Loc : constant Source_Ptr := Sloc (N);
@@ -13112,7 +13081,7 @@ package body Exp_Util is
elsif Is_Entity_Name (N) then
return Ekind (Entity (N)) = E_In_Parameter;
- elsif Nkind_In (N, N_Indexed_Component, N_Selected_Component) then
+ elsif Nkind (N) in N_Indexed_Component | N_Selected_Component then
return Within_In_Parameter (Prefix (N));
else
@@ -13193,9 +13162,7 @@ package body Exp_Util is
-- explicit dereference, then the designated object could
-- be modified by an assignment.
- if Nkind_In (RO, N_Indexed_Component,
- N_Explicit_Dereference)
- then
+ if Nkind (RO) in N_Indexed_Component | N_Explicit_Dereference then
return False;
-- A selected component must have a safe prefix
@@ -13244,58 +13211,18 @@ package body Exp_Util is
case Nkind (N) is
- -- An attribute reference is side effect free if its expressions
- -- are side effect free and its prefix is side effect free or
- -- is an entity reference.
-
- -- Is this right? what about x'first where x is a variable???
+ -- An attribute reference is side-effect free if its expressions
+ -- are side-effect free and its prefix is side-effect free or is
+ -- an entity reference.
when N_Attribute_Reference =>
- Attribute_Reference : declare
-
- function Side_Effect_Free_Attribute
- (Attribute_Name : Name_Id) return Boolean;
- -- Returns True if evaluation of the given attribute is
- -- considered side-effect free (independent of prefix and
- -- arguments).
-
- --------------------------------
- -- Side_Effect_Free_Attribute --
- --------------------------------
-
- function Side_Effect_Free_Attribute
- (Attribute_Name : Name_Id) return Boolean
- is
- begin
- case Attribute_Name is
- when Name_Input =>
- return False;
-
- when Name_Image
- | Name_Img
- | Name_Wide_Image
- | Name_Wide_Wide_Image
- =>
- -- CodePeer doesn't want to see replicated copies of
- -- 'Image calls.
-
- return not CodePeer_Mode;
-
- when others =>
- return True;
- end case;
- end Side_Effect_Free_Attribute;
-
- -- Start of processing for Attribute_Reference
-
- begin
- return
- Side_Effect_Free (Expressions (N), Name_Req, Variable_Ref)
- and then Side_Effect_Free_Attribute (Attribute_Name (N))
- and then (Is_Entity_Name (Prefix (N))
- or else Side_Effect_Free
- (Prefix (N), Name_Req, Variable_Ref));
- end Attribute_Reference;
+ return Side_Effect_Free_Attribute (Attribute_Name (N))
+ and then
+ Side_Effect_Free (Expressions (N), Name_Req, Variable_Ref)
+ and then
+ (Is_Entity_Name (Prefix (N))
+ or else
+ Side_Effect_Free (Prefix (N), Name_Req, Variable_Ref));
-- A binary operator is side effect free if and both operands are
-- side effect free. For this purpose binary operators include
@@ -13416,6 +13343,12 @@ package body Exp_Util is
=>
return True;
+ -- An aggregate is side effect free if all its values are compile
+ -- time known.
+
+ when N_Aggregate =>
+ return Compile_Time_Known_Aggregate (N);
+
-- We consider that anything else has side effects. This is a bit
-- crude, but we are pretty close for most common cases, and we
-- are certainly correct (i.e. we never return True when the
@@ -13454,6 +13387,30 @@ package body Exp_Util is
end if;
end Side_Effect_Free;
+ --------------------------------
+ -- Side_Effect_Free_Attribute --
+ --------------------------------
+
+ function Side_Effect_Free_Attribute (Name : Name_Id) return Boolean is
+ begin
+ case Name is
+ when Name_Input =>
+ return False;
+
+ when Name_Image
+ | Name_Img
+ | Name_Wide_Image
+ | Name_Wide_Wide_Image
+ =>
+ -- CodePeer doesn't want to see replicated copies of 'Image calls
+
+ return not CodePeer_Mode;
+
+ when others =>
+ return True;
+ end case;
+ end Side_Effect_Free_Attribute;
+
----------------------------------
-- Silly_Boolean_Array_Not_Test --
----------------------------------
@@ -13734,8 +13691,7 @@ package body Exp_Util is
Par := Parent (N);
while Present (Par) loop
- if Nkind_In (Original_Node (Par), N_Case_Expression,
- N_If_Expression)
+ if Nkind (Original_Node (Par)) in N_Case_Expression | N_If_Expression
then
return True;
@@ -13751,11 +13707,11 @@ package body Exp_Util is
return False;
end Within_Case_Or_If_Expression;
- --------------------------------
- -- Within_Internal_Subprogram --
- --------------------------------
+ ------------------------------
+ -- Predicate_Check_In_Scope --
+ ------------------------------
- function Within_Internal_Subprogram return Boolean is
+ function Predicate_Check_In_Scope (N : Node_Id) return Boolean is
S : Entity_Id;
begin
@@ -13764,10 +13720,23 @@ package body Exp_Util is
S := Scope (S);
end loop;
- return Present (S)
- and then Get_TSS_Name (S) /= TSS_Null
- and then not Is_Predicate_Function (S)
- and then not Is_Predicate_Function_M (S);
- end Within_Internal_Subprogram;
+ if Present (S) then
+
+ -- Predicate checks should only be enabled in init procs for
+ -- expressions coming from source.
+
+ if Is_Init_Proc (S) then
+ return Comes_From_Source (N);
+
+ elsif Get_TSS_Name (S) /= TSS_Null
+ and then not Is_Predicate_Function (S)
+ and then not Is_Predicate_Function_M (S)
+ then
+ return False;
+ end if;
+ end if;
+
+ return True;
+ end Predicate_Check_In_Scope;
end Exp_Util;