aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sem_util.adb
diff options
context:
space:
mode:
authorGiuliano Belinassi <giuliano.belinassi@usp.br>2020-08-22 17:43:43 -0300
committerGiuliano Belinassi <giuliano.belinassi@usp.br>2020-08-22 17:43:43 -0300
commita926878ddbd5a98b272c22171ce58663fc04c3e0 (patch)
tree86af256e5d9a9c06263c00adc90e5fe348008c43 /gcc/ada/sem_util.adb
parent542730f087133690b47e036dfd43eb0db8a650ce (diff)
parent07cbaed8ba7d1b6e4ab3a9f44175502a4e1ecdb1 (diff)
downloadgcc-devel/autopar_devel.zip
gcc-devel/autopar_devel.tar.gz
gcc-devel/autopar_devel.tar.bz2
Merge branch 'autopar_rebase2' into autopar_develdevel/autopar_devel
Quickly commit changes in the rebase branch.
Diffstat (limited to 'gcc/ada/sem_util.adb')
-rw-r--r--gcc/ada/sem_util.adb4158
1 files changed, 2913 insertions, 1245 deletions
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index e1703e9..679b3be 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_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- --
@@ -36,6 +36,7 @@ with Exp_Ch11; use Exp_Ch11;
with Exp_Util; use Exp_Util;
with Fname; use Fname;
with Freeze; use Freeze;
+with Itypes; use Itypes;
with Lib; use Lib;
with Lib.Xref; use Lib.Xref;
with Namet.Sp; use Namet.Sp;
@@ -115,8 +116,8 @@ package body Sem_Util is
(Item_Id : Entity_Id;
Property : Name_Id) return Boolean;
-- Subsidiary to routines Async_xxx_Enabled and Effective_xxx_Enabled.
- -- Determine whether an abstract state or a variable denoted by entity
- -- Item_Id has enabled property Property.
+ -- Determine whether the state abstraction, variable, or type denoted by
+ -- entity Item_Id has enabled property Property.
function Has_Null_Extension (T : Entity_Id) return Boolean;
-- T is a derived tagged type. Check whether the type extension is null.
@@ -132,6 +133,10 @@ package body Sem_Util is
-- components in the selected variant to determine whether all of them
-- have a default.
+ function Is_Preelaborable_Function (Id : Entity_Id) return Boolean;
+ -- Ada 2020: Determine whether the specified function is suitable as the
+ -- name of a call in a preelaborable construct (RM 10.2.1(7/5)).
+
type Null_Status_Kind is
(Is_Null,
-- This value indicates that a subexpression is known to have a null
@@ -190,8 +195,7 @@ package body Sem_Util is
Nod := Declaration_Node (Base_Type (Typ));
- if Nkind_In (Nod, N_Full_Type_Declaration,
- N_Private_Type_Declaration)
+ if Nkind (Nod) in N_Full_Type_Declaration | N_Private_Type_Declaration
then
return Empty_List;
end if;
@@ -1019,11 +1023,13 @@ package body Sem_Util is
HSS : Node_Id;
begin
- pragma Assert (Nkind_In (N, N_Block_Statement,
- N_Entry_Body,
- N_Package_Body,
- N_Subprogram_Body,
- N_Task_Body));
+ pragma Assert
+ (Nkind (N) in
+ N_Block_Statement |
+ N_Entry_Body |
+ N_Package_Body |
+ N_Subprogram_Body |
+ N_Task_Body);
HSS := Handled_Statement_Sequence (N);
@@ -1218,6 +1224,10 @@ package body Sem_Util is
-- Similar to previous one, for discriminated components constrained
-- by the discriminant of the enclosing object.
+ function Copy_And_Maybe_Dereference (N : Node_Id) return Node_Id;
+ -- Copy the subtree rooted at N and insert an explicit dereference if it
+ -- is of an access type.
+
-----------------------------------
-- Build_Actual_Array_Constraint --
-----------------------------------
@@ -1239,7 +1249,7 @@ package body Sem_Util is
if Denotes_Discriminant (Old_Lo) then
Lo :=
Make_Selected_Component (Loc,
- Prefix => New_Copy_Tree (P),
+ Prefix => Copy_And_Maybe_Dereference (P),
Selector_Name => New_Occurrence_Of (Entity (Old_Lo), Loc));
else
@@ -1257,7 +1267,7 @@ package body Sem_Util is
if Denotes_Discriminant (Old_Hi) then
Hi :=
Make_Selected_Component (Loc,
- Prefix => New_Copy_Tree (P),
+ Prefix => Copy_And_Maybe_Dereference (P),
Selector_Name => New_Occurrence_Of (Entity (Old_Hi), Loc));
else
@@ -1286,7 +1296,7 @@ package body Sem_Util is
while Present (D) loop
if Denotes_Discriminant (Node (D)) then
D_Val := Make_Selected_Component (Loc,
- Prefix => New_Copy_Tree (P),
+ Prefix => Copy_And_Maybe_Dereference (P),
Selector_Name => New_Occurrence_Of (Entity (Node (D)), Loc));
else
@@ -1322,13 +1332,13 @@ package body Sem_Util is
D_Val := New_Copy_Tree (D);
Set_Expression (D_Val,
Make_Selected_Component (Loc,
- Prefix => New_Copy_Tree (P),
+ Prefix => Copy_And_Maybe_Dereference (P),
Selector_Name =>
New_Occurrence_Of (Entity (Expression (D)), Loc)));
elsif Denotes_Discriminant (D) then
D_Val := Make_Selected_Component (Loc,
- Prefix => New_Copy_Tree (P),
+ Prefix => Copy_And_Maybe_Dereference (P),
Selector_Name => New_Occurrence_Of (Entity (D), Loc));
else
@@ -1342,6 +1352,22 @@ package body Sem_Util is
return Constraints;
end Build_Access_Record_Constraint;
+ --------------------------------
+ -- Copy_And_Maybe_Dereference --
+ --------------------------------
+
+ function Copy_And_Maybe_Dereference (N : Node_Id) return Node_Id is
+ New_N : constant Node_Id := New_Copy_Tree (N);
+
+ begin
+ if Is_Access_Type (Etype (N)) then
+ return Make_Explicit_Dereference (Sloc (Parent (N)), New_N);
+
+ else
+ return New_N;
+ end if;
+ end Copy_And_Maybe_Dereference;
+
-- Start of processing for Build_Actual_Subtype_Of_Component
begin
@@ -1396,7 +1422,7 @@ package body Sem_Util is
if Ekind (Desig_Typ) = E_Array_Subtype then
Id := First_Index (Desig_Typ);
- -- Check whether an index bound is constrained by a discriminant.
+ -- Check whether an index bound is constrained by a discriminant
while Present (Id) loop
Index_Typ := Underlying_Type (Etype (Id));
@@ -1485,17 +1511,38 @@ package body Sem_Util is
Loc : constant Source_Ptr := Sloc (Bod);
Clone_Id : constant Entity_Id := Class_Wide_Clone (Spec_Id);
Clone_Body : Node_Id;
+ Assoc_List : constant Elist_Id := New_Elmt_List;
begin
-- The declaration of the class-wide clone was created when the
-- corresponding class-wide condition was analyzed.
+ -- The body of the original condition may contain references to
+ -- the formals of Spec_Id. In the body of the class-wide clone,
+ -- these must be replaced with the corresponding formals of
+ -- the clone.
+
+ declare
+ Spec_Formal_Id : Entity_Id := First_Formal (Spec_Id);
+ Clone_Formal_Id : Entity_Id := First_Formal (Clone_Id);
+ begin
+ while Present (Spec_Formal_Id) loop
+ Append_Elmt (Spec_Formal_Id, Assoc_List);
+ Append_Elmt (Clone_Formal_Id, Assoc_List);
+
+ Next_Formal (Spec_Formal_Id);
+ Next_Formal (Clone_Formal_Id);
+ end loop;
+ end;
+
Clone_Body :=
Make_Subprogram_Body (Loc,
Specification =>
Copy_Subprogram_Spec (Parent (Clone_Id)),
Declarations => Declarations (Bod),
- Handled_Statement_Sequence => Handled_Statement_Sequence (Bod));
+ Handled_Statement_Sequence =>
+ New_Copy_Tree (Handled_Statement_Sequence (Bod),
+ Map => Assoc_List));
-- The new operation is internal and overriding indicators do not apply
-- (the original primitive may have carried one).
@@ -1618,6 +1665,13 @@ package body Sem_Util is
-- wrapper call to inherited operation.
Set_Class_Wide_Clone (Spec_Id, Clone_Id);
+
+ -- Inherit debug info flag from Spec_Id to Clone_Id to allow debugging
+ -- of the class-wide clone subprogram.
+
+ if Needs_Debug_Info (Spec_Id) then
+ Set_Debug_Info_Needed (Clone_Id);
+ end if;
end Build_Class_Wide_Clone_Decl;
-----------------------------
@@ -1656,6 +1710,78 @@ package body Sem_Util is
return Decl;
end Build_Component_Subtype;
+ -----------------------------
+ -- Build_Constrained_Itype --
+ -----------------------------
+
+ procedure Build_Constrained_Itype
+ (N : Node_Id;
+ Typ : Entity_Id;
+ New_Assoc_List : List_Id)
+ is
+ Constrs : constant List_Id := New_List;
+ Loc : constant Source_Ptr := Sloc (N);
+ Def_Id : Entity_Id;
+ Indic : Node_Id;
+ New_Assoc : Node_Id;
+ Subtyp_Decl : Node_Id;
+
+ begin
+ New_Assoc := First (New_Assoc_List);
+ while Present (New_Assoc) loop
+
+ -- There is exactly one choice in the component association (and
+ -- it is either a discriminant, a component or the others clause).
+ pragma Assert (List_Length (Choices (New_Assoc)) = 1);
+
+ -- Duplicate expression for the discriminant and put it on the
+ -- list of constraints for the itype declaration.
+
+ if Is_Entity_Name (First (Choices (New_Assoc)))
+ and then
+ Ekind (Entity (First (Choices (New_Assoc)))) = E_Discriminant
+ then
+ Append_To (Constrs, Duplicate_Subexpr (Expression (New_Assoc)));
+ end if;
+
+ Next (New_Assoc);
+ end loop;
+
+ if Has_Unknown_Discriminants (Typ)
+ and then Present (Underlying_Record_View (Typ))
+ then
+ Indic :=
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark =>
+ New_Occurrence_Of (Underlying_Record_View (Typ), Loc),
+ Constraint =>
+ Make_Index_Or_Discriminant_Constraint (Loc,
+ Constraints => Constrs));
+ else
+ Indic :=
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark =>
+ New_Occurrence_Of (Base_Type (Typ), Loc),
+ Constraint =>
+ Make_Index_Or_Discriminant_Constraint (Loc,
+ Constraints => Constrs));
+ end if;
+
+ Def_Id := Create_Itype (Ekind (Typ), N);
+
+ Subtyp_Decl :=
+ Make_Subtype_Declaration (Loc,
+ Defining_Identifier => Def_Id,
+ Subtype_Indication => Indic);
+ Set_Parent (Subtyp_Decl, Parent (N));
+
+ -- Itypes must be analyzed with checks off (see itypes.ads)
+
+ Analyze (Subtyp_Decl, Suppress => All_Checks);
+
+ Set_Etype (N, Def_Id);
+ end Build_Constrained_Itype;
+
---------------------------
-- Build_Default_Subtype --
---------------------------
@@ -1899,12 +2025,6 @@ package body Sem_Util is
if Present (Elaboration_Entity (Spec_Id)) then
return;
- -- Ignore in ASIS mode, elaboration entity is not in source and plays
- -- no role in analysis.
-
- elsif ASIS_Mode then
- return;
-
-- Do not generate an elaboration entity in GNATprove move because the
-- elaboration counter is a form of expansion.
@@ -2099,6 +2219,81 @@ package body Sem_Util is
return New_Spec;
end Build_Overriding_Spec;
+ -------------------
+ -- Build_Subtype --
+ -------------------
+
+ function Build_Subtype
+ (Related_Node : Node_Id;
+ Loc : Source_Ptr;
+ Typ : Entity_Id;
+ Constraints : List_Id)
+ return Entity_Id
+ is
+ Indic : Node_Id;
+ Subtyp_Decl : Node_Id;
+ Def_Id : Entity_Id;
+ Btyp : Entity_Id := Base_Type (Typ);
+
+ begin
+ -- The Related_Node better be here or else we won't be able to
+ -- attach new itypes to a node in the tree.
+
+ pragma Assert (Present (Related_Node));
+
+ -- If the view of the component's type is incomplete or private
+ -- with unknown discriminants, then the constraint must be applied
+ -- to the full type.
+
+ if Has_Unknown_Discriminants (Btyp)
+ and then Present (Underlying_Type (Btyp))
+ then
+ Btyp := Underlying_Type (Btyp);
+ end if;
+
+ Indic :=
+ Make_Subtype_Indication (Loc,
+ Subtype_Mark => New_Occurrence_Of (Btyp, Loc),
+ Constraint =>
+ Make_Index_Or_Discriminant_Constraint (Loc, Constraints));
+
+ Def_Id := Create_Itype (Ekind (Typ), Related_Node);
+
+ Subtyp_Decl :=
+ Make_Subtype_Declaration (Loc,
+ Defining_Identifier => Def_Id,
+ Subtype_Indication => Indic);
+
+ Set_Parent (Subtyp_Decl, Parent (Related_Node));
+
+ -- Itypes must be analyzed with checks off (see package Itypes)
+
+ Analyze (Subtyp_Decl, Suppress => All_Checks);
+
+ if Is_Itype (Def_Id) and then Has_Predicates (Typ) then
+ Inherit_Predicate_Flags (Def_Id, Typ);
+
+ -- Indicate where the predicate function may be found
+
+ if Is_Itype (Typ) then
+ if Present (Predicate_Function (Def_Id)) then
+ null;
+
+ elsif Present (Predicate_Function (Typ)) then
+ Set_Predicate_Function (Def_Id, Predicate_Function (Typ));
+
+ else
+ Set_Predicated_Parent (Def_Id, Predicated_Parent (Typ));
+ end if;
+
+ elsif No (Predicate_Function (Def_Id)) then
+ Set_Predicated_Parent (Def_Id, Typ);
+ end if;
+ end if;
+
+ return Def_Id;
+ end Build_Subtype;
+
-----------------------------------
-- Cannot_Raise_Constraint_Error --
-----------------------------------
@@ -2376,10 +2571,8 @@ package body Sem_Util is
-- Don't collect identifiers of packages, called functions, etc
- elsif Ekind_In (Entity (N), E_Package,
- E_Function,
- E_Procedure,
- E_Entry)
+ elsif Ekind (Entity (N)) in
+ E_Package | E_Function | E_Procedure | E_Entry
then
return Skip;
@@ -2399,9 +2592,8 @@ package body Sem_Util is
-- to identify a corner case???
elsif Nkind (Parent (N)) = N_Component_Association
- and then Nkind_In (Parent (Parent (N)),
- N_Aggregate,
- N_Extension_Aggregate)
+ and then Nkind (Parent (Parent (N))) in
+ N_Aggregate | N_Extension_Aggregate
then
declare
Choice : constant Node_Id := First (Choices (Parent (N)));
@@ -2435,15 +2627,15 @@ package body Sem_Util is
return Abandon;
end if;
- if Ekind_In (Id, E_Function, E_Generic_Function)
+ if Ekind (Id) in E_Function | E_Generic_Function
and then Has_Out_Or_In_Out_Parameter (Id)
then
Formal := First_Formal (Id);
Actual := First_Actual (Call);
while Present (Actual) and then Present (Formal) loop
if Actual = N then
- if Ekind_In (Formal, E_Out_Parameter,
- E_In_Out_Parameter)
+ if Ekind (Formal) in E_Out_Parameter
+ | E_In_Out_Parameter
then
Is_Writable_Actual := True;
end if;
@@ -2594,15 +2786,15 @@ package body Sem_Util is
if Ada_Version < Ada_2012
or else not Check_Actuals (N)
- or else (not (Nkind (N) in N_Op)
- and then not (Nkind (N) in N_Membership_Test)
- and then not Nkind_In (N, N_Range,
- N_Aggregate,
- N_Extension_Aggregate,
- N_Full_Type_Declaration,
- N_Function_Call,
- N_Procedure_Call_Statement,
- N_Entry_Call_Statement))
+ or else Nkind (N) not in N_Op
+ | N_Membership_Test
+ | N_Range
+ | N_Aggregate
+ | N_Extension_Aggregate
+ | N_Full_Type_Declaration
+ | N_Function_Call
+ | N_Procedure_Call_Statement
+ | N_Entry_Call_Statement
or else (Nkind (N) = N_Full_Type_Declaration
and then not Is_Record_Type (Defining_Identifier (N)))
@@ -2642,7 +2834,7 @@ package body Sem_Util is
Collect_Identifiers (Right_Opnd (N));
end if;
- if Nkind_In (N, N_In, N_Not_In)
+ if Nkind (N) in N_In | N_Not_In
and then Present (Alternatives (N))
then
Expr := First (Alternatives (N));
@@ -2720,8 +2912,7 @@ package body Sem_Util is
Formal := First_Formal (Id);
Actual := First_Actual (N);
while Present (Actual) and then Present (Formal) loop
- if Ekind_In (Formal, E_Out_Parameter,
- E_In_Out_Parameter)
+ if Ekind (Formal) in E_Out_Parameter | E_In_Out_Parameter
then
Collect_Identifiers (Actual);
end if;
@@ -2759,7 +2950,7 @@ package body Sem_Util is
declare
Count_Components : Uint := Uint_0;
Num_Components : Uint;
- Others_Assoc : Node_Id;
+ Others_Assoc : Node_Id := Empty;
Others_Choice : Node_Id := Empty;
Others_Box_Present : Boolean := False;
@@ -2788,8 +2979,8 @@ package body Sem_Util is
-- Count several components
- elsif Nkind_In (Choice, N_Range,
- N_Subtype_Indication)
+ elsif Nkind (Choice) in
+ N_Range | N_Subtype_Indication
or else (Is_Entity_Name (Choice)
and then Is_Type (Entity (Choice)))
then
@@ -2844,6 +3035,8 @@ package body Sem_Util is
-- minimum decoration required to collect the
-- identifiers.
+ pragma Assert (Present (Others_Assoc));
+
if not Expander_Active then
Comp_Expr := Expression (Others_Assoc);
else
@@ -2889,8 +3082,8 @@ package body Sem_Util is
while Present (Assoc) loop
Choice := First (Choices (Assoc));
while Present (Choice) loop
- if Nkind_In (Choice, N_Range,
- N_Subtype_Indication)
+ if Nkind (Choice) in
+ N_Range | N_Subtype_Indication
or else (Is_Entity_Name (Choice)
and then Is_Type (Entity (Choice)))
then
@@ -3250,8 +3443,8 @@ package body Sem_Util is
elsif Nkind (P) = N_Parameter_Specification
and then Scope (Current_Scope) = Scope (Nam)
- and then Nkind_In (Parent (P), N_Entry_Declaration,
- N_Subprogram_Declaration)
+ and then Nkind (Parent (P)) in
+ N_Entry_Declaration | N_Subprogram_Declaration
then
Error_Msg_N
("internal call cannot appear in default for formal of "
@@ -3320,7 +3513,8 @@ package body Sem_Util is
-- Loop through sequence of basic declarative items
Outer : while Present (Decl) loop
- if not Nkind_In (Decl, N_Subprogram_Body, N_Package_Body, N_Task_Body)
+ if Nkind (Decl) not in
+ N_Subprogram_Body | N_Package_Body | N_Task_Body
and then Nkind (Decl) not in N_Body_Stub
then
Next (Decl);
@@ -3339,10 +3533,6 @@ package body Sem_Util is
Error_Msg_N
("(Ada 83) decl cannot appear after body#", Decl);
end if;
- else
- Error_Msg_Sloc := Body_Sloc;
- Check_SPARK_05_Restriction
- ("decl cannot appear after body#", Decl);
end if;
end if;
@@ -3362,7 +3552,7 @@ package body Sem_Util is
Scop : Entity_Id;
begin
- pragma Assert (Ekind_In (Id, E_Abstract_State, E_Variable));
+ pragma Assert (Ekind (Id) in E_Abstract_State | E_Variable);
-- Nothing to do for internally-generated abstract states and variables
-- because they do not represent the hidden state of the source unit.
@@ -3387,23 +3577,21 @@ package body Sem_Util is
return;
-- Objects and states that appear immediately within a subprogram or
- -- inside a construct nested within a subprogram do not introduce a
- -- hidden state. They behave as local variable declarations.
+ -- entry inside a construct nested within a subprogram do not
+ -- introduce a hidden state. They behave as local variable
+ -- declarations. The same is true for elaboration code inside a block
+ -- or a task.
- elsif Is_Subprogram (Context) then
+ elsif Is_Subprogram_Or_Entry (Context)
+ or else Ekind (Context) in E_Block | E_Task_Type
+ then
return;
-
- -- When examining a package body, use the entity of the spec as it
- -- carries the abstract state declarations.
-
- elsif Ekind (Context) = E_Package_Body then
- Context := Spec_Entity (Context);
end if;
-- Stop the traversal when a package subject to a null abstract state
-- has been found.
- if Ekind_In (Context, E_Generic_Package, E_Package)
+ if Is_Package_Or_Generic_Package (Context)
and then Has_Null_Abstract_State (Context)
then
exit;
@@ -3613,7 +3801,7 @@ package body Sem_Util is
-- Initial_Condition and Initializes as this is part of the
-- elaboration checks for the constituent (SPARK RM 9(3)).
- if Nam_In (Prag_Nam, Name_Initial_Condition, Name_Initializes) then
+ if Prag_Nam in Name_Initial_Condition | Name_Initializes then
return;
-- When the reference appears within pragma Depends or Global,
@@ -3621,7 +3809,7 @@ package body Sem_Util is
-- that the pragma may not encapsulated by the type definition,
-- but this is still a valid context.
- elsif Nam_In (Prag_Nam, Name_Depends, Name_Global)
+ elsif Prag_Nam in Name_Depends | Name_Global
and then Is_Single_Task_Pragma (Par, Conc_Obj)
then
return;
@@ -3630,8 +3818,8 @@ package body Sem_Util is
-- The reference appears somewhere in the definition of a single
-- concurrent type (SPARK RM 9(3)).
- elsif Nkind_In (Par, N_Single_Protected_Declaration,
- N_Single_Task_Declaration)
+ elsif Nkind (Par) in
+ N_Single_Protected_Declaration | N_Single_Task_Declaration
and then Defining_Entity (Par) = Conc_Obj
then
return;
@@ -3639,10 +3827,10 @@ package body Sem_Util is
-- The reference appears within the declaration or body of a single
-- concurrent type (SPARK RM 9(3)).
- elsif Nkind_In (Par, N_Protected_Body,
- N_Protected_Type_Declaration,
- N_Task_Body,
- N_Task_Type_Declaration)
+ elsif Nkind (Par) in N_Protected_Body
+ | N_Protected_Type_Declaration
+ | N_Task_Body
+ | N_Task_Type_Declaration
and then Is_Single_Declaration_Or_Body (Par, Conc_Obj)
then
return;
@@ -3661,10 +3849,10 @@ package body Sem_Util is
-- real check was already performed in the original context of the
-- reference.
- elsif Nkind_In (Par, N_Package_Body,
- N_Package_Declaration,
- N_Subprogram_Body,
- N_Subprogram_Declaration)
+ elsif Nkind (Par) in N_Package_Body
+ | N_Package_Declaration
+ | N_Subprogram_Body
+ | N_Subprogram_Declaration
and then Is_Internal_Declaration_Or_Body (Par)
then
return;
@@ -3874,10 +4062,10 @@ package body Sem_Util is
-- Empty list (no global items) or single global item
-- declaration (only input items).
- if Nkind_In (List, N_Null,
- N_Expanded_Name,
- N_Identifier,
- N_Selected_Component)
+ if Nkind (List) in N_Null
+ | N_Expanded_Name
+ | N_Identifier
+ | N_Selected_Component
then
return False;
@@ -3928,7 +4116,7 @@ package body Sem_Util is
Param := First_Formal (Subp);
while Present (Param) loop
- if Ekind_In (Param, E_Out_Parameter, E_In_Out_Parameter) then
+ if Ekind (Param) in E_Out_Parameter | E_In_Out_Parameter then
return False;
end if;
@@ -3993,7 +4181,7 @@ package body Sem_Util is
procedure Check_Conjuncts (Expr : Node_Id) is
begin
- if Nkind_In (Expr, N_Op_And, N_And_Then) then
+ if Nkind (Expr) in N_Op_And | N_And_Then then
Check_Conjuncts (Left_Opnd (Expr));
Check_Conjuncts (Right_Opnd (Expr));
else
@@ -4075,11 +4263,11 @@ package body Sem_Util is
Ent : Entity_Id;
begin
- if Nkind_In (N, N_Explicit_Dereference, N_Function_Call) then
+ if Nkind (N) in N_Explicit_Dereference | N_Function_Call then
Post_State_Seen := True;
return Abandon;
- elsif Nkind_In (N, N_Expanded_Name, N_Identifier) then
+ elsif Nkind (N) in N_Expanded_Name | N_Identifier then
Ent := Entity (N);
-- Treat an undecorated reference as OK
@@ -4089,10 +4277,10 @@ package body Sem_Util is
-- A reference to an assignable entity is considered a
-- change in the post-state of a subprogram.
- or else Ekind_In (Ent, E_Generic_In_Out_Parameter,
- E_In_Out_Parameter,
- E_Out_Parameter,
- E_Variable)
+ or else Ekind (Ent) in E_Generic_In_Out_Parameter
+ | E_In_Out_Parameter
+ | E_Out_Parameter
+ | E_Variable
-- The reference may be modified through a dereference
@@ -4150,8 +4338,7 @@ package body Sem_Util is
-- Examine the expression of a postcondition
- else pragma Assert (Nam_In (Nam, Name_Postcondition,
- Name_Refined_Post));
+ else pragma Assert (Nam in Name_Postcondition | Name_Refined_Post);
Check_Expression (Expr);
end if;
end Check_Result_And_Post_State_In_Pragma;
@@ -4225,8 +4412,8 @@ package body Sem_Util is
Prag := Pre_Post_Conditions (Items);
while Present (Prag) loop
- if Nam_In (Pragma_Name_Unmapped (Prag),
- Name_Postcondition, Name_Refined_Post)
+ if Pragma_Name_Unmapped (Prag)
+ in Name_Postcondition | Name_Refined_Post
and then not Error_Posted (Prag)
then
Post_Prag := Prag;
@@ -4253,7 +4440,7 @@ package body Sem_Util is
-- Do not emit any errors if the subprogram is not a function
- if not Ekind_In (Spec_Id, E_Function, E_Generic_Function) then
+ if Ekind (Spec_Id) not in E_Function | E_Generic_Function then
null;
-- Regardless of whether the function has postconditions or contract
@@ -4386,8 +4573,8 @@ package body Sem_Util is
if Present (Decls) then
Decl := First (Decls);
while Present (Decl) loop
- if Nkind_In (Decl, N_Generic_Package_Declaration,
- N_Package_Declaration)
+ if Nkind (Decl) in N_Generic_Package_Declaration
+ | N_Package_Declaration
then
Check_Package (Decl);
end if;
@@ -4430,10 +4617,10 @@ package body Sem_Util is
-- An entry, protected, subprogram, or task body may declare a nested
-- package.
- elsif Nkind_In (Context, N_Entry_Body,
- N_Protected_Body,
- N_Subprogram_Body,
- N_Task_Body)
+ elsif Nkind (Context) in N_Entry_Body
+ | N_Protected_Body
+ | N_Subprogram_Body
+ | N_Task_Body
then
-- Do not verify proper state refinement when the body is subject to
-- pragma SPARK_Mode Off because this disables the requirement for
@@ -4458,8 +4645,8 @@ package body Sem_Util is
-- A library level [generic] package may declare a nested package
- elsif Nkind_In (Context, N_Generic_Package_Declaration,
- N_Package_Declaration)
+ elsif Nkind (Context) in
+ N_Generic_Package_Declaration | N_Package_Declaration
and then Is_Main_Unit
then
Check_Package (Context);
@@ -4512,7 +4699,7 @@ package body Sem_Util is
-- For indexed and selected components, recursively check the prefix
- if Nkind_In (Obj, N_Indexed_Component, N_Selected_Component) then
+ if Nkind (Obj) in N_Indexed_Component | N_Selected_Component then
return Enclosing_Protected_Type (Prefix (Obj));
-- The object does not denote a protected component
@@ -4616,9 +4803,8 @@ package body Sem_Util is
Constit_Id := Entity_Of (Constit);
if Present (Constit_Id)
- and then Ekind_In (Constit_Id, E_Abstract_State,
- E_Constant,
- E_Variable)
+ and then Ekind (Constit_Id) in
+ E_Abstract_State | E_Constant | E_Variable
then
Remove (States, Constit_Id);
end if;
@@ -4746,6 +4932,96 @@ package body Sem_Util is
end if;
end Check_Unused_Body_States;
+ ------------------------------------
+ -- Check_Volatility_Compatibility --
+ ------------------------------------
+
+ procedure Check_Volatility_Compatibility
+ (Id1, Id2 : Entity_Id;
+ Description_1, Description_2 : String;
+ Srcpos_Bearer : Node_Id) is
+
+ begin
+ if SPARK_Mode /= On then
+ return;
+ end if;
+
+ declare
+ AR1 : constant Boolean := Async_Readers_Enabled (Id1);
+ AW1 : constant Boolean := Async_Writers_Enabled (Id1);
+ ER1 : constant Boolean := Effective_Reads_Enabled (Id1);
+ EW1 : constant Boolean := Effective_Writes_Enabled (Id1);
+ AR2 : constant Boolean := Async_Readers_Enabled (Id2);
+ AW2 : constant Boolean := Async_Writers_Enabled (Id2);
+ ER2 : constant Boolean := Effective_Reads_Enabled (Id2);
+ EW2 : constant Boolean := Effective_Writes_Enabled (Id2);
+
+ AR_Check_Failed : constant Boolean := AR1 and not AR2;
+ AW_Check_Failed : constant Boolean := AW1 and not AW2;
+ ER_Check_Failed : constant Boolean := ER1 and not ER2;
+ EW_Check_Failed : constant Boolean := EW1 and not EW2;
+
+ package Failure_Description is
+ procedure Note_If_Failure
+ (Failed : Boolean; Aspect_Name : String);
+ -- If Failed is False, do nothing.
+ -- If Failed is True, add Aspect_Name to the failure description.
+
+ function Failure_Text return String;
+ -- returns accumulated list of failing aspects
+ end Failure_Description;
+
+ package body Failure_Description is
+ Description_Buffer : Bounded_String;
+
+ ---------------------
+ -- Note_If_Failure --
+ ---------------------
+
+ procedure Note_If_Failure
+ (Failed : Boolean; Aspect_Name : String) is
+ begin
+ if Failed then
+ if Description_Buffer.Length /= 0 then
+ Append (Description_Buffer, ", ");
+ end if;
+ Append (Description_Buffer, Aspect_Name);
+ end if;
+ end Note_If_Failure;
+
+ ------------------
+ -- Failure_Text --
+ ------------------
+
+ function Failure_Text return String is
+ begin
+ return +Description_Buffer;
+ end Failure_Text;
+ end Failure_Description;
+
+ use Failure_Description;
+ begin
+ if AR_Check_Failed
+ or AW_Check_Failed
+ or ER_Check_Failed
+ or EW_Check_Failed
+ then
+ Note_If_Failure (AR_Check_Failed, "Async_Readers");
+ Note_If_Failure (AW_Check_Failed, "Async_Writers");
+ Note_If_Failure (ER_Check_Failed, "Effective_Reads");
+ Note_If_Failure (EW_Check_Failed, "Effective_Writes");
+
+ Error_Msg_N
+ (Description_1
+ & " and "
+ & Description_2
+ & " are not compatible with respect to volatility due to "
+ & Failure_Text,
+ Srcpos_Bearer);
+ end if;
+ end;
+ end Check_Volatility_Compatibility;
+
-----------------
-- Choice_List --
-----------------
@@ -4800,7 +5076,7 @@ package body Sem_Util is
elsif Ekind (Item_Id) = E_Abstract_State then
Append_New_Elmt (Item_Id, States);
- elsif Ekind_In (Item_Id, E_Constant, E_Variable)
+ elsif Ekind (Item_Id) in E_Constant | E_Variable
and then Is_Visible_Object (Item_Id)
then
Append_New_Elmt (Item_Id, States);
@@ -5587,7 +5863,14 @@ package body Sem_Util is
-- will happen when something is evaluated if it never will be
-- evaluated.
- if not Is_Statically_Unevaluated (N) then
+ -- Suppress error reporting when checking that the expression of a
+ -- static expression function is a potentially static expression,
+ -- because we don't want additional errors being reported during the
+ -- preanalysis of the expression (see Analyze_Expression_Function).
+
+ if not Is_Statically_Unevaluated (N)
+ and then not Checking_Potentially_Static_Expression
+ then
if Present (Ent) then
Error_Msg_NEL (Msgc (1 .. Msgl), N, Ent, Eloc);
else
@@ -5860,14 +6143,14 @@ package body Sem_Util is
-- Current_Entity_In_Scope --
-----------------------------
- function Current_Entity_In_Scope (N : Node_Id) return Entity_Id is
+ function Current_Entity_In_Scope (N : Name_Id) return Entity_Id is
E : Entity_Id;
CS : constant Entity_Id := Current_Scope;
Transient_Case : constant Boolean := Scope_Is_Transient;
begin
- E := Get_Name_Entity_Id (Chars (N));
+ E := Get_Name_Entity_Id (N);
while Present (E)
and then Scope (E) /= CS
and then (not Transient_Case or else Scope (E) /= Scope (CS))
@@ -5878,6 +6161,15 @@ package body Sem_Util is
return E;
end Current_Entity_In_Scope;
+ -----------------------------
+ -- Current_Entity_In_Scope --
+ -----------------------------
+
+ function Current_Entity_In_Scope (N : Node_Id) return Entity_Id is
+ begin
+ return Current_Entity_In_Scope (Chars (N));
+ end Current_Entity_In_Scope;
+
-------------------
-- Current_Scope --
-------------------
@@ -6126,8 +6418,28 @@ package body Sem_Util is
function Is_Renaming (N : Node_Id) return Boolean is
begin
- return
- Is_Entity_Name (N) and then Present (Renamed_Entity (Entity (N)));
+ if not Is_Entity_Name (N) then
+ return False;
+ end if;
+
+ case Ekind (Entity (N)) is
+ when E_Variable | E_Constant =>
+ return Present (Renamed_Object (Entity (N)));
+
+ when E_Exception
+ | E_Function
+ | E_Generic_Function
+ | E_Generic_Package
+ | E_Generic_Procedure
+ | E_Operator
+ | E_Package
+ | E_Procedure
+ =>
+ return Present (Renamed_Entity (Entity (N)));
+
+ when others =>
+ return False;
+ end case;
end Is_Renaming;
-----------------------
@@ -6354,7 +6666,7 @@ package body Sem_Util is
function Denotes_Same_Prefix (A1, A2 : Node_Id) return Boolean is
begin
if Is_Entity_Name (A1) then
- if Nkind_In (A2, N_Selected_Component, N_Indexed_Component)
+ if Nkind (A2) in N_Selected_Component | N_Indexed_Component
and then not Is_Access_Type (Etype (A1))
then
return Denotes_Same_Object (A1, Prefix (A2))
@@ -6366,9 +6678,9 @@ package body Sem_Util is
elsif Is_Entity_Name (A2) then
return Denotes_Same_Prefix (A1 => A2, A2 => A1);
- elsif Nkind_In (A1, N_Selected_Component, N_Indexed_Component, N_Slice)
+ elsif Nkind (A1) in N_Selected_Component | N_Indexed_Component | N_Slice
and then
- Nkind_In (A2, N_Selected_Component, N_Indexed_Component, N_Slice)
+ Nkind (A2) in N_Selected_Component | N_Indexed_Component | N_Slice
then
declare
Root1, Root2 : Node_Id;
@@ -6377,8 +6689,8 @@ package body Sem_Util is
begin
Root1 := Prefix (A1);
while not Is_Entity_Name (Root1) loop
- if not Nkind_In
- (Root1, N_Selected_Component, N_Indexed_Component)
+ if Nkind (Root1) not in
+ N_Selected_Component | N_Indexed_Component
then
return False;
else
@@ -6390,8 +6702,8 @@ package body Sem_Util is
Root2 := Prefix (A2);
while not Is_Entity_Name (Root2) loop
- if not Nkind_In (Root2, N_Selected_Component,
- N_Indexed_Component)
+ if Nkind (Root2) not in
+ N_Selected_Component | N_Indexed_Component
then
return False;
else
@@ -6501,19 +6813,19 @@ package body Sem_Util is
-- Start of processing for Designate_Same_Unit
begin
- if Nkind_In (K1, N_Identifier, N_Defining_Identifier)
+ if K1 in N_Identifier | N_Defining_Identifier
and then
- Nkind_In (K2, N_Identifier, N_Defining_Identifier)
+ K2 in N_Identifier | N_Defining_Identifier
then
return Chars (Name1) = Chars (Name2);
- elsif Nkind_In (K1, N_Expanded_Name,
- N_Selected_Component,
- N_Defining_Program_Unit_Name)
- and then
- Nkind_In (K2, N_Expanded_Name,
- N_Selected_Component,
- N_Defining_Program_Unit_Name)
+ elsif K1 in N_Expanded_Name
+ | N_Selected_Component
+ | N_Defining_Program_Unit_Name
+ and then
+ K2 in N_Expanded_Name
+ | N_Selected_Component
+ | N_Defining_Program_Unit_Name
then
return
(Chars (Select_Node (Name1)) = Chars (Select_Node (Name2)))
@@ -6609,7 +6921,7 @@ package body Sem_Util is
end if;
if (Is_Formal (E)
- or else Ekind_In (E, E_Variable, E_Constant))
+ or else Ekind (E) in E_Variable | E_Constant)
and then Present (Get_Accessibility (E))
then
return New_Occurrence_Of (Get_Accessibility (E), Loc);
@@ -6619,7 +6931,7 @@ package body Sem_Util is
-- Handle a constant-folded conditional expression by avoiding use of
-- the original node.
- if Nkind_In (Expr, N_Case_Expression, N_If_Expression) then
+ if Nkind (Expr) in N_Case_Expression | N_If_Expression then
Expr := N;
end if;
@@ -6938,13 +7250,13 @@ package body Sem_Util is
begin
Par := Parent (N);
while Present (Par) loop
- if Nkind_In (Par, N_Package_Body, N_Subprogram_Body) then
+ if Nkind (Par) in N_Package_Body | N_Subprogram_Body then
Spec_Id := Corresponding_Spec (Par);
if Present (Spec_Id)
- and then Nkind_In (Unit_Declaration_Node (Spec_Id),
- N_Generic_Package_Declaration,
- N_Generic_Subprogram_Declaration)
+ and then Nkind (Unit_Declaration_Node (Spec_Id)) in
+ N_Generic_Package_Declaration |
+ N_Generic_Subprogram_Declaration
then
return Par;
end if;
@@ -6968,19 +7280,19 @@ package body Sem_Util is
begin
Par := Parent (N);
while Present (Par) loop
- if Nkind_In (Par, N_Generic_Package_Declaration,
- N_Generic_Subprogram_Declaration)
+ if Nkind (Par) in N_Generic_Package_Declaration
+ | N_Generic_Subprogram_Declaration
then
return Par;
- elsif Nkind_In (Par, N_Package_Body, N_Subprogram_Body) then
+ elsif Nkind (Par) in N_Package_Body | N_Subprogram_Body then
Spec_Id := Corresponding_Spec (Par);
if Present (Spec_Id) then
Spec_Decl := Unit_Declaration_Node (Spec_Id);
- if Nkind_In (Spec_Decl, N_Generic_Package_Declaration,
- N_Generic_Subprogram_Declaration)
+ if Nkind (Spec_Decl) in N_Generic_Package_Declaration
+ | N_Generic_Subprogram_Declaration
then
return Spec_Decl;
end if;
@@ -7050,9 +7362,8 @@ package body Sem_Util is
elsif Dynamic_Scope = Empty then
return Empty;
- elsif Ekind_In (Dynamic_Scope, E_Generic_Package,
- E_Package,
- E_Package_Body)
+ elsif Ekind (Dynamic_Scope) in
+ E_Generic_Package | E_Package | E_Package_Body
then
return Dynamic_Scope;
@@ -7101,10 +7412,10 @@ package body Sem_Util is
elsif Ekind (Dyn_Scop) = E_Subprogram_Body then
return Corresponding_Spec (Parent (Parent (Dyn_Scop)));
- elsif Ekind_In (Dyn_Scop, E_Block, E_Loop, E_Return_Statement) then
+ elsif Ekind (Dyn_Scop) in E_Block | E_Loop | E_Return_Statement then
return Enclosing_Subprogram (Dyn_Scop);
- elsif Ekind_In (Dyn_Scop, E_Entry, E_Entry_Family) then
+ elsif Ekind (Dyn_Scop) in E_Entry | E_Entry_Family then
-- For a task entry or entry family, return the enclosing subprogram
-- of the task itself.
@@ -7126,17 +7437,16 @@ package body Sem_Util is
-- The scope may appear as a private type or as a private extension
-- whose completion is a task or protected type.
- elsif Ekind_In (Dyn_Scop, E_Limited_Private_Type,
- E_Record_Type_With_Private)
+ elsif Ekind (Dyn_Scop) in
+ E_Limited_Private_Type | E_Record_Type_With_Private
and then Present (Full_View (Dyn_Scop))
- and then Ekind_In (Full_View (Dyn_Scop), E_Task_Type, E_Protected_Type)
+ and then Ekind (Full_View (Dyn_Scop)) in E_Task_Type | E_Protected_Type
then
return Get_Task_Body_Procedure (Full_View (Dyn_Scop));
-- No body is generated if the protected operation is eliminated
- elsif Convention (Dyn_Scop) = Convention_Protected
- and then not Is_Eliminated (Dyn_Scop)
+ elsif not Is_Eliminated (Dyn_Scop)
and then Present (Protected_Body_Subprogram (Dyn_Scop))
then
return Protected_Body_Subprogram (Dyn_Scop);
@@ -7188,11 +7498,11 @@ package body Sem_Util is
-- Start of processing for End_Keyword_Location
begin
- if Nkind_In (N, N_Block_Statement,
- N_Entry_Body,
- N_Package_Body,
- N_Subprogram_Body,
- N_Task_Body)
+ if Nkind (N) in N_Block_Statement
+ | N_Entry_Body
+ | N_Package_Body
+ | N_Subprogram_Body
+ | N_Task_Body
then
Owner := Handled_Statement_Sequence (N);
@@ -7202,13 +7512,12 @@ package body Sem_Util is
elsif Nkind (N) = N_Protected_Body then
Owner := N;
- elsif Nkind_In (N, N_Protected_Type_Declaration,
- N_Single_Protected_Declaration)
+ elsif Nkind (N) in N_Protected_Type_Declaration
+ | N_Single_Protected_Declaration
then
Owner := Protected_Definition (N);
- elsif Nkind_In (N, N_Single_Task_Declaration,
- N_Task_Type_Declaration)
+ elsif Nkind (N) in N_Single_Task_Declaration | N_Task_Type_Declaration
then
Owner := Task_Definition (N);
@@ -7464,7 +7773,7 @@ package body Sem_Util is
-- Avoid cascaded messages with duplicate components in
-- derived types.
- if Ekind_In (E, E_Component, E_Discriminant) then
+ if Ekind (E) in E_Component | E_Discriminant then
return;
end if;
end if;
@@ -7499,7 +7808,7 @@ package body Sem_Util is
-- of inheriting components in a derived record definition. Preserve
-- their Ekind and Etype.
- if Ekind_In (Def_Id, E_Discriminant, E_Component) then
+ if Ekind (Def_Id) in E_Discriminant | E_Component then
null;
-- If a type is already set, leave it alone (happens when a type
@@ -7522,7 +7831,7 @@ package body Sem_Util is
-- Unless the Itype is for a record type with a corresponding remote
-- type (what is that about, it was not commented ???)
- if Ekind_In (Def_Id, E_Discriminant, E_Component)
+ if Ekind (Def_Id) in E_Discriminant | E_Component
or else
((not Is_Record_Type (Def_Id)
or else No (Corresponding_Remote_Type (Def_Id)))
@@ -7536,52 +7845,6 @@ package body Sem_Util is
Append_Entity (Def_Id, S);
Set_Public_Status (Def_Id);
- -- Declaring a homonym is not allowed in SPARK ...
-
- if Present (C) and then Restriction_Check_Required (SPARK_05) then
- declare
- Enclosing_Subp : constant Node_Id := Enclosing_Subprogram (Def_Id);
- Enclosing_Pack : constant Node_Id := Enclosing_Package (Def_Id);
- Other_Scope : constant Node_Id := Enclosing_Dynamic_Scope (C);
-
- begin
- -- ... unless the new declaration is in a subprogram, and the
- -- visible declaration is a variable declaration or a parameter
- -- specification outside that subprogram.
-
- if Present (Enclosing_Subp)
- and then Nkind_In (Parent (C), N_Object_Declaration,
- N_Parameter_Specification)
- and then not Scope_Within_Or_Same (Other_Scope, Enclosing_Subp)
- then
- null;
-
- -- ... or the new declaration is in a package, and the visible
- -- declaration occurs outside that package.
-
- elsif Present (Enclosing_Pack)
- and then not Scope_Within_Or_Same (Other_Scope, Enclosing_Pack)
- then
- null;
-
- -- ... or the new declaration is a component declaration in a
- -- record type definition.
-
- elsif Nkind (Parent (Def_Id)) = N_Component_Declaration then
- null;
-
- -- Don't issue error for non-source entities
-
- elsif Comes_From_Source (Def_Id)
- and then Comes_From_Source (C)
- then
- Error_Msg_Sloc := Sloc (C);
- Check_SPARK_05_Restriction
- ("redeclaration of identifier &#", Def_Id);
- end if;
- end;
- end if;
-
-- Warn if new entity hides an old one
if Warn_On_Hiding and then Present (C)
@@ -7920,8 +8183,7 @@ package body Sem_Util is
elsif Comes_From_Source (Decl)
or else
- (Nkind_In (Decl, N_Subprogram_Body,
- N_Subprogram_Declaration)
+ (Nkind (Decl) in N_Subprogram_Body | N_Subprogram_Declaration
and then Is_Expression_Function (Defining_Entity (Decl)))
then
exit;
@@ -7993,7 +8255,7 @@ package body Sem_Util is
Call_Nam : Node_Id;
begin
- if Nkind_In (Context, N_Indexed_Component, N_Selected_Component)
+ if Nkind (Context) in N_Indexed_Component | N_Selected_Component
and then N = Prefix (Context)
then
Find_Actual (Context, Formal, Call);
@@ -8004,9 +8266,9 @@ package body Sem_Util is
then
Call := Parent (Context);
- elsif Nkind_In (Context, N_Entry_Call_Statement,
- N_Function_Call,
- N_Procedure_Call_Statement)
+ elsif Nkind (Context) in N_Entry_Call_Statement
+ | N_Function_Call
+ | N_Procedure_Call_Statement
then
Call := Context;
@@ -8020,9 +8282,9 @@ package body Sem_Util is
-- we exclude overloaded calls, since we don't know enough to be sure
-- of giving the right answer in this case.
- if Nkind_In (Call, N_Entry_Call_Statement,
- N_Function_Call,
- N_Procedure_Call_Statement)
+ if Nkind (Call) in N_Entry_Call_Statement
+ | N_Function_Call
+ | N_Procedure_Call_Statement
then
Call_Nam := Name (Call);
@@ -8066,8 +8328,8 @@ package body Sem_Util is
return;
else
- Actual := Next_Actual (Actual);
- Formal := Next_Formal (Formal);
+ Next_Actual (Actual);
+ Next_Formal (Formal);
end if;
end loop;
end if;
@@ -8422,7 +8684,7 @@ package body Sem_Util is
Expr := Prefix (Expr);
exit;
- -- Check for Const where Const is a constant entity
+ -- Check for Const where Const is a constant entity
elsif Is_Entity_Name (Expr)
and then Ekind (Entity (Expr)) = E_Constant
@@ -8448,8 +8710,7 @@ package body Sem_Util is
-- Check for components
- elsif
- Nkind_In (Expr, N_Selected_Component, N_Indexed_Component)
+ elsif Nkind (Expr) in N_Selected_Component | N_Indexed_Component
then
Expr := Prefix (Expr);
Off := True;
@@ -8800,7 +9061,7 @@ package body Sem_Util is
-- Single global item declaration (only input items)
- elsif Nkind_In (List, N_Expanded_Name, N_Identifier) then
+ elsif Nkind (List) in N_Expanded_Name | N_Identifier then
if Global_Mode = Name_Input then
return List;
else
@@ -8854,10 +9115,10 @@ package body Sem_Util is
-- Start of processing for First_Global
begin
- pragma Assert (Nam_In (Global_Mode, Name_In_Out,
- Name_Input,
- Name_Output,
- Name_Proof_In));
+ pragma Assert (Global_Mode in Name_In_Out
+ | Name_Input
+ | Name_Output
+ | Name_Proof_In);
-- Retrieve the suitable pragma Global or Refined_Global. In the second
-- case, it can only be located on the body entity.
@@ -8906,7 +9167,7 @@ package body Sem_Util is
function Fix_Msg (Id : Entity_Id; Msg : String) return String is
Is_Task : constant Boolean :=
- Ekind_In (Id, E_Task_Body, E_Task_Type)
+ Ekind (Id) in E_Task_Body | E_Task_Type
or else Is_Single_Task_Object (Id);
Msg_Last : constant Natural := Msg'Last;
Msg_Index : Natural;
@@ -8926,7 +9187,7 @@ package body Sem_Util is
if Msg_Index <= Msg_Last - 10
and then Msg (Msg_Index .. Msg_Index + 9) = "subprogram"
then
- if Ekind_In (Id, E_Entry, E_Entry_Family) then
+ if Is_Entry (Id) then
Res (Res_Index .. Res_Index + 4) := "entry";
Res_Index := Res_Index + 5;
@@ -9946,6 +10207,16 @@ package body Sem_Util is
(Typ : Entity_Id;
Nam : Name_Id) return Entity_Id
is
+ pragma Assert
+ (Is_Type (Typ)
+ and then
+ Nam in Name_Element
+ | Name_First
+ | Name_Has_Element
+ | Name_Last
+ | Name_Next
+ | Name_Previous);
+
Funcs : constant Node_Id := Find_Value_Of_Aspect (Typ, Aspect_Iterable);
Assoc : Node_Id;
@@ -9960,7 +10231,7 @@ package body Sem_Util is
return Entity (Expression (Assoc));
end if;
- Assoc := Next (Assoc);
+ Next (Assoc);
end loop;
return Empty;
@@ -10181,6 +10452,7 @@ package body Sem_Util is
begin
R := N;
while Is_Entity_Name (R)
+ and then Is_Object (Entity (R))
and then Present (Renamed_Object (Entity (R)))
loop
R := Renamed_Object (Entity (R));
@@ -10246,14 +10518,14 @@ package body Sem_Util is
-- Strip the subprogram call
loop
- if Nkind_In (Subp, N_Explicit_Dereference,
- N_Indexed_Component,
- N_Selected_Component)
+ if Nkind (Subp) in N_Explicit_Dereference
+ | N_Indexed_Component
+ | N_Selected_Component
then
Subp := Prefix (Subp);
- elsif Nkind_In (Subp, N_Type_Conversion,
- N_Unchecked_Type_Conversion)
+ elsif Nkind (Subp) in N_Type_Conversion
+ | N_Unchecked_Type_Conversion
then
Subp := Expression (Subp);
@@ -10337,7 +10609,7 @@ package body Sem_Util is
(Typ : Entity_Id;
Priv_Typ : out Entity_Id;
Full_Typ : out Entity_Id;
- Full_Base : out Entity_Id;
+ UFull_Typ : out Entity_Id;
CRec_Typ : out Entity_Id)
is
IP_View : Entity_Id;
@@ -10347,7 +10619,7 @@ package body Sem_Util is
Priv_Typ := Empty;
Full_Typ := Empty;
- Full_Base := Empty;
+ UFull_Typ := Empty;
CRec_Typ := Empty;
-- The input type is the corresponding record type of a protected or a
@@ -10356,10 +10628,9 @@ package body Sem_Util is
if Ekind (Typ) = E_Record_Type
and then Is_Concurrent_Record_Type (Typ)
then
- CRec_Typ := Typ;
- Full_Typ := Corresponding_Concurrent_Type (CRec_Typ);
- Full_Base := Base_Type (Full_Typ);
- Priv_Typ := Incomplete_Or_Partial_View (Full_Typ);
+ CRec_Typ := Typ;
+ Full_Typ := Corresponding_Concurrent_Type (CRec_Typ);
+ Priv_Typ := Incomplete_Or_Partial_View (Full_Typ);
-- Otherwise the input type denotes an arbitrary type
@@ -10384,10 +10655,19 @@ package body Sem_Util is
Full_Typ := Typ;
end if;
- if Present (Full_Typ) then
- Full_Base := Base_Type (Full_Typ);
+ if Present (Full_Typ) and then Is_Private_Type (Full_Typ) then
+ UFull_Typ := Underlying_Full_View (Full_Typ);
+
+ if Present (UFull_Typ)
+ and then Ekind (UFull_Typ) in E_Protected_Type | E_Task_Type
+ then
+ CRec_Typ := Corresponding_Record_Type (UFull_Typ);
+ end if;
- if Ekind_In (Full_Typ, E_Protected_Type, E_Task_Type) then
+ else
+ if Present (Full_Typ)
+ and then Ekind (Full_Typ) in E_Protected_Type | E_Task_Type
+ then
CRec_Typ := Corresponding_Record_Type (Full_Typ);
end if;
end if;
@@ -10781,15 +11061,15 @@ package body Sem_Util is
function Has_Declarations (N : Node_Id) return Boolean is
begin
- return Nkind_In (Nkind (N), N_Accept_Statement,
- N_Block_Statement,
- N_Compilation_Unit_Aux,
- N_Entry_Body,
- N_Package_Body,
- N_Protected_Body,
- N_Subprogram_Body,
- N_Task_Body,
- N_Package_Specification);
+ return Nkind (N) in N_Accept_Statement
+ | N_Block_Statement
+ | N_Compilation_Unit_Aux
+ | N_Entry_Body
+ | N_Package_Body
+ | N_Protected_Body
+ | N_Subprogram_Body
+ | N_Task_Body
+ | N_Package_Specification;
end Has_Declarations;
---------------------------------
@@ -10891,7 +11171,7 @@ package body Sem_Util is
-- Inspect the return type of functions
- if Ekind_In (Subp_Id, E_Function, E_Generic_Function)
+ if Ekind (Subp_Id) in E_Function | E_Generic_Function
and then Is_Effectively_Volatile (Etype (Subp_Id))
then
return True;
@@ -10908,28 +11188,26 @@ package body Sem_Util is
(Item_Id : Entity_Id;
Property : Name_Id) return Boolean
is
- function Protected_Object_Has_Enabled_Property return Boolean;
- -- Determine whether a protected object denoted by Item_Id has the
- -- property enabled.
+ function Protected_Type_Or_Variable_Has_Enabled_Property return Boolean;
+ -- Determine whether a protected type or variable denoted by Item_Id
+ -- has the property enabled.
function State_Has_Enabled_Property return Boolean;
-- Determine whether a state denoted by Item_Id has the property enabled
- function Variable_Has_Enabled_Property return Boolean;
- -- Determine whether a variable denoted by Item_Id has the property
- -- enabled.
-
- -------------------------------------------
- -- Protected_Object_Has_Enabled_Property --
- -------------------------------------------
+ function Type_Or_Variable_Has_Enabled_Property
+ (Item_Id : Entity_Id) return Boolean;
+ -- Determine whether type or variable denoted by Item_Id has the
+ -- property enabled.
- function Protected_Object_Has_Enabled_Property return Boolean is
- Constits : constant Elist_Id := Part_Of_Constituents (Item_Id);
- Constit_Elmt : Elmt_Id;
- Constit_Id : Entity_Id;
+ -----------------------------------------------------
+ -- Protected_Type_Or_Variable_Has_Enabled_Property --
+ -----------------------------------------------------
+ function Protected_Type_Or_Variable_Has_Enabled_Property return Boolean
+ is
begin
- -- Protected objects always have the properties Async_Readers and
+ -- Protected entities always have the properties Async_Readers and
-- Async_Writers (SPARK RM 7.1.2(16)).
if Property = Name_Async_Readers
@@ -10941,21 +11219,30 @@ package body Sem_Util is
-- properties Effective_Reads and Effective_Writes
-- (SPARK RM 7.1.2(16)).
- elsif Present (Constits) then
- Constit_Elmt := First_Elmt (Constits);
- while Present (Constit_Elmt) loop
- Constit_Id := Node (Constit_Elmt);
+ elsif Is_Single_Protected_Object (Item_Id) then
+ declare
+ Constit_Elmt : Elmt_Id;
+ Constit_Id : Entity_Id;
+ Constits : constant Elist_Id
+ := Part_Of_Constituents (Item_Id);
+ begin
+ if Present (Constits) then
+ Constit_Elmt := First_Elmt (Constits);
+ while Present (Constit_Elmt) loop
+ Constit_Id := Node (Constit_Elmt);
- if Has_Enabled_Property (Constit_Id, Property) then
- return True;
- end if;
+ if Has_Enabled_Property (Constit_Id, Property) then
+ return True;
+ end if;
- Next_Elmt (Constit_Elmt);
- end loop;
+ Next_Elmt (Constit_Elmt);
+ end loop;
+ end if;
+ end;
end if;
return False;
- end Protected_Object_Has_Enabled_Property;
+ end Protected_Type_Or_Variable_Has_Enabled_Property;
--------------------------------
-- State_Has_Enabled_Property --
@@ -11111,17 +11398,19 @@ package body Sem_Util is
-- Synchronous (SPARK RM 7.1.4(9)).
elsif Has_Synchronous then
- return Nam_In (Property, Name_Async_Readers, Name_Async_Writers);
+ return Property in Name_Async_Readers | Name_Async_Writers;
end if;
return False;
end State_Has_Enabled_Property;
- -----------------------------------
- -- Variable_Has_Enabled_Property --
- -----------------------------------
+ -------------------------------------------
+ -- Type_Or_Variable_Has_Enabled_Property --
+ -------------------------------------------
- function Variable_Has_Enabled_Property return Boolean is
+ function Type_Or_Variable_Has_Enabled_Property
+ (Item_Id : Entity_Id) return Boolean
+ is
function Is_Enabled (Prag : Node_Id) return Boolean;
-- Determine whether property pragma Prag (if present) denotes an
-- enabled property.
@@ -11169,7 +11458,11 @@ package body Sem_Util is
EW : constant Node_Id :=
Get_Pragma (Item_Id, Pragma_Effective_Writes);
- -- Start of processing for Variable_Has_Enabled_Property
+ Is_Derived_Type_With_Volatile_Parent_Type : constant Boolean :=
+ Is_Derived_Type (Item_Id)
+ and then Is_Effectively_Volatile (Etype (Base_Type (Item_Id)));
+
+ -- Start of processing for Type_Or_Variable_Has_Enabled_Property
begin
-- A non-effectively volatile object can never possess external
@@ -11184,23 +11477,57 @@ package body Sem_Util is
-- property is enabled when the flag evaluates to True or the flag is
-- missing altogether.
- elsif Property = Name_Async_Readers and then Is_Enabled (AR) then
- return True;
+ elsif Property = Name_Async_Readers and then Present (AR) then
+ return Is_Enabled (AR);
- elsif Property = Name_Async_Writers and then Is_Enabled (AW) then
- return True;
+ elsif Property = Name_Async_Writers and then Present (AW) then
+ return Is_Enabled (AW);
- elsif Property = Name_Effective_Reads and then Is_Enabled (ER) then
- return True;
+ elsif Property = Name_Effective_Reads and then Present (ER) then
+ return Is_Enabled (ER);
- elsif Property = Name_Effective_Writes and then Is_Enabled (EW) then
- return True;
+ elsif Property = Name_Effective_Writes and then Present (EW) then
+ return Is_Enabled (EW);
+
+ -- If other properties are set explicitly, then this one is set
+ -- implicitly to False, except in the case of a derived type
+ -- whose parent type is volatile (in that case, we will inherit
+ -- from the parent type, below).
+
+ elsif (Present (AR)
+ or else Present (AW)
+ or else Present (ER)
+ or else Present (EW))
+ and then not Is_Derived_Type_With_Volatile_Parent_Type
+ then
+ return False;
+
+ -- For a private type, may need to look at the full view
+
+ elsif Is_Private_Type (Item_Id) and then Present (Full_View (Item_Id))
+ then
+ return Type_Or_Variable_Has_Enabled_Property (Full_View (Item_Id));
+
+ -- For a derived type whose parent type is volatile, the
+ -- property may be inherited (but ignore a non-volatile parent).
+
+ elsif Is_Derived_Type_With_Volatile_Parent_Type then
+ return Type_Or_Variable_Has_Enabled_Property
+ (First_Subtype (Etype (Base_Type (Item_Id))));
+
+ -- If not specified explicitly for an object and the type
+ -- is effectively volatile, then take result from the type.
+
+ elsif not Is_Type (Item_Id)
+ and then Is_Effectively_Volatile (Etype (Item_Id))
+ then
+ return Has_Enabled_Property (Etype (Item_Id), Property);
-- The implicit case lacks all property pragmas
elsif No (AR) and then No (AW) and then No (ER) and then No (EW) then
if Is_Protected_Type (Etype (Item_Id)) then
- return Protected_Object_Has_Enabled_Property;
+ return Protected_Type_Or_Variable_Has_Enabled_Property;
else
return True;
end if;
@@ -11208,7 +11535,7 @@ package body Sem_Util is
else
return False;
end if;
- end Variable_Has_Enabled_Property;
+ end Type_Or_Variable_Has_Enabled_Property;
-- Start of processing for Has_Enabled_Property
@@ -11220,15 +11547,19 @@ package body Sem_Util is
return State_Has_Enabled_Property;
elsif Ekind (Item_Id) = E_Variable then
- return Variable_Has_Enabled_Property;
+ return Type_Or_Variable_Has_Enabled_Property (Item_Id);
- -- By default, protected objects only have the properties Async_Readers
- -- and Async_Writers. If they have Part_Of components, they also inherit
- -- their properties Effective_Reads and Effective_Writes
- -- (SPARK RM 7.1.2(16)).
+ -- Other objects can only inherit properties through their type. We
+ -- cannot call directly Type_Or_Variable_Has_Enabled_Property on
+ -- these as they don't have contracts attached, which is expected by
+ -- this function.
- elsif Ekind (Item_Id) = E_Protected_Object then
- return Protected_Object_Has_Enabled_Property;
+ elsif Is_Object (Item_Id) then
+ return Type_Or_Variable_Has_Enabled_Property (Etype (Item_Id));
+
+ elsif Is_Type (Item_Id) then
+ return Type_Or_Variable_Has_Enabled_Property
+ (Item_Id => First_Subtype (Item_Id));
-- Otherwise a property is enabled when the related item is effectively
-- volatile.
@@ -11286,17 +11617,16 @@ package body Sem_Util is
-- Inspect all entities defined in the scope of the type, looking for
-- uninitialized components.
- Comp := First_Entity (Typ);
+ Comp := First_Component (Typ);
while Present (Comp) loop
- if Ekind (Comp) = E_Component
- and then Comes_From_Source (Comp)
+ if Comes_From_Source (Comp)
and then No (Expression (Parent (Comp)))
and then not Has_Full_Default_Initialization (Etype (Comp))
then
return False;
end if;
- Next_Entity (Comp);
+ Next_Component (Comp);
end loop;
-- Ensure that the parent type of a type extension is fully default
@@ -11490,12 +11820,10 @@ package body Sem_Util is
elsif Nkind (N) in N_Has_Entity then
return Present (Entity (N))
- and then Ekind_In (Entity (N), E_Variable,
- E_Constant,
- E_Enumeration_Literal,
- E_In_Parameter,
- E_Out_Parameter,
- E_In_Out_Parameter)
+ and then
+ Ekind (Entity (N)) in
+ E_Variable | E_Constant | E_Enumeration_Literal |
+ E_In_Parameter | E_Out_Parameter | E_In_Out_Parameter
and then not Is_Volatile (Entity (N));
else
@@ -11534,7 +11862,7 @@ package body Sem_Util is
Node := First (L);
loop
- if Nkind (Node) /= N_Null_Statement then
+ if Nkind (Node) not in N_Null_Statement | N_Call_Marker then
return True;
end if;
@@ -11547,6 +11875,104 @@ package body Sem_Util is
end Has_Non_Null_Statements;
----------------------------------
+ -- Is_Access_Subprogram_Wrapper --
+ ----------------------------------
+
+ function Is_Access_Subprogram_Wrapper (E : Entity_Id) return Boolean is
+ Formal : constant Entity_Id := Last_Formal (E);
+ begin
+ return Present (Formal)
+ and then Ekind (Etype (Formal)) in Access_Subprogram_Kind
+ and then Access_Subprogram_Wrapper
+ (Directly_Designated_Type (Etype (Formal))) = E;
+ end Is_Access_Subprogram_Wrapper;
+
+ ---------------------------------
+ -- Side_Effect_Free_Statements --
+ ---------------------------------
+
+ function Side_Effect_Free_Statements (L : List_Id) return Boolean is
+ Node : Node_Id;
+
+ begin
+ if Is_Non_Empty_List (L) then
+ Node := First (L);
+
+ loop
+ case Nkind (Node) is
+ when N_Null_Statement | N_Call_Marker | N_Raise_xxx_Error =>
+ null;
+ when N_Object_Declaration =>
+ if Present (Expression (Node))
+ and then not Side_Effect_Free (Expression (Node))
+ then
+ return False;
+ end if;
+
+ when others =>
+ return False;
+ end case;
+
+ Next (Node);
+ exit when Node = Empty;
+ end loop;
+ end if;
+
+ return True;
+ end Side_Effect_Free_Statements;
+
+ ---------------------------
+ -- Side_Effect_Free_Loop --
+ ---------------------------
+
+ function Side_Effect_Free_Loop (N : Node_Id) return Boolean is
+ Scheme : Node_Id;
+ Spec : Node_Id;
+ Subt : Node_Id;
+
+ begin
+ -- If this is not a loop (e.g. because the loop has been rewritten),
+ -- then return false.
+
+ if Nkind (N) /= N_Loop_Statement then
+ return False;
+ end if;
+
+ -- First check the statements
+
+ if Side_Effect_Free_Statements (Statements (N)) then
+
+ -- Then check the loop condition/indexes
+
+ if Present (Iteration_Scheme (N)) then
+ Scheme := Iteration_Scheme (N);
+
+ if Present (Condition (Scheme))
+ or else Present (Iterator_Specification (Scheme))
+ then
+ return False;
+ elsif Present (Loop_Parameter_Specification (Scheme)) then
+ Spec := Loop_Parameter_Specification (Scheme);
+ Subt := Discrete_Subtype_Definition (Spec);
+
+ if Present (Subt) then
+ if Nkind (Subt) = N_Range then
+ return Side_Effect_Free (Low_Bound (Subt))
+ and then Side_Effect_Free (High_Bound (Subt));
+ else
+ -- subtype indication
+
+ return True;
+ end if;
+ end if;
+ end if;
+ end if;
+ end if;
+
+ return False;
+ end Side_Effect_Free_Loop;
+
+ ----------------------------------
-- Has_Non_Trivial_Precondition --
----------------------------------
@@ -11639,7 +12065,6 @@ package body Sem_Util is
when N_Component_Definition
| N_Formal_Object_Declaration
- | N_Object_Renaming_Declaration
=>
if Present (Subtype_Mark (N)) then
return Null_Exclusion_Present (N);
@@ -11647,6 +12072,15 @@ package body Sem_Util is
return Null_Exclusion_Present (Access_Definition (N));
end if;
+ when N_Object_Renaming_Declaration =>
+ if Present (Subtype_Mark (N)) then
+ return Null_Exclusion_Present (N);
+ elsif Present (Access_Definition (N)) then
+ return Null_Exclusion_Present (Access_Definition (N));
+ else
+ return False; -- Case of no subtype in renaming (AI12-0275)
+ end if;
+
when N_Discriminant_Specification =>
if Nkind (Discriminant_Type (N)) = N_Access_Definition then
return Null_Exclusion_Present (Discriminant_Type (N));
@@ -11663,7 +12097,8 @@ package body Sem_Util is
when N_Parameter_Specification =>
if Nkind (Parameter_Type (N)) = N_Access_Definition then
- return Null_Exclusion_Present (Parameter_Type (N));
+ return Null_Exclusion_Present (Parameter_Type (N))
+ or else Null_Exclusion_Present (N);
else
return Null_Exclusion_Present (N);
end if;
@@ -11975,14 +12410,10 @@ package body Sem_Util is
function Has_Prefix (N : Node_Id) return Boolean is
begin
- return
- Nkind_In (N, N_Attribute_Reference,
- N_Expanded_Name,
- N_Explicit_Dereference,
- N_Indexed_Component,
- N_Reference,
- N_Selected_Component,
- N_Slice);
+ return Nkind (N) in
+ N_Attribute_Reference | N_Expanded_Name | N_Explicit_Dereference |
+ N_Indexed_Component | N_Reference | N_Selected_Component |
+ N_Slice;
end Has_Prefix;
---------------------------
@@ -12046,6 +12477,147 @@ package body Sem_Util is
end if;
end Has_Private_Component;
+ --------------------------------
+ -- Has_Relaxed_Initialization --
+ --------------------------------
+
+ function Has_Relaxed_Initialization (E : Entity_Id) return Boolean is
+
+ function Denotes_Relaxed_Parameter
+ (Expr : Node_Id;
+ Param : Entity_Id)
+ return Boolean;
+ -- Returns True iff expression Expr denotes a formal parameter or
+ -- function Param (through its attribute Result).
+
+ -------------------------------
+ -- Denotes_Relaxed_Parameter --
+ -------------------------------
+
+ function Denotes_Relaxed_Parameter
+ (Expr : Node_Id;
+ Param : Entity_Id) return Boolean is
+ begin
+ if Nkind (Expr) in N_Identifier | N_Expanded_Name then
+ return Entity (Expr) = Param;
+ else
+ pragma Assert (Is_Attribute_Result (Expr));
+ return Entity (Prefix (Expr)) = Param;
+ end if;
+ end Denotes_Relaxed_Parameter;
+
+ -- Start of processing for Has_Relaxed_Initialization
+
+ begin
+ -- When analyzing, we checked all syntax legality rules for the aspect
+ -- Relaxed_Initialization, but didn't store the property anywhere (e.g.
+ -- as an Einfo flag). To query the property we look directly at the AST,
+ -- but now without any syntactic checks.
+
+ case Ekind (E) is
+ -- Abstract states have option Relaxed_Initialization
+
+ when E_Abstract_State =>
+ return Is_Relaxed_Initialization_State (E);
+
+ -- Constants have this aspect attached directly; for deferred
+ -- constants, the aspect is attached to the partial view.
+
+ when E_Constant =>
+ return Has_Aspect (E, Aspect_Relaxed_Initialization);
+
+ -- Variables have this aspect attached directly
+
+ when E_Variable =>
+ return Has_Aspect (E, Aspect_Relaxed_Initialization);
+
+ -- Types have this aspect attached directly (though we only allow it
+ -- to be specified for the first subtype). For private types, the
+ -- aspect is attached to the partial view.
+
+ when Type_Kind =>
+ pragma Assert (Is_First_Subtype (E));
+ return Has_Aspect (E, Aspect_Relaxed_Initialization);
+
+ -- Formal parameters and functions have the Relaxed_Initialization
+ -- aspect attached to the subprogram entity and must be listed in
+ -- the aspect expression.
+
+ when Formal_Kind
+ | E_Function
+ =>
+ declare
+ Subp_Id : Entity_Id;
+ Aspect_Expr : Node_Id;
+ Param_Expr : Node_Id;
+ Assoc : Node_Id;
+
+ begin
+ if Is_Formal (E) then
+ Subp_Id := Scope (E);
+ else
+ Subp_Id := E;
+ end if;
+
+ if Has_Aspect (Subp_Id, Aspect_Relaxed_Initialization) then
+ Aspect_Expr :=
+ Find_Value_Of_Aspect
+ (Subp_Id, Aspect_Relaxed_Initialization);
+
+ -- Aspect expression is either an aggregate with an optional
+ -- Boolean expression (which defaults to True), e.g.:
+ --
+ -- function F (X : Integer) return Integer
+ -- with Relaxed_Initialization => (X => True, F'Result);
+
+ if Nkind (Aspect_Expr) = N_Aggregate then
+
+ if Present (Component_Associations (Aspect_Expr)) then
+ Assoc := First (Component_Associations (Aspect_Expr));
+
+ while Present (Assoc) loop
+ if Denotes_Relaxed_Parameter
+ (First (Choices (Assoc)), E)
+ then
+ return
+ Is_True
+ (Static_Boolean (Expression (Assoc)));
+ end if;
+
+ Next (Assoc);
+ end loop;
+ end if;
+
+ Param_Expr := First (Expressions (Aspect_Expr));
+
+ while Present (Param_Expr) loop
+ if Denotes_Relaxed_Parameter (Param_Expr, E) then
+ return True;
+ end if;
+
+ Next (Param_Expr);
+ end loop;
+
+ return False;
+
+ -- or it is a single identifier, e.g.:
+ --
+ -- function F (X : Integer) return Integer
+ -- with Relaxed_Initialization => X;
+
+ else
+ return Denotes_Relaxed_Parameter (Aspect_Expr, E);
+ end if;
+ else
+ return False;
+ end if;
+ end;
+
+ when others =>
+ raise Program_Error;
+ end case;
+ end Has_Relaxed_Initialization;
+
----------------------
-- Has_Signed_Zeros --
----------------------
@@ -12217,13 +12789,9 @@ package body Sem_Util is
begin
pragma Assert (Relaxed_RM_Semantics);
- pragma Assert (Nkind_In (N, N_Null,
- N_Op_Eq,
- N_Op_Ge,
- N_Op_Gt,
- N_Op_Le,
- N_Op_Lt,
- N_Op_Ne));
+ pragma Assert
+ (Nkind (N) in
+ N_Null | N_Op_Eq | N_Op_Ge | N_Op_Gt | N_Op_Le | N_Op_Lt | N_Op_Ne);
if Nkind (N) = N_Null then
Rewrite (N, New_Occurrence_Of (RTE (RE_Null_Address), Sloc (N)));
@@ -12274,6 +12842,32 @@ package body Sem_Util is
end if;
end Has_Tagged_Component;
+ --------------------------------------------
+ -- Has_Unconstrained_Access_Discriminants --
+ --------------------------------------------
+
+ function Has_Unconstrained_Access_Discriminants
+ (Subtyp : Entity_Id) return Boolean
+ is
+ Discr : Entity_Id;
+
+ begin
+ if Has_Discriminants (Subtyp)
+ and then not Is_Constrained (Subtyp)
+ then
+ Discr := First_Discriminant (Subtyp);
+ while Present (Discr) loop
+ if Ekind (Etype (Discr)) = E_Anonymous_Access_Type then
+ return True;
+ end if;
+
+ Next_Discriminant (Discr);
+ end loop;
+ end if;
+
+ return False;
+ end Has_Unconstrained_Access_Discriminants;
+
-----------------------------
-- Has_Undefined_Reference --
-----------------------------
@@ -12336,7 +12930,7 @@ package body Sem_Util is
return True;
end if;
- Comp := Next_Component (Comp);
+ Next_Component (Comp);
end loop;
end if;
@@ -12402,6 +12996,32 @@ package body Sem_Util is
return False;
end Implements_Interface;
+ --------------------------------
+ -- Implicitly_Designated_Type --
+ --------------------------------
+
+ function Implicitly_Designated_Type (Typ : Entity_Id) return Entity_Id is
+ Desig : constant Entity_Id := Designated_Type (Typ);
+
+ begin
+ -- An implicit dereference is a legal occurrence of an incomplete type
+ -- imported through a limited_with clause, if the full view is visible.
+
+ if Is_Incomplete_Type (Desig)
+ and then From_Limited_With (Desig)
+ and then not From_Limited_With (Scope (Desig))
+ and then
+ (Is_Immediately_Visible (Scope (Desig))
+ or else
+ (Is_Child_Unit (Scope (Desig))
+ and then Is_Visible_Lib_Unit (Scope (Desig))))
+ then
+ return Available_View (Desig);
+ else
+ return Desig;
+ end if;
+ end Implicitly_Designated_Type;
+
------------------------------------
-- In_Assertion_Expression_Pragma --
------------------------------------
@@ -12519,7 +13139,7 @@ package body Sem_Util is
begin
S := Current_Scope;
while Present (S) and then S /= Standard_Standard loop
- if Ekind_In (S, E_Function, E_Procedure)
+ if Ekind (S) in E_Function | E_Procedure
and then Is_Generic_Instance (S)
then
return True;
@@ -12547,7 +13167,7 @@ package body Sem_Util is
begin
S := Current_Scope;
while Present (S) and then S /= Standard_Standard loop
- if Ekind_In (S, E_Function, E_Procedure)
+ if Ekind (S) in E_Function | E_Procedure
and then Is_Generic_Instance (S)
then
return True;
@@ -12751,15 +13371,15 @@ package body Sem_Util is
if Nod = Cont then
return True;
- elsif Nkind_In (Nod, N_Accept_Statement,
- N_Block_Statement,
- N_Compilation_Unit,
- N_Entry_Body,
- N_Package_Body,
- N_Package_Declaration,
- N_Protected_Body,
- N_Subprogram_Body,
- N_Task_Body)
+ elsif Nkind (Nod) in N_Accept_Statement
+ | N_Block_Statement
+ | N_Compilation_Unit
+ | N_Entry_Body
+ | N_Package_Body
+ | N_Package_Declaration
+ | N_Protected_Body
+ | N_Subprogram_Body
+ | N_Task_Body
then
return False;
@@ -12924,9 +13544,9 @@ package body Sem_Util is
-- declaration hold the partial view and the full view is an
-- itype.
- elsif Nkind_In (Decl, N_Full_Type_Declaration,
- N_Private_Extension_Declaration,
- N_Private_Type_Declaration)
+ elsif Nkind (Decl) in N_Full_Type_Declaration
+ | N_Private_Extension_Declaration
+ | N_Private_Type_Declaration
then
Match := Defining_Identifier (Decl);
end if;
@@ -12974,7 +13594,7 @@ package body Sem_Util is
begin
if Present (Pkg)
- and then Ekind_In (Pkg, E_Generic_Package, E_Package)
+ and then Is_Package_Or_Generic_Package (Pkg)
then
while Nkind (Pkg_Decl) /= N_Package_Specification loop
Pkg_Decl := Parent (Pkg_Decl);
@@ -13032,13 +13652,13 @@ package body Sem_Util is
Ent : Entity_Id := First_Entity (Limited_View (Scope (Typ)));
begin
while Present (Ent) loop
- if Ekind (Ent) in Incomplete_Kind
+ if Is_Incomplete_Type (Ent)
and then Non_Limited_View (Ent) = Typ
then
return Ent;
end if;
- Ent := Next_Entity (Ent);
+ Next_Entity (Ent);
end loop;
end;
end if;
@@ -13099,6 +13719,38 @@ package body Sem_Util is
return Off * (Expr_Value (Exp) - Expr_Value (Low_Bound ((Ind))));
end Indexed_Component_Bit_Offset;
+ -----------------------------
+ -- Inherit_Predicate_Flags --
+ -----------------------------
+
+ procedure Inherit_Predicate_Flags (Subt, Par : Entity_Id) is
+ begin
+ if Present (Predicate_Function (Subt)) then
+ return;
+ end if;
+
+ Set_Has_Predicates (Subt, Has_Predicates (Par));
+ Set_Has_Static_Predicate_Aspect
+ (Subt, Has_Static_Predicate_Aspect (Par));
+ Set_Has_Dynamic_Predicate_Aspect
+ (Subt, Has_Dynamic_Predicate_Aspect (Par));
+
+ -- A named subtype does not inherit the predicate function of its
+ -- parent but an itype declared for a loop index needs the discrete
+ -- predicate information of its parent to execute the loop properly.
+ -- A non-discrete type may has a static predicate (for example True)
+ -- but has no static_discrete_predicate.
+
+ if Is_Itype (Subt) and then Present (Predicate_Function (Par)) then
+ Set_Subprograms_For_Type (Subt, Subprograms_For_Type (Par));
+
+ if Has_Static_Predicate (Par) and then Is_Discrete_Type (Par) then
+ Set_Static_Discrete_Predicate
+ (Subt, Static_Discrete_Predicate (Par));
+ end if;
+ end if;
+ end Inherit_Predicate_Flags;
+
----------------------------
-- Inherit_Rep_Item_Chain --
----------------------------
@@ -13265,7 +13917,7 @@ package body Sem_Util is
procedure Insert_Explicit_Dereference (N : Node_Id) is
New_Prefix : constant Node_Id := Relocate_Node (N);
Ent : Entity_Id := Empty;
- Pref : Node_Id;
+ Pref : Node_Id := Empty;
I : Interp_Index;
It : Interp;
T : Entity_Id;
@@ -13311,13 +13963,12 @@ package body Sem_Util is
-- For a retrieval of a subcomponent of some composite object,
-- retrieve the ultimate entity if there is one.
- elsif Nkind_In (New_Prefix, N_Selected_Component,
- N_Indexed_Component)
+ elsif Nkind (New_Prefix) in N_Selected_Component | N_Indexed_Component
then
Pref := Prefix (New_Prefix);
while Present (Pref)
- and then Nkind_In (Pref, N_Selected_Component,
- N_Indexed_Component)
+ and then Nkind (Pref) in
+ N_Selected_Component | N_Indexed_Component
loop
Pref := Prefix (Pref);
end loop;
@@ -13366,7 +14017,7 @@ package body Sem_Util is
Defining_Identifier (Decl));
end if;
- Decl := Next (Decl);
+ Next (Decl);
end loop;
end Inspect_Deferred_Constant_Completion;
@@ -13591,6 +14242,28 @@ package body Sem_Util is
end if;
end Invalid_Scalar_Value;
+ --------------------------------
+ -- Is_Anonymous_Access_Actual --
+ --------------------------------
+
+ function Is_Anonymous_Access_Actual (N : Node_Id) return Boolean is
+ Par : Node_Id;
+ begin
+ if Ekind (Etype (N)) /= E_Anonymous_Access_Type then
+ return False;
+ end if;
+
+ Par := Parent (N);
+ while Present (Par)
+ and then Nkind (Par) in N_Case_Expression
+ | N_If_Expression
+ | N_Parameter_Association
+ loop
+ Par := Parent (Par);
+ end loop;
+ return Nkind (Par) in N_Subprogram_Call;
+ end Is_Anonymous_Access_Actual;
+
-----------------------------
-- Is_Actual_Out_Parameter --
-----------------------------
@@ -13603,6 +14276,18 @@ package body Sem_Util is
return Present (Formal) and then Ekind (Formal) = E_Out_Parameter;
end Is_Actual_Out_Parameter;
+ --------------------------------
+ -- Is_Actual_In_Out_Parameter --
+ --------------------------------
+
+ function Is_Actual_In_Out_Parameter (N : Node_Id) return Boolean is
+ Formal : Entity_Id;
+ Call : Node_Id;
+ begin
+ Find_Actual (N, Formal, Call);
+ return Present (Formal) and then Ekind (Formal) = E_In_Out_Parameter;
+ end Is_Actual_In_Out_Parameter;
+
-------------------------
-- Is_Actual_Parameter --
-------------------------
@@ -13688,10 +14373,17 @@ package body Sem_Util is
and then Has_Aliased_Components
(Designated_Type (Etype (Prefix (Obj)))));
- elsif Nkind_In (Obj, N_Unchecked_Type_Conversion, N_Type_Conversion) then
+ elsif Nkind (Obj) in N_Unchecked_Type_Conversion | N_Type_Conversion then
return Is_Tagged_Type (Etype (Obj))
and then Is_Aliased_View (Expression (Obj));
+ -- Ada 202x AI12-0228
+
+ elsif Nkind (Obj) = N_Qualified_Expression
+ and then Ada_Version >= Ada_2012
+ then
+ return Is_Aliased_View (Expression (Obj));
+
elsif Nkind (Obj) = N_Explicit_Dereference then
return Nkind (Original_Node (Obj)) /= N_Function_Call;
@@ -13796,6 +14488,16 @@ package body Sem_Util is
return Is_Atomic_Object (N) or else Is_Volatile_Full_Access_Object (N);
end Is_Atomic_Or_VFA_Object;
+ -----------------------------
+ -- Is_Attribute_Loop_Entry --
+ -----------------------------
+
+ function Is_Attribute_Loop_Entry (N : Node_Id) return Boolean is
+ begin
+ return Nkind (N) = N_Attribute_Reference
+ and then Attribute_Name (N) = Name_Loop_Entry;
+ end Is_Attribute_Loop_Entry;
+
----------------------
-- Is_Attribute_Old --
----------------------
@@ -13854,6 +14556,17 @@ package body Sem_Util is
Is_RTE (Root_Type (Under), RO_WW_Super_String));
end Is_Bounded_String;
+ -------------------------------
+ -- Is_By_Protected_Procedure --
+ -------------------------------
+
+ function Is_By_Protected_Procedure (Id : Entity_Id) return Boolean is
+ begin
+ return Ekind (Id) = E_Procedure
+ and then Present (Get_Rep_Pragma (Id, Name_Implemented))
+ and then Implementation_Kind (Id) = Name_By_Protected_Procedure;
+ end Is_By_Protected_Procedure;
+
---------------------
-- Is_CCT_Instance --
---------------------
@@ -13863,21 +14576,17 @@ package body Sem_Util is
Context_Id : Entity_Id) return Boolean
is
begin
- pragma Assert (Ekind_In (Ref_Id, E_Protected_Type, E_Task_Type));
+ pragma Assert (Ekind (Ref_Id) in E_Protected_Type | E_Task_Type);
if Is_Single_Task_Object (Context_Id) then
return Scope_Within_Or_Same (Etype (Context_Id), Ref_Id);
else
- pragma Assert (Ekind_In (Context_Id, E_Entry,
- E_Entry_Family,
- E_Function,
- E_Package,
- E_Procedure,
- E_Protected_Type,
- E_Task_Type)
- or else
- Is_Record_Type (Context_Id));
+ pragma Assert
+ (Ekind (Context_Id) in
+ E_Entry | E_Entry_Family | E_Function | E_Package |
+ E_Procedure | E_Protected_Type | E_Task_Type
+ or else Is_Record_Type (Context_Id));
return Scope_Within_Or_Same (Context_Id, Ref_Id);
end if;
end Is_CCT_Instance;
@@ -14191,10 +14900,10 @@ package body Sem_Util is
elsif Nkind (Parent (Par)) = N_Object_Renaming_Declaration then
return False;
- elsif Nkind_In
- (Nkind (Parent (Par)), N_Function_Call,
- N_Procedure_Call_Statement,
- N_Entry_Call_Statement)
+ elsif Nkind (Parent (Par)) in
+ N_Function_Call |
+ N_Procedure_Call_Statement |
+ N_Entry_Call_Statement
then
-- Check that the element is not part of an actual for an
-- in-out parameter.
@@ -14354,9 +15063,9 @@ package body Sem_Util is
P := Parent (N);
while Present (P) loop
- if Nkind_In (P, N_Full_Type_Declaration,
- N_Private_Type_Declaration,
- N_Subtype_Declaration)
+ if Nkind (P) in N_Full_Type_Declaration
+ | N_Private_Type_Declaration
+ | N_Subtype_Declaration
and then Comes_From_Source (P)
and then Defining_Entity (P) = Typ
then
@@ -14388,6 +15097,59 @@ package body Sem_Util is
return False;
end Is_Current_Instance;
+ --------------------------------------------------
+ -- Is_Current_Instance_Reference_In_Type_Aspect --
+ --------------------------------------------------
+
+ function Is_Current_Instance_Reference_In_Type_Aspect
+ (N : Node_Id) return Boolean
+ is
+ begin
+ -- When a current_instance is referenced within an aspect_specification
+ -- of a type or subtype, it will show up as a reference to the formal
+ -- parameter of the aspect's associated subprogram rather than as a
+ -- reference to the type or subtype itself (in fact, the original name
+ -- is never even analyzed). We check for predicate, invariant, and
+ -- Default_Initial_Condition subprograms (in theory there could be
+ -- other cases added, in which case this function will need updating).
+
+ if Is_Entity_Name (N) then
+ return Present (Entity (N))
+ and then Ekind (Entity (N)) = E_In_Parameter
+ and then Ekind (Scope (Entity (N))) in E_Function | E_Procedure
+ and then
+ (Is_Predicate_Function (Scope (Entity (N)))
+ or else Is_Predicate_Function_M (Scope (Entity (N)))
+ or else Is_Invariant_Procedure (Scope (Entity (N)))
+ or else Is_Partial_Invariant_Procedure (Scope (Entity (N)))
+ or else Is_DIC_Procedure (Scope (Entity (N))));
+
+ else
+ case Nkind (N) is
+ when N_Indexed_Component
+ | N_Slice
+ =>
+ return
+ Is_Current_Instance_Reference_In_Type_Aspect (Prefix (N));
+
+ when N_Selected_Component =>
+ return
+ Is_Current_Instance_Reference_In_Type_Aspect (Prefix (N));
+
+ when N_Type_Conversion =>
+ return Is_Current_Instance_Reference_In_Type_Aspect
+ (Expression (N));
+
+ when N_Qualified_Expression =>
+ return Is_Current_Instance_Reference_In_Type_Aspect
+ (Expression (N));
+
+ when others =>
+ return False;
+ end case;
+ end if;
+ end Is_Current_Instance_Reference_In_Type_Aspect;
+
--------------------
-- Is_Declaration --
--------------------
@@ -14531,13 +15293,14 @@ package body Sem_Util is
begin
-- Find the dereference node if any
- while Nkind_In (Deref, N_Indexed_Component,
- N_Selected_Component,
- N_Slice)
+ while Nkind (Deref) in
+ N_Indexed_Component | N_Selected_Component | N_Slice
loop
Deref := Prefix (Deref);
end loop;
+ Deref := Original_Node (Deref);
+
-- If the prefix is a qualified expression of a variable, then function
-- Is_Variable will return False for that because a qualified expression
-- denotes a constant view, so we need to get the name being qualified
@@ -14555,9 +15318,11 @@ package body Sem_Util is
if Is_Variable (Object)
or else Is_Variable (Deref)
- or else (Ada_Version >= Ada_2005
- and then (Nkind (Deref) = N_Explicit_Dereference
- or else Is_Access_Type (Etype (Deref))))
+ or else
+ (Ada_Version >= Ada_2005
+ and then (Nkind (Deref) = N_Explicit_Dereference
+ or else (Present (Etype (Deref))
+ and then Is_Access_Type (Etype (Deref)))))
then
if Nkind (Object) = N_Selected_Component then
@@ -14565,8 +15330,8 @@ package body Sem_Util is
-- False (it could be a function selector in a prefix form call
-- occurring in an iterator specification).
- if not Ekind_In (Entity (Selector_Name (Object)), E_Component,
- E_Discriminant)
+ if Ekind (Entity (Selector_Name (Object))) not in
+ E_Component | E_Discriminant
then
return False;
end if;
@@ -14732,10 +15497,10 @@ package body Sem_Util is
function Is_Dereferenced (N : Node_Id) return Boolean is
P : constant Node_Id := Parent (N);
begin
- return Nkind_In (P, N_Selected_Component,
- N_Explicit_Dereference,
- N_Indexed_Component,
- N_Slice)
+ return Nkind (P) in N_Selected_Component
+ | N_Explicit_Dereference
+ | N_Indexed_Component
+ | N_Slice
and then Prefix (P) = N;
end Is_Dereferenced;
@@ -14867,22 +15632,24 @@ package body Sem_Util is
-- effectively volatile.
elsif Is_Array_Type (Id) then
- declare
- Anc : Entity_Id := Base_Type (Id);
- begin
- if Is_Private_Type (Anc) then
- Anc := Full_View (Anc);
- end if;
+ if Has_Volatile_Components (Id) then
+ return True;
+ else
+ declare
+ Anc : Entity_Id := Base_Type (Id);
+ begin
+ if Is_Private_Type (Anc) then
+ Anc := Full_View (Anc);
+ end if;
- -- Test for presence of ancestor, as the full view of a private
- -- type may be missing in case of error.
+ -- Test for presence of ancestor, as the full view of a
+ -- private type may be missing in case of error.
- return
- Has_Volatile_Components (Id)
- or else
- (Present (Anc)
- and then Is_Effectively_Volatile (Component_Type (Anc)));
- end;
+ return
+ Present (Anc)
+ and then Is_Effectively_Volatile (Component_Type (Anc));
+ end;
+ end if;
-- A protected type is always volatile
@@ -14903,12 +15670,14 @@ package body Sem_Util is
-- Otherwise Id denotes an object
- else
+ else pragma Assert (Is_Object (Id));
-- A volatile object for which No_Caching is enabled is not
-- effectively volatile.
return
- (Is_Volatile (Id) and then not No_Caching_Enabled (Id))
+ (Is_Volatile (Id)
+ and then not
+ (Ekind (Id) = E_Variable and then No_Caching_Enabled (Id)))
or else Has_Volatile_Components (Id)
or else Is_Effectively_Volatile (Etype (Id));
end if;
@@ -14921,9 +15690,10 @@ package body Sem_Util is
function Is_Effectively_Volatile_Object (N : Node_Id) return Boolean is
begin
if Is_Entity_Name (N) then
- return Is_Effectively_Volatile (Entity (N));
+ return Is_Object (Entity (N))
+ and then Is_Effectively_Volatile (Entity (N));
- elsif Nkind (N) = N_Indexed_Component then
+ elsif Nkind (N) in N_Indexed_Component | N_Slice then
return Is_Effectively_Volatile_Object (Prefix (N));
elsif Nkind (N) = N_Selected_Component then
@@ -14932,6 +15702,12 @@ package body Sem_Util is
or else
Is_Effectively_Volatile_Object (Selector_Name (N));
+ elsif Nkind (N) in N_Qualified_Expression
+ | N_Unchecked_Type_Conversion
+ | N_Type_Conversion
+ then
+ return Is_Effectively_Volatile_Object (Expression (N));
+
else
return False;
end if;
@@ -14944,7 +15720,7 @@ package body Sem_Util is
function Is_Entry_Body (Id : Entity_Id) return Boolean is
begin
return
- Ekind_In (Id, E_Entry, E_Entry_Family)
+ Is_Entry (Id)
and then Nkind (Unit_Declaration_Node (Id)) = N_Entry_Body;
end Is_Entry_Body;
@@ -14955,7 +15731,7 @@ package body Sem_Util is
function Is_Entry_Declaration (Id : Entity_Id) return Boolean is
begin
return
- Ekind_In (Id, E_Entry, E_Entry_Family)
+ Is_Entry (Id)
and then Nkind (Unit_Declaration_Node (Id)) = N_Entry_Declaration;
end Is_Entry_Declaration;
@@ -14979,7 +15755,7 @@ package body Sem_Util is
function Is_Expression_Function (Subp : Entity_Id) return Boolean is
begin
- if Ekind_In (Subp, E_Function, E_Subprogram_Body) then
+ if Ekind (Subp) in E_Function | E_Subprogram_Body then
return
Nkind (Original_Node (Unit_Declaration_Node (Subp))) =
N_Expression_Function;
@@ -15074,9 +15850,9 @@ package body Sem_Util is
-- A qualified expression or a type conversion is an EVF expression when
-- its operand is an EVF expression.
- elsif Nkind_In (N, N_Qualified_Expression,
- N_Unchecked_Type_Conversion,
- N_Type_Conversion)
+ elsif Nkind (N) in N_Qualified_Expression
+ | N_Unchecked_Type_Conversion
+ | N_Type_Conversion
then
return Is_EVF_Expression (Expression (N));
@@ -15084,9 +15860,9 @@ package body Sem_Util is
-- their prefix denotes an EVF expression.
elsif Nkind (N) = N_Attribute_Reference
- and then Nam_In (Attribute_Name (N), Name_Loop_Entry,
- Name_Old,
- Name_Update)
+ and then Attribute_Name (N) in Name_Loop_Entry
+ | Name_Old
+ | Name_Update
then
return Is_EVF_Expression (Prefix (N));
end if;
@@ -15412,14 +16188,14 @@ package body Sem_Util is
begin
-- Package/subprogram body
- if Nkind_In (Decl, N_Package_Body, N_Subprogram_Body)
+ if Nkind (Decl) in N_Package_Body | N_Subprogram_Body
and then Present (Corresponding_Spec (Decl))
then
Spec_Decl := Unit_Declaration_Node (Corresponding_Spec (Decl));
-- Package/subprogram body stub
- elsif Nkind_In (Decl, N_Package_Body_Stub, N_Subprogram_Body_Stub)
+ elsif Nkind (Decl) in N_Package_Body_Stub | N_Subprogram_Body_Stub
and then Present (Corresponding_Spec_Of_Stub (Decl))
then
Spec_Decl :=
@@ -15437,8 +16213,8 @@ package body Sem_Util is
-- calls.
return
- Nkind_In (Spec_Decl, N_Generic_Package_Declaration,
- N_Generic_Subprogram_Declaration);
+ Nkind (Spec_Decl) in N_Generic_Package_Declaration
+ | N_Generic_Subprogram_Declaration;
end Is_Generic_Declaration_Or_Body;
---------------------------
@@ -15560,7 +16336,7 @@ package body Sem_Util is
and then not Is_Dispatching_Operation (Subp)
and then Needs_Finalization (Etype (Subp))
and then not Is_Class_Wide_Type (Etype (Subp))
- and then not (Has_Invariants (Etype (Subp)))
+ and then not Has_Invariants (Etype (Subp))
and then Present (Subprogram_Body (Subp))
and then Was_Expression_Function (Subprogram_Body (Subp))
then
@@ -15597,8 +16373,7 @@ package body Sem_Util is
-- a predefined unit, i.e the one that declares iterator interfaces.
return
- Nam_In (Chars (Iter_Typ), Name_Forward_Iterator,
- Name_Reversible_Iterator)
+ Chars (Iter_Typ) in Name_Forward_Iterator | Name_Reversible_Iterator
and then In_Predefined_Unit (Root_Type (Iter_Typ));
end Denotes_Iterator;
@@ -15674,7 +16449,7 @@ package body Sem_Util is
-- Case of prefix of indexed or selected component or slice
- elsif Nkind_In (P, N_Indexed_Component, N_Selected_Component, N_Slice)
+ elsif Nkind (P) in N_Indexed_Component | N_Selected_Component | N_Slice
and then N = Prefix (P)
then
-- Here we have the case where the parent P is N.Q or N(Q .. R).
@@ -15752,7 +16527,7 @@ package body Sem_Util is
Ent : constant Entity_Id := Entity (Expr);
Sub : constant Entity_Id := Enclosing_Subprogram (Ent);
begin
- if not Ekind_In (Ent, E_Variable, E_In_Out_Parameter) then
+ if Ekind (Ent) not in E_Variable | E_In_Out_Parameter then
return False;
else
return Present (Sub) and then Sub = Current_Subprogram;
@@ -15782,8 +16557,7 @@ package body Sem_Util is
-- Attributes 'Input, 'Old and 'Result produce objects
when N_Attribute_Reference =>
- return
- Nam_In (Attribute_Name (N), Name_Input, Name_Old, Name_Result);
+ return Attribute_Name (N) in Name_Input | Name_Old | Name_Result;
when N_Selected_Component =>
return
@@ -16016,6 +16790,9 @@ package body Sem_Util is
Visit (Discrete_Subtype_Definition (Nod));
+ when N_Parameter_Association =>
+ Visit (Explicit_Actual_Parameter (N));
+
when N_Protected_Definition =>
-- End_Label is left out because it is not relevant for
@@ -16181,6 +16958,21 @@ package body Sem_Util is
Visit_List (Actions (Expr));
Visit (Expression (Expr));
+ when N_Function_Call =>
+
+ -- Ada 2020 (AI12-0175): Calls to certain functions that are
+ -- essentially unchecked conversions are preelaborable.
+
+ if Ada_Version >= Ada_2020
+ and then Nkind (Expr) = N_Function_Call
+ and then Is_Entity_Name (Name (Expr))
+ and then Is_Preelaborable_Function (Entity (Name (Expr)))
+ then
+ Visit_List (Parameter_Associations (Expr));
+ else
+ raise Non_Preelaborable;
+ end if;
+
when N_If_Expression =>
Visit_List (Expressions (Expr));
@@ -16214,7 +17006,7 @@ package body Sem_Util is
if Ekind (Id) = E_Discriminant then
null;
- elsif Ekind_In (Id, E_Constant, E_In_Parameter)
+ elsif Ekind (Id) in E_Constant | E_In_Parameter
and then Present (Discriminal_Link (Id))
then
null;
@@ -16306,13 +17098,6 @@ package body Sem_Util is
function Is_Object_Image (Prefix : Node_Id) return Boolean is
begin
- -- When the type of the prefix is not scalar, then the prefix is not
- -- valid in any scenario.
-
- if not Is_Scalar_Type (Etype (Prefix)) then
- return False;
- end if;
-
-- Here we test for the case that the prefix is not a type and assume
-- if it is not then it must be a named value or an object reference.
-- This is because the parser always checks that prefixes of attributes
@@ -16326,36 +17111,14 @@ package body Sem_Util is
-------------------------
function Is_Object_Reference (N : Node_Id) return Boolean is
- function Is_Internally_Generated_Renaming (N : Node_Id) return Boolean;
- -- Determine whether N is the name of an internally-generated renaming
-
- --------------------------------------
- -- Is_Internally_Generated_Renaming --
- --------------------------------------
-
- function Is_Internally_Generated_Renaming (N : Node_Id) return Boolean is
- P : Node_Id;
-
- begin
- P := N;
- while Present (P) loop
- if Nkind (P) = N_Object_Renaming_Declaration then
- return not Comes_From_Source (P);
- elsif Is_List_Member (P) then
- return False;
- end if;
-
- P := Parent (P);
- end loop;
-
- return False;
- end Is_Internally_Generated_Renaming;
-
- -- Start of processing for Is_Object_Reference
-
begin
+ -- AI12-0068: Note that a current instance reference in a type or
+ -- subtype's aspect_specification is considered a value, not an object
+ -- (see RM 8.6(18/5)).
+
if Is_Entity_Name (N) then
- return Present (Entity (N)) and then Is_Object (Entity (N));
+ return Present (Entity (N)) and then Is_Object (Entity (N))
+ and then not Is_Current_Instance_Reference_In_Type_Aspect (N);
else
case Nkind (N) is
@@ -16372,20 +17135,20 @@ package body Sem_Util is
-- Note that predefined operators are functions as well, and so
-- are attributes that are (can be renamed as) functions.
- when N_Binary_Op
- | N_Function_Call
- | N_Unary_Op
+ when N_Function_Call
+ | N_Op
=>
return Etype (N) /= Standard_Void_Type;
- -- Attributes references 'Loop_Entry, 'Old, and 'Result yield
- -- objects, even though they are not functions.
+ -- Attributes references 'Loop_Entry, 'Old, 'Priority and 'Result
+ -- yield objects, even though they are not functions.
when N_Attribute_Reference =>
return
- Nam_In (Attribute_Name (N), Name_Loop_Entry,
- Name_Old,
- Name_Result)
+ Attribute_Name (N) in Name_Loop_Entry
+ | Name_Old
+ | Name_Priority
+ | Name_Result
or else Is_Function_Attribute_Name (Attribute_Name (N));
when N_Selected_Component =>
@@ -16401,15 +17164,25 @@ package body Sem_Util is
-- names.
when N_Explicit_Dereference =>
- return not Nkind_In (Original_Node (N), N_Case_Expression,
- N_If_Expression);
+ return Nkind (Original_Node (N)) not in
+ N_Case_Expression | N_If_Expression;
-- A view conversion of a tagged object is an object reference
when N_Type_Conversion =>
- return Is_Tagged_Type (Etype (Subtype_Mark (N)))
- and then Is_Tagged_Type (Etype (Expression (N)))
- and then Is_Object_Reference (Expression (N));
+ if Ada_Version <= Ada_2012 then
+ -- A view conversion of a tagged object is an object
+ -- reference.
+ return Is_Tagged_Type (Etype (Subtype_Mark (N)))
+ and then Is_Tagged_Type (Etype (Expression (N)))
+ and then Is_Object_Reference (Expression (N));
+
+ else
+ -- AI12-0226: In Ada 202x a value conversion of an object is
+ -- an object.
+
+ return Is_Object_Reference (Expression (N));
+ end if;
-- An unchecked type conversion is considered to be an object if
-- the operand is an object (this construction arises only as a
@@ -16418,25 +17191,31 @@ package body Sem_Util is
when N_Unchecked_Type_Conversion =>
return True;
- -- Allow string literals to act as objects as long as they appear
- -- in internally-generated renamings. The expansion of iterators
- -- may generate such renamings when the range involves a string
- -- literal.
-
- when N_String_Literal =>
- return Is_Internally_Generated_Renaming (Parent (N));
-
-- AI05-0003: In Ada 2012 a qualified expression is a name.
-- This allows disambiguation of function calls and the use
-- of aggregates in more contexts.
when N_Qualified_Expression =>
- if Ada_Version < Ada_2012 then
- return False;
- else
- return Is_Object_Reference (Expression (N))
- or else Nkind (Expression (N)) = N_Aggregate;
- end if;
+ return Ada_Version >= Ada_2012
+ and then Is_Object_Reference (Expression (N));
+
+ -- In Ada 95 an aggregate is an object reference
+
+ when N_Aggregate =>
+ return Ada_Version >= Ada_95;
+
+ -- A string literal is not an object reference, but it might come
+ -- from rewriting of an object reference, e.g. from folding of an
+ -- aggregate.
+
+ when N_String_Literal =>
+ return Is_Rewrite_Substitution (N)
+ and then Is_Object_Reference (Original_Node (N));
+
+ -- AI12-0125: Target name represents a constant object
+
+ when N_Target_Name =>
+ return True;
when others =>
return False;
@@ -16470,10 +17249,9 @@ package body Sem_Util is
-- check whether the context requires an access_to_variable type.
elsif Nkind (AV) = N_Explicit_Dereference
- and then Ada_Version >= Ada_2012
- and then Nkind (Original_Node (AV)) = N_Indexed_Component
and then Present (Etype (Original_Node (AV)))
and then Has_Implicit_Dereference (Etype (Original_Node (AV)))
+ and then Ada_Version >= Ada_2012
then
return not Is_Access_Constant (Etype (Prefix (AV)));
@@ -16486,7 +17264,7 @@ package body Sem_Util is
-- expansion of a packed array aggregate).
elsif Nkind (AV) = N_Unchecked_Type_Conversion then
- if Nkind_In (Original_Node (AV), N_Function_Call, N_Aggregate) then
+ if Nkind (Original_Node (AV)) in N_Function_Call | N_Aggregate then
return False;
elsif Comes_From_Source (AV)
@@ -16531,28 +17309,7 @@ package body Sem_Util is
-- but we still want to allow the conversion if it converts a variable).
elsif Is_Rewrite_Substitution (AV) then
-
- -- In Ada 2012, the explicit dereference may be a rewritten call to a
- -- Reference function.
-
- if Ada_Version >= Ada_2012
- and then Nkind (Original_Node (AV)) = N_Function_Call
- and then
- Has_Implicit_Dereference (Etype (Name (Original_Node (AV))))
- then
-
- -- Check that this is not a constant reference.
-
- return not Is_Access_Constant (Etype (Prefix (AV)));
-
- elsif Has_Implicit_Dereference (Etype (Original_Node (AV))) then
- return
- not Is_Access_Constant (Etype
- (Get_Reference_Discriminant (Etype (Original_Node (AV)))));
-
- else
- return Is_OK_Variable_For_Out_Formal (Original_Node (AV));
- end if;
+ return Is_OK_Variable_For_Out_Formal (Original_Node (AV));
-- All other non-variables are rejected
@@ -16603,10 +17360,8 @@ package body Sem_Util is
and then Is_Protected_Type (Etype (Pref))
and then Is_Entity_Name (Subp)
and then Present (Entity (Subp))
- and then Ekind_In (Entity (Subp), E_Entry,
- E_Entry_Family,
- E_Function,
- E_Procedure);
+ and then Ekind (Entity (Subp)) in
+ E_Entry | E_Entry_Family | E_Function | E_Procedure;
else
return False;
end if;
@@ -16651,7 +17406,7 @@ package body Sem_Util is
Func_Id := Id;
while Present (Func_Id) and then Func_Id /= Standard_Standard loop
- if Ekind_In (Func_Id, E_Function, E_Generic_Function) then
+ if Ekind (Func_Id) in E_Function | E_Generic_Function then
return Is_Volatile_Function (Func_Id);
end if;
@@ -16679,6 +17434,7 @@ package body Sem_Util is
elsif Nkind (Context) = N_Object_Declaration
and then Present (Expression (Context))
and then Expression (Context) = Obj_Ref
+ and then Nkind (Parent (Context)) /= N_Expression_With_Actions
then
Obj_Id := Defining_Entity (Context);
@@ -16730,11 +17486,12 @@ package body Sem_Util is
-- The volatile object appears as the prefix of a name occurring in a
-- non-interfering context.
- elsif Nkind_In (Context, N_Attribute_Reference,
- N_Explicit_Dereference,
- N_Indexed_Component,
- N_Selected_Component,
- N_Slice)
+ elsif Nkind (Context) in
+ N_Attribute_Reference |
+ N_Explicit_Dereference |
+ N_Indexed_Component |
+ N_Selected_Component |
+ N_Slice
and then Prefix (Context) = Obj_Ref
and then Is_OK_Volatile_Context
(Context => Parent (Context),
@@ -16748,25 +17505,26 @@ package body Sem_Util is
elsif Nkind (Context) = N_Attribute_Reference
and then Prefix (Context) = Obj_Ref
- and then Nam_In (Attribute_Name (Context), Name_Address,
- Name_Alignment,
- Name_Component_Size,
- Name_First,
- Name_First_Bit,
- Name_Last,
- Name_Last_Bit,
- Name_Length,
- Name_Position,
- Name_Size,
- Name_Storage_Size)
+ and then Attribute_Name (Context) in Name_Address
+ | Name_Alignment
+ | Name_Component_Size
+ | Name_First
+ | Name_First_Bit
+ | Name_Last
+ | Name_Last_Bit
+ | Name_Length
+ | Name_Position
+ | Name_Size
+ | Name_Storage_Size
then
return True;
-- The volatile object appears as the expression of a type conversion
-- occurring in a non-interfering context.
- elsif Nkind_In (Context, N_Type_Conversion,
- N_Unchecked_Type_Conversion)
+ elsif Nkind (Context) in N_Qualified_Expression
+ | N_Type_Conversion
+ | N_Unchecked_Type_Conversion
and then Expression (Context) = Obj_Ref
and then Is_OK_Volatile_Context
(Context => Parent (Context),
@@ -16832,7 +17590,7 @@ package body Sem_Util is
is
begin
if Is_Scalar_Type (Typ) then
- return False;
+ return Has_Default_Aspect (Base_Type (Typ));
elsif Is_Access_Type (Typ) then
return Include_Implicit;
@@ -16841,8 +17599,9 @@ package body Sem_Util is
-- If component type is partially initialized, so is array type
- if Is_Partially_Initialized_Type
- (Component_Type (Typ), Include_Implicit)
+ if Has_Default_Aspect (Base_Type (Typ))
+ or else Is_Partially_Initialized_Type
+ (Component_Type (Typ), Include_Implicit)
then
return True;
@@ -16871,7 +17630,7 @@ package body Sem_Util is
else
declare
- Ent : Entity_Id;
+ Comp : Entity_Id;
Component_Present : Boolean := False;
-- Set True if at least one component is present. If no
@@ -16881,30 +17640,28 @@ package body Sem_Util is
begin
-- Loop through components
- Ent := First_Entity (Typ);
- while Present (Ent) loop
- if Ekind (Ent) = E_Component then
- Component_Present := True;
+ Comp := First_Component (Typ);
+ while Present (Comp) loop
+ Component_Present := True;
- -- If a component has an initialization expression then
- -- the enclosing record type is partially initialized
+ -- If a component has an initialization expression then the
+ -- enclosing record type is partially initialized
- if Present (Parent (Ent))
- and then Present (Expression (Parent (Ent)))
- then
- return True;
+ if Present (Parent (Comp))
+ and then Present (Expression (Parent (Comp)))
+ then
+ return True;
- -- If a component is of a type which is itself partially
- -- initialized, then the enclosing record type is also.
+ -- If a component is of a type which is itself partially
+ -- initialized, then the enclosing record type is also.
- elsif Is_Partially_Initialized_Type
- (Etype (Ent), Include_Implicit)
- then
- return True;
- end if;
+ elsif Is_Partially_Initialized_Type
+ (Etype (Comp), Include_Implicit)
+ then
+ return True;
end if;
- Next_Entity (Ent);
+ Next_Component (Comp);
end loop;
-- No initialized components found. If we found any components
@@ -17018,9 +17775,181 @@ package body Sem_Util is
--------------------------------
function Is_Potentially_Unevaluated (N : Node_Id) return Boolean is
+ function Has_Null_Others_Choice (Aggr : Node_Id) return Boolean;
+ -- Aggr is an array aggregate with static bounds and an others clause;
+ -- return True if the others choice of the given array aggregate does
+ -- not cover any component (i.e. is null).
+
+ function Immediate_Context_Implies_Is_Potentially_Unevaluated
+ (Expr : Node_Id) return Boolean;
+ -- Return True if the *immediate* context of this expression tells us
+ -- that it is potentially unevaluated; return False if the *immediate*
+ -- context doesn't provide an answer to this question and we need to
+ -- keep looking.
+
+ function Non_Static_Or_Null_Range (N : Node_Id) return Boolean;
+ -- Return True if the given range is nonstatic or null
+
+ ----------------------------
+ -- Has_Null_Others_Choice --
+ ----------------------------
+
+ function Has_Null_Others_Choice (Aggr : Node_Id) return Boolean is
+ Idx : constant Node_Id := First_Index (Etype (Aggr));
+ Hiv : constant Uint := Expr_Value (Type_High_Bound (Etype (Idx)));
+ Lov : constant Uint := Expr_Value (Type_Low_Bound (Etype (Idx)));
+
+ begin
+ declare
+ Intervals : constant Interval_Lists.Discrete_Interval_List :=
+ Interval_Lists.Aggregate_Intervals (Aggr);
+
+ begin
+ -- The others choice is null if, after normalization, we
+ -- have a single interval covering the whole aggregate.
+
+ return Intervals'Length = 1
+ and then
+ Intervals (Intervals'First).Low = Lov
+ and then
+ Intervals (Intervals'First).High = Hiv;
+ end;
+
+ -- If the aggregate is malformed (that is, indexes are not disjoint)
+ -- then no action is needed at this stage; the error will be reported
+ -- later by the frontend.
+
+ exception
+ when Interval_Lists.Intervals_Error =>
+ return False;
+ end Has_Null_Others_Choice;
+
+ ----------------------------------------------------------
+ -- Immediate_Context_Implies_Is_Potentially_Unevaluated --
+ ----------------------------------------------------------
+
+ function Immediate_Context_Implies_Is_Potentially_Unevaluated
+ (Expr : Node_Id) return Boolean
+ is
+ Par : constant Node_Id := Parent (Expr);
+
+ begin
+ if Nkind (Par) = N_If_Expression then
+ return Is_Elsif (Par) or else Expr /= First (Expressions (Par));
+
+ elsif Nkind (Par) = N_Case_Expression then
+ return Expr /= Expression (Par);
+
+ elsif Nkind (Par) in N_And_Then | N_Or_Else then
+ return Expr = Right_Opnd (Par);
+
+ elsif Nkind (Par) in N_In | N_Not_In then
+
+ -- If the membership includes several alternatives, only the first
+ -- is definitely evaluated.
+
+ if Present (Alternatives (Par)) then
+ return Expr /= First (Alternatives (Par));
+
+ -- If this is a range membership both bounds are evaluated
+
+ else
+ return False;
+ end if;
+
+ elsif Nkind (Par) = N_Quantified_Expression then
+ return Expr = Condition (Par);
+
+ elsif Nkind (Par) = N_Aggregate
+ and then Present (Etype (Par))
+ and then Etype (Par) /= Any_Composite
+ and then Is_Array_Type (Etype (Par))
+ and then Nkind (Expr) = N_Component_Association
+ then
+ declare
+ Choice : Node_Id;
+ In_Others_Choice : Boolean := False;
+
+ begin
+ -- The expression of an array_component_association is
+ -- potentially unevaluated if the associated choice is a
+ -- subtype_indication or range that defines a nonstatic or
+ -- null range.
+
+ Choice := First (Choices (Expr));
+ while Present (Choice) loop
+ if Nkind (Choice) = N_Range
+ and then Non_Static_Or_Null_Range (Choice)
+ then
+ return True;
+
+ elsif Nkind (Choice) = N_Identifier
+ and then Present (Scalar_Range (Etype (Choice)))
+ and then
+ Non_Static_Or_Null_Range (Scalar_Range (Etype (Choice)))
+ then
+ return True;
+
+ elsif Nkind (Choice) = N_Others_Choice then
+ In_Others_Choice := True;
+ end if;
+
+ Next (Choice);
+ end loop;
+
+ -- It is also potentially unevaluated if the associated choice
+ -- is an others choice and the applicable index constraint is
+ -- nonstatic or null.
+
+ if In_Others_Choice then
+ if not Compile_Time_Known_Bounds (Etype (Par)) then
+ return True;
+ else
+ return Has_Null_Others_Choice (Par);
+ end if;
+ end if;
+ end;
+
+ return False;
+
+ else
+ return False;
+ end if;
+ end Immediate_Context_Implies_Is_Potentially_Unevaluated;
+
+ ------------------------------
+ -- Non_Static_Or_Null_Range --
+ ------------------------------
+
+ function Non_Static_Or_Null_Range (N : Node_Id) return Boolean is
+ Low, High : Node_Id;
+
+ begin
+ Get_Index_Bounds (N, Low, High);
+
+ -- Check static bounds
+
+ if not Compile_Time_Known_Value (Low)
+ or else not Compile_Time_Known_Value (High)
+ then
+ return True;
+
+ -- Check null range
+
+ elsif Expr_Value (High) < Expr_Value (Low) then
+ return True;
+ end if;
+
+ return False;
+ end Non_Static_Or_Null_Range;
+
+ -- Local variables
+
Par : Node_Id;
Expr : Node_Id;
+ -- Start of processing for Is_Potentially_Unevaluated
+
begin
Expr := N;
Par := N;
@@ -17049,22 +17978,27 @@ package body Sem_Util is
-- conjunct in a postcondition) with a potentially unevaluated operand.
Par := Parent (Expr);
- while not Nkind_In (Par, N_And_Then,
- N_Case_Expression,
- N_If_Expression,
- N_In,
- N_Not_In,
- N_Or_Else,
- N_Quantified_Expression)
+
+ while Present (Par)
+ and then Nkind (Par) /= N_Pragma_Argument_Association
loop
- Expr := Par;
- Par := Parent (Par);
+ if Comes_From_Source (Par)
+ and then
+ Immediate_Context_Implies_Is_Potentially_Unevaluated (Expr)
+ then
+ return True;
+
+ -- For component associations continue climbing; it may be part of
+ -- an array aggregate.
+
+ elsif Nkind (Par) = N_Component_Association then
+ null;
-- If the context is not an expression, or if is the result of
-- expansion of an enclosing construct (such as another attribute)
-- the predicate does not apply.
- if Nkind (Par) = N_Case_Expression_Alternative then
+ elsif Nkind (Par) = N_Case_Expression_Alternative then
null;
elsif Nkind (Par) not in N_Subexpr
@@ -17072,37 +18006,12 @@ package body Sem_Util is
then
return False;
end if;
- end loop;
-
- if Nkind (Par) = N_If_Expression then
- return Is_Elsif (Par) or else Expr /= First (Expressions (Par));
-
- elsif Nkind (Par) = N_Case_Expression then
- return Expr /= Expression (Par);
-
- elsif Nkind_In (Par, N_And_Then, N_Or_Else) then
- return Expr = Right_Opnd (Par);
-
- elsif Nkind_In (Par, N_In, N_Not_In) then
-
- -- If the membership includes several alternatives, only the first is
- -- definitely evaluated.
-
- if Present (Alternatives (Par)) then
- return Expr /= First (Alternatives (Par));
- -- If this is a range membership both bounds are evaluated
-
- else
- return False;
- end if;
-
- elsif Nkind (Par) = N_Quantified_Expression then
- return Expr = Condition (Par);
+ Expr := Par;
+ Par := Parent (Par);
+ end loop;
- else
- return False;
- end if;
+ return False;
end Is_Potentially_Unevaluated;
-----------------------------------------
@@ -17130,7 +18039,7 @@ package body Sem_Util is
TSS_Name_Type
(Name_Buffer (Name_Len - TSS_Name'Length + 1 .. Name_Len));
- if Nam_In (Chars (E), Name_uAssign, Name_uSize)
+ if Chars (E) in Name_uAssign | Name_uSize
or else
(Chars (E) = Name_Op_Eq
and then Etype (First_Formal (E)) = Etype (Last_Formal (E)))
@@ -17140,6 +18049,7 @@ package body Sem_Util is
or else TSS_Name = TSS_Stream_Output
or else TSS_Name = TSS_Stream_Read
or else TSS_Name = TSS_Stream_Write
+ or else TSS_Name = TSS_Put_Image
or else Is_Predefined_Interface_Primitive (E)
then
return True;
@@ -17160,12 +18070,12 @@ package body Sem_Util is
-- these primitives.
return (Ada_Version >= Ada_2005 or else not Tagged_Type_Expansion)
- and then Nam_In (Chars (E), Name_uDisp_Asynchronous_Select,
- Name_uDisp_Conditional_Select,
- Name_uDisp_Get_Prim_Op_Kind,
- Name_uDisp_Get_Task_Id,
- Name_uDisp_Requeue,
- Name_uDisp_Timed_Select);
+ and then Chars (E) in Name_uDisp_Asynchronous_Select
+ | Name_uDisp_Conditional_Select
+ | Name_uDisp_Get_Prim_Op_Kind
+ | Name_uDisp_Get_Task_Id
+ | Name_uDisp_Requeue
+ | Name_uDisp_Timed_Select;
end Is_Predefined_Interface_Primitive;
---------------------------------------
@@ -17193,7 +18103,7 @@ package body Sem_Util is
TSS_Name_Type
(Name_Buffer (Name_Len - TSS_Name'Length + 1 .. Name_Len));
- if Nam_In (Chars (E), Name_uSize, Name_uAssign)
+ if Chars (E) in Name_uSize | Name_uAssign
or else
(Chars (E) = Name_Op_Eq
and then Etype (First_Formal (E)) = Etype (Last_Formal (E)))
@@ -17323,7 +18233,7 @@ package body Sem_Util is
begin
-- Aggregates
- if Nkind_In (N, N_Aggregate, N_Extension_Aggregate) then
+ if Nkind (N) in N_Aggregate | N_Extension_Aggregate then
return Is_Preelaborable_Aggregate (N);
-- Attributes are allowed in general, even if their prefix is a formal
@@ -17348,7 +18258,7 @@ package body Sem_Util is
and then Present (Entity (N))
and then
(Ekind (Entity (N)) = E_Discriminant
- or else (Ekind_In (Entity (N), E_Constant, E_In_Parameter)
+ or else (Ekind (Entity (N)) in E_Constant | E_In_Parameter
and then Present (Discriminal_Link (Entity (N)))))
then
return True;
@@ -17358,6 +18268,30 @@ package body Sem_Util is
elsif Nkind (N) = N_Null then
return True;
+ -- Ada 2020 (AI12-0175): Calls to certain functions that are essentially
+ -- unchecked conversions are preelaborable.
+
+ elsif Ada_Version >= Ada_2020
+ and then Nkind (N) = N_Function_Call
+ and then Is_Entity_Name (Name (N))
+ and then Is_Preelaborable_Function (Entity (Name (N)))
+ then
+ declare
+ A : Node_Id;
+ begin
+ A := First_Actual (N);
+
+ while Present (A) loop
+ if not Is_Preelaborable_Construct (A) then
+ return False;
+ end if;
+
+ Next_Actual (A);
+ end loop;
+ end;
+
+ return True;
+
-- Otherwise the construct is not preelaborable
else
@@ -17365,6 +18299,50 @@ package body Sem_Util is
end if;
end Is_Preelaborable_Construct;
+ -------------------------------
+ -- Is_Preelaborable_Function --
+ -------------------------------
+
+ function Is_Preelaborable_Function (Id : Entity_Id) return Boolean is
+ SATAC : constant Rtsfind.RTU_Id := System_Address_To_Access_Conversions;
+ Scop : constant Entity_Id := Scope (Id);
+
+ begin
+ -- Small optimization: every allowed function has convention Intrinsic
+ -- (see Analyze_Subprogram_Instantiation for the subtlety in the test).
+
+ if not Is_Intrinsic_Subprogram (Id)
+ and then Convention (Id) /= Convention_Intrinsic
+ then
+ return False;
+ end if;
+
+ -- An instance of Unchecked_Conversion
+
+ if Is_Unchecked_Conversion_Instance (Id) then
+ return True;
+ end if;
+
+ -- A function declared in System.Storage_Elements
+
+ if Is_RTU (Scop, System_Storage_Elements) then
+ return True;
+ end if;
+
+ -- The functions To_Pointer and To_Address declared in an instance of
+ -- System.Address_To_Access_Conversions (they are the only ones).
+
+ if Ekind (Scop) = E_Package
+ and then Nkind (Parent (Scop)) = N_Package_Specification
+ and then Present (Generic_Parent (Parent (Scop)))
+ and then Is_RTU (Generic_Parent (Parent (Scop)), SATAC)
+ then
+ return True;
+ end if;
+
+ return False;
+ end Is_Preelaborable_Function;
+
---------------------------------
-- Is_Protected_Self_Reference --
---------------------------------
@@ -17568,28 +18546,6 @@ package body Sem_Util is
return False;
end Is_Renamed_Entry;
- -----------------------------
- -- Is_Renaming_Declaration --
- -----------------------------
-
- function Is_Renaming_Declaration (N : Node_Id) return Boolean is
- begin
- case Nkind (N) is
- when N_Exception_Renaming_Declaration
- | N_Generic_Function_Renaming_Declaration
- | N_Generic_Package_Renaming_Declaration
- | N_Generic_Procedure_Renaming_Declaration
- | N_Object_Renaming_Declaration
- | N_Package_Renaming_Declaration
- | N_Subprogram_Renaming_Declaration
- =>
- return True;
-
- when others =>
- return False;
- end case;
- end Is_Renaming_Declaration;
-
----------------------------
-- Is_Reversible_Iterator --
----------------------------
@@ -17636,12 +18592,12 @@ package body Sem_Util is
begin
if not Is_List_Member (N) then
declare
- P : constant Node_Id := Parent (N);
+ P : constant Node_Id := Parent (N);
begin
- return Nkind_In (P, N_Expanded_Name,
- N_Generic_Association,
- N_Parameter_Association,
- N_Selected_Component)
+ return Nkind (P) in N_Expanded_Name
+ | N_Generic_Association
+ | N_Parameter_Association
+ | N_Selected_Component
and then Selector_Name (P) = N;
end;
@@ -17676,7 +18632,7 @@ package body Sem_Util is
function Is_Single_Concurrent_Type (Id : Entity_Id) return Boolean is
begin
return
- Ekind_In (Id, E_Protected_Type, E_Task_Type)
+ Ekind (Id) in E_Protected_Type | E_Task_Type
and then Is_Single_Concurrent_Type_Declaration
(Declaration_Node (Id));
end Is_Single_Concurrent_Type;
@@ -17689,8 +18645,8 @@ package body Sem_Util is
(N : Node_Id) return Boolean
is
begin
- return Nkind_In (Original_Node (N), N_Single_Protected_Declaration,
- N_Single_Task_Declaration);
+ return Nkind (Original_Node (N)) in
+ N_Single_Protected_Declaration | N_Single_Task_Declaration;
end Is_Single_Concurrent_Type_Declaration;
---------------------------------------------
@@ -17731,157 +18687,42 @@ package body Sem_Util is
and then Is_Single_Concurrent_Type (Etype (Id));
end Is_Single_Task_Object;
- -------------------------------------
- -- Is_SPARK_05_Initialization_Expr --
- -------------------------------------
-
- function Is_SPARK_05_Initialization_Expr (N : Node_Id) return Boolean is
- Is_Ok : Boolean;
- Expr : Node_Id;
- Comp_Assn : Node_Id;
- Orig_N : constant Node_Id := Original_Node (N);
+ --------------------------------------
+ -- Is_Special_Aliased_Formal_Access --
+ --------------------------------------
+ function Is_Special_Aliased_Formal_Access
+ (Exp : Node_Id;
+ Scop : Entity_Id) return Boolean is
begin
- Is_Ok := True;
+ -- Verify the expression is an access reference to 'Access within a
+ -- return statement as this is the only time an explicitly aliased
+ -- formal has different semantics.
- if not Comes_From_Source (Orig_N) then
- goto Done;
+ if Nkind (Exp) /= N_Attribute_Reference
+ or else Get_Attribute_Id (Attribute_Name (Exp)) /= Attribute_Access
+ or else Nkind (Parent (Exp)) /= N_Simple_Return_Statement
+ then
+ return False;
end if;
- pragma Assert (Nkind (Orig_N) in N_Subexpr);
-
- case Nkind (Orig_N) is
- when N_Character_Literal
- | N_Integer_Literal
- | N_Real_Literal
- | N_String_Literal
- =>
- null;
-
- when N_Expanded_Name
- | N_Identifier
- =>
- if Is_Entity_Name (Orig_N)
- and then Present (Entity (Orig_N)) -- needed in some cases
- then
- case Ekind (Entity (Orig_N)) is
- when E_Constant
- | E_Enumeration_Literal
- | E_Named_Integer
- | E_Named_Real
- =>
- null;
-
- when others =>
- if Is_Type (Entity (Orig_N)) then
- null;
- else
- Is_Ok := False;
- end if;
- end case;
- end if;
-
- when N_Qualified_Expression
- | N_Type_Conversion
- =>
- Is_Ok := Is_SPARK_05_Initialization_Expr (Expression (Orig_N));
-
- when N_Unary_Op =>
- Is_Ok := Is_SPARK_05_Initialization_Expr (Right_Opnd (Orig_N));
-
- when N_Binary_Op
- | N_Membership_Test
- | N_Short_Circuit
- =>
- Is_Ok := Is_SPARK_05_Initialization_Expr (Left_Opnd (Orig_N))
- and then
- Is_SPARK_05_Initialization_Expr (Right_Opnd (Orig_N));
-
- when N_Aggregate
- | N_Extension_Aggregate
- =>
- if Nkind (Orig_N) = N_Extension_Aggregate then
- Is_Ok :=
- Is_SPARK_05_Initialization_Expr (Ancestor_Part (Orig_N));
- end if;
-
- Expr := First (Expressions (Orig_N));
- while Present (Expr) loop
- if not Is_SPARK_05_Initialization_Expr (Expr) then
- Is_Ok := False;
- goto Done;
- end if;
-
- Next (Expr);
- end loop;
-
- Comp_Assn := First (Component_Associations (Orig_N));
- while Present (Comp_Assn) loop
- Expr := Expression (Comp_Assn);
-
- -- Note: test for Present here needed for box assocation
-
- if Present (Expr)
- and then not Is_SPARK_05_Initialization_Expr (Expr)
- then
- Is_Ok := False;
- goto Done;
- end if;
-
- Next (Comp_Assn);
- end loop;
-
- when N_Attribute_Reference =>
- if Nkind (Prefix (Orig_N)) in N_Subexpr then
- Is_Ok := Is_SPARK_05_Initialization_Expr (Prefix (Orig_N));
- end if;
-
- Expr := First (Expressions (Orig_N));
- while Present (Expr) loop
- if not Is_SPARK_05_Initialization_Expr (Expr) then
- Is_Ok := False;
- goto Done;
- end if;
-
- Next (Expr);
- end loop;
+ -- Check if the prefix of the reference is indeed an explicitly aliased
+ -- formal parameter for the function Scop. Additionally, we must check
+ -- that Scop returns an anonymous access type, otherwise the special
+ -- rules dictating a need for a dynamic check are not in effect.
- -- Selected components might be expanded named not yet resolved, so
- -- default on the safe side. (Eg on sparklex.ads)
-
- when N_Selected_Component =>
- null;
-
- when others =>
- Is_Ok := False;
- end case;
-
- <<Done>>
- return Is_Ok;
- end Is_SPARK_05_Initialization_Expr;
-
- ----------------------------------
- -- Is_SPARK_05_Object_Reference --
- ----------------------------------
-
- function Is_SPARK_05_Object_Reference (N : Node_Id) return Boolean is
- begin
- if Is_Entity_Name (N) then
- return Present (Entity (N))
- and then
- (Ekind_In (Entity (N), E_Constant, E_Variable)
- or else Ekind (Entity (N)) in Formal_Kind);
-
- else
- case Nkind (N) is
- when N_Selected_Component =>
- return Is_SPARK_05_Object_Reference (Prefix (N));
-
- when others =>
- return False;
- end case;
- end if;
- end Is_SPARK_05_Object_Reference;
+ declare
+ P_Ult : constant Node_Id := Ultimate_Prefix (Prefix (Exp));
+ begin
+ return Is_Entity_Name (P_Ult)
+ and then Is_Aliased (Entity (P_Ult))
+ and then Is_Formal (Entity (P_Ult))
+ and then Scope (Entity (P_Ult)) = Scop
+ and then Ekind (Scop) in
+ E_Function | E_Operator | E_Subprogram_Type
+ and then Needs_Result_Accessibility_Level (Scop);
+ end;
+ end Is_Special_Aliased_Formal_Access;
-----------------------------
-- Is_Specific_Tagged_Type --
@@ -17915,6 +18756,74 @@ package body Sem_Util is
or else Nkind (N) = N_Procedure_Call_Statement;
end Is_Statement;
+ ------------------------
+ -- Is_Static_Function --
+ ------------------------
+
+ function Is_Static_Function (Subp : Entity_Id) return Boolean is
+ begin
+ return Has_Aspect (Subp, Aspect_Static)
+ and then
+ (No (Find_Value_Of_Aspect (Subp, Aspect_Static))
+ or else Is_True (Static_Boolean
+ (Find_Value_Of_Aspect (Subp, Aspect_Static))));
+ end Is_Static_Function;
+
+ ------------------------------
+ -- Is_Static_Function_Call --
+ ------------------------------
+
+ function Is_Static_Function_Call (Call : Node_Id) return Boolean is
+ function Has_All_Static_Actuals (Call : Node_Id) return Boolean;
+ -- Return whether all actual parameters of Call are static expressions
+
+ ----------------------------
+ -- Has_All_Static_Actuals --
+ ----------------------------
+
+ function Has_All_Static_Actuals (Call : Node_Id) return Boolean is
+ Actual : Node_Id := First_Actual (Call);
+ String_Result : constant Boolean :=
+ Is_String_Type (Etype (Entity (Name (Call))));
+
+ begin
+ while Present (Actual) loop
+ if not Is_Static_Expression (Actual) then
+
+ -- ??? In the string-returning case we want to avoid a call
+ -- being made to Establish_Transient_Scope in Resolve_Call,
+ -- but at the point where that's tested for (which now includes
+ -- a call to test Is_Static_Function_Call), the actuals of the
+ -- call haven't been resolved, so expressions of the actuals
+ -- may not have been marked Is_Static_Expression yet, so we
+ -- force them to be resolved here, so we can tell if they're
+ -- static. Calling Resolve here is admittedly a kludge, and we
+ -- limit this call to string-returning cases.
+
+ if String_Result then
+ Resolve (Actual);
+ end if;
+
+ -- Test flag again in case it's now True due to above Resolve
+
+ if not Is_Static_Expression (Actual) then
+ return False;
+ end if;
+ end if;
+
+ Next_Actual (Actual);
+ end loop;
+
+ return True;
+ end Has_All_Static_Actuals;
+
+ begin
+ return Nkind (Call) = N_Function_Call
+ and then Is_Entity_Name (Name (Call))
+ and then Is_Static_Function (Entity (Name (Call)))
+ and then Has_All_Static_Actuals (Call);
+ end Is_Static_Function_Call;
+
----------------------------------------
-- Is_Subcomponent_Of_Atomic_Object --
----------------------------------------
@@ -17925,7 +18834,7 @@ package body Sem_Util is
begin
R := Get_Referenced_Object (N);
- while Nkind_In (R, N_Indexed_Component, N_Selected_Component, N_Slice)
+ while Nkind (R) in N_Indexed_Component | N_Selected_Component | N_Slice
loop
R := Get_Referenced_Object (Prefix (R));
@@ -18281,7 +19190,7 @@ package body Sem_Util is
end if;
end if;
- Idx := Next_Index (Idx);
+ Next_Index (Idx);
end loop;
return False;
@@ -18461,14 +19370,14 @@ package body Sem_Util is
or else
Is_Variable_Prefix (Original_Node (Prefix (N)));
- -- in Ada 2012, the dereference may have been added for a type with
- -- a declared implicit dereference aspect. Check that it is not an
- -- access to constant.
+ -- Generalized indexing operations are rewritten as explicit
+ -- dereferences, and it is only during resolution that we can
+ -- check whether the context requires an access_to_variable type.
elsif Nkind (N) = N_Explicit_Dereference
and then Present (Etype (Orig_Node))
- and then Ada_Version >= Ada_2012
and then Has_Implicit_Dereference (Etype (Orig_Node))
+ and then Ada_Version >= Ada_2012
then
return not Is_Access_Constant (Etype (Prefix (N)));
@@ -18567,6 +19476,31 @@ package body Sem_Util is
end if;
end Is_Variable;
+ ------------------------
+ -- Is_View_Conversion --
+ ------------------------
+
+ function Is_View_Conversion (N : Node_Id) return Boolean is
+ begin
+ if Nkind (N) = N_Type_Conversion
+ and then Nkind (Unqual_Conv (N)) = N_Identifier
+ then
+ if Is_Tagged_Type (Etype (N))
+ and then Is_Tagged_Type (Etype (Unqual_Conv (N)))
+ then
+ return True;
+
+ elsif Is_Actual_Parameter (N)
+ and then (Is_Actual_Out_Parameter (N)
+ or else Is_Actual_In_Out_Parameter (N))
+ then
+ return True;
+ end if;
+ end if;
+
+ return False;
+ end Is_View_Conversion;
+
---------------------------
-- Is_Visibly_Controlled --
---------------------------
@@ -18624,7 +19558,7 @@ package body Sem_Util is
function Is_Volatile_Function (Func_Id : Entity_Id) return Boolean is
begin
- pragma Assert (Ekind_In (Func_Id, E_Function, E_Generic_Function));
+ pragma Assert (Ekind (Func_Id) in E_Function | E_Generic_Function);
-- A function declared within a protected type is volatile
@@ -18755,8 +19689,8 @@ package body Sem_Util is
begin
pragma Assert (Is_Itype (Id));
return Present (Parent (Id))
- and then Nkind_In (Parent (Id), N_Full_Type_Declaration,
- N_Subtype_Declaration)
+ and then Nkind (Parent (Id)) in
+ N_Full_Type_Declaration | N_Subtype_Declaration
and then Defining_Entity (Parent (Id)) = Id;
end Itype_Has_Declaration;
@@ -19167,9 +20101,8 @@ package body Sem_Util is
-- Obj := new ...'(new Coextension ...);
if Nkind (Context_Nod) = N_Assignment_Statement then
- Is_Dynamic :=
- Nkind_In (Expression (Context_Nod), N_Allocator,
- N_Qualified_Expression);
+ Is_Dynamic := Nkind (Expression (Context_Nod)) in
+ N_Allocator | N_Qualified_Expression;
-- An allocator that appears within the expression of a simple return
-- statement is treated as a potentially dynamic coextension when the
@@ -19179,10 +20112,8 @@ package body Sem_Util is
-- return new ...'(new Coextension ...);
elsif Nkind (Context_Nod) = N_Simple_Return_Statement then
- Is_Dynamic :=
- Nkind_In (Expression (Context_Nod), N_Aggregate,
- N_Allocator,
- N_Qualified_Expression);
+ Is_Dynamic := Nkind (Expression (Context_Nod)) in
+ N_Aggregate | N_Allocator | N_Qualified_Expression;
-- An alloctor that appears within the initialization expression of an
-- object declaration is considered a potentially dynamic coextension
@@ -19198,10 +20129,8 @@ package body Sem_Util is
-- return Obj : ... := (new Coextension ...);
elsif Nkind (Context_Nod) = N_Object_Declaration then
- Is_Dynamic :=
- Nkind_In (Root_Nod, N_Allocator, N_Qualified_Expression)
- or else
- Nkind (Parent (Context_Nod)) = N_Extended_Return_Statement;
+ Is_Dynamic := Nkind (Root_Nod) in N_Allocator | N_Qualified_Expression
+ or else Nkind (Parent (Context_Nod)) = N_Extended_Return_Statement;
-- This routine should not be called with constructs that cannot contain
-- coextensions.
@@ -19367,12 +20296,12 @@ package body Sem_Util is
-- suppressed. As a result the elaboration checks of the call must
-- be disabled in order to preserve this dependency.
- if Nkind_In (N, N_Entry_Call_Statement,
- N_Function_Call,
- N_Function_Instantiation,
- N_Package_Instantiation,
- N_Procedure_Call_Statement,
- N_Procedure_Instantiation)
+ if Nkind (N) in N_Entry_Call_Statement
+ | N_Function_Call
+ | N_Function_Instantiation
+ | N_Package_Instantiation
+ | N_Procedure_Call_Statement
+ | N_Procedure_Instantiation
then
Nam := Extract_Name (N);
@@ -19451,16 +20380,16 @@ package body Sem_Util is
-- Obtain the complimentary unit of the main unit
- if Nkind_In (Main_Unit, N_Generic_Package_Declaration,
- N_Generic_Subprogram_Declaration,
- N_Package_Declaration,
- N_Subprogram_Declaration)
+ if Nkind (Main_Unit) in N_Generic_Package_Declaration
+ | N_Generic_Subprogram_Declaration
+ | N_Package_Declaration
+ | N_Subprogram_Declaration
then
Aux_Id := Corresponding_Body (Main_Unit);
- elsif Nkind_In (Main_Unit, N_Package_Body,
- N_Subprogram_Body,
- N_Subprogram_Renaming_Declaration)
+ elsif Nkind (Main_Unit) in N_Package_Body
+ | N_Subprogram_Body
+ | N_Subprogram_Renaming_Declaration
then
Aux_Id := Corresponding_Spec (Main_Unit);
end if;
@@ -19791,12 +20720,10 @@ package body Sem_Util is
function Process (N : Node_Id) return Traverse_Result is
begin
- if Nkind_In (N, N_Procedure_Call_Statement,
- N_Function_Call,
- N_Raise_Statement,
- N_Raise_Constraint_Error,
- N_Raise_Program_Error,
- N_Raise_Storage_Error)
+ if Nkind (N) in N_Procedure_Call_Statement
+ | N_Function_Call
+ | N_Raise_Statement
+ | N_Raise_xxx_Error
then
Result := True;
return Abandon;
@@ -19978,6 +20905,144 @@ package body Sem_Util is
end if;
end Needs_One_Actual;
+ --------------------------------------
+ -- Needs_Result_Accessibility_Level --
+ --------------------------------------
+
+ function Needs_Result_Accessibility_Level
+ (Func_Id : Entity_Id) return Boolean
+ is
+ Func_Typ : constant Entity_Id := Underlying_Type (Etype (Func_Id));
+
+ function Has_Unconstrained_Access_Discriminant_Component
+ (Comp_Typ : Entity_Id) return Boolean;
+ -- Returns True if any component of the type has an unconstrained access
+ -- discriminant.
+
+ -----------------------------------------------------
+ -- Has_Unconstrained_Access_Discriminant_Component --
+ -----------------------------------------------------
+
+ function Has_Unconstrained_Access_Discriminant_Component
+ (Comp_Typ : Entity_Id) return Boolean
+ is
+ begin
+ if not Is_Limited_Type (Comp_Typ) then
+ return False;
+
+ -- Only limited types can have access discriminants with
+ -- defaults.
+
+ elsif Has_Unconstrained_Access_Discriminants (Comp_Typ) then
+ return True;
+
+ elsif Is_Array_Type (Comp_Typ) then
+ return Has_Unconstrained_Access_Discriminant_Component
+ (Underlying_Type (Component_Type (Comp_Typ)));
+
+ elsif Is_Record_Type (Comp_Typ) then
+ declare
+ Comp : Entity_Id;
+
+ begin
+ Comp := First_Component (Comp_Typ);
+ while Present (Comp) loop
+ if Has_Unconstrained_Access_Discriminant_Component
+ (Underlying_Type (Etype (Comp)))
+ then
+ return True;
+ end if;
+
+ Next_Component (Comp);
+ end loop;
+ end;
+ end if;
+
+ return False;
+ end Has_Unconstrained_Access_Discriminant_Component;
+
+ Disable_Coextension_Cases : constant Boolean := True;
+ -- Flag used to temporarily disable a "True" result for types with
+ -- access discriminants and related coextension cases.
+
+ -- Start of processing for Needs_Result_Accessibility_Level
+
+ begin
+ -- False if completion unavailable (how does this happen???)
+
+ if not Present (Func_Typ) then
+ return False;
+
+ -- False if not a function, also handle enum-lit renames case
+
+ elsif Func_Typ = Standard_Void_Type
+ or else Is_Scalar_Type (Func_Typ)
+ then
+ return False;
+
+ -- Handle a corner case, a cross-dialect subp renaming. For example,
+ -- an Ada 2012 renaming of an Ada 2005 subprogram. This can occur when
+ -- an Ada 2005 (or earlier) unit references predefined run-time units.
+
+ elsif Present (Alias (Func_Id)) then
+
+ -- Unimplemented: a cross-dialect subp renaming which does not set
+ -- the Alias attribute (e.g., a rename of a dereference of an access
+ -- to subprogram value). ???
+
+ return Present (Extra_Accessibility_Of_Result (Alias (Func_Id)));
+
+ -- Remaining cases require Ada 2012 mode
+
+ elsif Ada_Version < Ada_2012 then
+ return False;
+
+ -- Handle the situation where a result is an anonymous access type
+ -- RM 3.10.2 (10.3/3).
+
+ elsif Ekind (Func_Typ) = E_Anonymous_Access_Type then
+ return True;
+
+ -- The following cases are related to coextensions and do not fully
+ -- cover everything mentioned in RM 3.10.2 (12) ???
+
+ -- Temporarily disabled ???
+
+ elsif Disable_Coextension_Cases then
+ return False;
+
+ -- In the case of, say, a null tagged record result type, the need for
+ -- this extra parameter might not be obvious so this function returns
+ -- True for all tagged types for compatibility reasons.
+
+ -- A function with, say, a tagged null controlling result type might
+ -- be overridden by a primitive of an extension having an access
+ -- discriminant and the overrider and overridden must have compatible
+ -- calling conventions (including implicitly declared parameters).
+
+ -- Similarly, values of one access-to-subprogram type might designate
+ -- both a primitive subprogram of a given type and a function which is,
+ -- for example, not a primitive subprogram of any type. Again, this
+ -- requires calling convention compatibility. It might be possible to
+ -- solve these issues by introducing wrappers, but that is not the
+ -- approach that was chosen.
+
+ elsif Is_Tagged_Type (Func_Typ) then
+ return True;
+
+ elsif Has_Unconstrained_Access_Discriminants (Func_Typ) then
+ return True;
+
+ elsif Has_Unconstrained_Access_Discriminant_Component (Func_Typ) then
+ return True;
+
+ -- False for all other cases
+
+ else
+ return False;
+ end if;
+ end Needs_Result_Accessibility_Level;
+
---------------------------------
-- Needs_Simple_Initialization --
---------------------------------
@@ -20087,9 +21152,9 @@ package body Sem_Util is
-- subprogram call, and the caller requests this behavior.
elsif not Calls_OK
- and then Nkind_In (Par, N_Entry_Call_Statement,
- N_Function_Call,
- N_Procedure_Call_Statement)
+ and then Nkind (Par) in N_Entry_Call_Statement
+ | N_Function_Call
+ | N_Procedure_Call_Statement
then
return False;
@@ -20120,12 +21185,6 @@ package body Sem_Util is
if Legacy_Elaboration_Checks then
return False;
- -- No marker needs to be created for ASIS because ABE diagnostics and
- -- checks are not performed in this mode.
-
- elsif ASIS_Mode then
- return False;
-
-- No marker needs to be created when the reference is preanalyzed
-- because the marker will be inserted in the wrong place.
@@ -20134,7 +21193,7 @@ package body Sem_Util is
-- Only references warrant a marker
- elsif not Nkind_In (N, N_Expanded_Name, N_Identifier) then
+ elsif Nkind (N) not in N_Expanded_Name | N_Identifier then
return False;
-- Only source references warrant a marker
@@ -20198,13 +21257,125 @@ package body Sem_Util is
while Present (E) loop
Append (New_Copy_Tree (E), NL);
- E := Next (E);
+ Next (E);
end loop;
return NL;
end if;
end New_Copy_List_Tree;
+ ----------------------------
+ -- New_Copy_Separate_List --
+ ----------------------------
+
+ function New_Copy_Separate_List (List : List_Id) return List_Id is
+ begin
+ if List = No_List then
+ return No_List;
+
+ else
+ declare
+ List_Copy : constant List_Id := New_List;
+ N : Node_Id := First (List);
+
+ begin
+ while Present (N) loop
+ Append (New_Copy_Separate_Tree (N), List_Copy);
+ Next (N);
+ end loop;
+
+ return List_Copy;
+ end;
+ end if;
+ end New_Copy_Separate_List;
+
+ ----------------------------
+ -- New_Copy_Separate_Tree --
+ ----------------------------
+
+ function New_Copy_Separate_Tree (Source : Node_Id) return Node_Id is
+ function Search_Decl (N : Node_Id) return Traverse_Result;
+ -- Subtree visitor which collects declarations
+
+ procedure Search_Declarations is new Traverse_Proc (Search_Decl);
+ -- Subtree visitor instantiation
+
+ -----------------
+ -- Search_Decl --
+ -----------------
+
+ Decls : Elist_Id;
+
+ function Search_Decl (N : Node_Id) return Traverse_Result is
+ begin
+ if Nkind (N) in N_Declaration then
+ if No (Decls) then
+ Decls := New_Elmt_List;
+ end if;
+
+ Append_Elmt (N, Decls);
+ end if;
+
+ return OK;
+ end Search_Decl;
+
+ -- Local variables
+
+ Source_Copy : constant Node_Id := New_Copy_Tree (Source);
+
+ -- Start of processing for New_Copy_Separate_Tree
+
+ begin
+ Decls := No_Elist;
+ Search_Declarations (Source_Copy);
+
+ -- Associate a new Entity with all the subtree declarations (keeping
+ -- their original name).
+
+ if Present (Decls) then
+ declare
+ Elmt : Elmt_Id;
+ Decl : Node_Id;
+ New_E : Entity_Id;
+
+ begin
+ Elmt := First_Elmt (Decls);
+ while Present (Elmt) loop
+ Decl := Node (Elmt);
+ New_E := Make_Defining_Identifier (Sloc (Decl),
+ New_Internal_Name ('P'));
+
+ if Nkind (Decl) = N_Expression_Function then
+ Decl := Specification (Decl);
+ end if;
+
+ if Nkind (Decl) in N_Function_Instantiation
+ | N_Function_Specification
+ | N_Generic_Function_Renaming_Declaration
+ | N_Generic_Package_Renaming_Declaration
+ | N_Generic_Procedure_Renaming_Declaration
+ | N_Package_Body
+ | N_Package_Instantiation
+ | N_Package_Renaming_Declaration
+ | N_Package_Specification
+ | N_Procedure_Instantiation
+ | N_Procedure_Specification
+ then
+ Set_Chars (New_E, Chars (Defining_Unit_Name (Decl)));
+ Set_Defining_Unit_Name (Decl, New_E);
+ else
+ Set_Chars (New_E, Chars (Defining_Identifier (Decl)));
+ Set_Defining_Identifier (Decl, New_E);
+ end if;
+
+ Next_Elmt (Elmt);
+ end loop;
+ end;
+ end if;
+
+ return Source_Copy;
+ end New_Copy_Separate_Tree;
+
-------------------
-- New_Copy_Tree --
-------------------
@@ -20312,7 +21483,7 @@ package body Sem_Util is
-- New_Id is the corresponding new entity generated during Phase 1.
procedure Add_Pending_Itype (Assoc_Nod : Node_Id; Itype : Entity_Id);
- pragma Inline (Add_New_Entity);
+ pragma Inline (Add_Pending_Itype);
-- Add an entry in the NCT_Pending_Itypes which maps key Assoc_Nod to
-- value Itype. Assoc_Nod is the associated node of an itype. Itype is
-- an itype.
@@ -20633,6 +21804,65 @@ package body Sem_Util is
New_Par : Node_Id := Empty;
Semantic : Boolean := False) return Union_Id
is
+ function Has_More_Ids (N : Node_Id) return Boolean;
+ -- Return True when N has attribute More_Ids set to True
+
+ function Is_Syntactic_Node return Boolean;
+ -- Return True when Field is a syntactic node
+
+ ------------------
+ -- Has_More_Ids --
+ ------------------
+
+ function Has_More_Ids (N : Node_Id) return Boolean is
+ begin
+ if Nkind (N) in N_Component_Declaration
+ | N_Discriminant_Specification
+ | N_Exception_Declaration
+ | N_Formal_Object_Declaration
+ | N_Number_Declaration
+ | N_Object_Declaration
+ | N_Parameter_Specification
+ | N_Use_Package_Clause
+ | N_Use_Type_Clause
+ then
+ return More_Ids (N);
+ else
+ return False;
+ end if;
+ end Has_More_Ids;
+
+ -----------------------
+ -- Is_Syntactic_Node --
+ -----------------------
+
+ function Is_Syntactic_Node return Boolean is
+ Old_N : constant Node_Id := Node_Id (Field);
+
+ begin
+ if Parent (Old_N) = Old_Par then
+ return True;
+
+ elsif not Has_More_Ids (Old_Par) then
+ return False;
+
+ -- Perform the check using the last last id in the syntactic chain
+
+ else
+ declare
+ N : Node_Id := Old_Par;
+
+ begin
+ while Present (N) and then More_Ids (N) loop
+ Next (N);
+ end loop;
+
+ pragma Assert (Prev_Ids (N));
+ return Parent (Old_N) = N;
+ end;
+ end if;
+ end Is_Syntactic_Node;
+
begin
-- The field is empty
@@ -20644,7 +21874,7 @@ package body Sem_Util is
elsif Field in Node_Range then
declare
Old_N : constant Node_Id := Node_Id (Field);
- Syntactic : constant Boolean := Parent (Old_N) = Old_Par;
+ Syntactic : constant Boolean := Is_Syntactic_Node;
New_N : Node_Id;
@@ -20835,9 +22065,9 @@ package body Sem_Util is
-- Update the First/Next_Named_Association chain for a replicated
-- call.
- if Nkind_In (N, N_Entry_Call_Statement,
- N_Function_Call,
- N_Procedure_Call_Statement)
+ if Nkind (N) in N_Entry_Call_Statement
+ | N_Function_Call
+ | N_Procedure_Call_Statement
then
Update_Named_Associations
(Old_Call => N,
@@ -20872,6 +22102,11 @@ package body Sem_Util is
Set_Chars (Result, Chars (Entity (Result)));
end if;
end if;
+
+ if Has_Aspects (N) then
+ Set_Aspect_Specifications (Result,
+ Copy_List_With_Replacement (Aspect_Specifications (N)));
+ end if;
end if;
return Result;
@@ -21254,12 +22489,9 @@ package body Sem_Util is
-- an entity declaration that must be replaced when the expander is
-- active if the expression has been preanalyzed or analyzed.
- elsif not Ekind_In (Id, E_Block,
- E_Constant,
- E_Label,
- E_Loop_Parameter,
- E_Procedure,
- E_Variable)
+ elsif Ekind (Id) not in
+ E_Block | E_Constant | E_Label | E_Loop_Parameter |
+ E_Procedure | E_Variable
and then not Is_Type (Id)
then
return;
@@ -21464,7 +22696,7 @@ package body Sem_Util is
-- shared. Thus cloned_Subtype must be set to indicate the sharing.
-- ??? What does this do?
- if Ekind_In (Itype, E_Class_Wide_Subtype, E_Record_Subtype) then
+ if Ekind (Itype) in E_Class_Wide_Subtype | E_Record_Subtype then
Set_Cloned_Subtype (New_Itype, Itype);
end if;
@@ -21552,9 +22784,9 @@ package body Sem_Util is
EWA_Level := EWA_Level + 1;
elsif EWA_Level > 0
- and then Nkind_In (N, N_Block_Statement,
- N_Subprogram_Body,
- N_Subprogram_Declaration)
+ and then Nkind (N) in N_Block_Statement
+ | N_Subprogram_Body
+ | N_Subprogram_Declaration
then
EWA_Inner_Scope_Level := EWA_Inner_Scope_Level + 1;
end if;
@@ -21580,9 +22812,9 @@ package body Sem_Util is
Par_Nod => N);
if EWA_Level > 0
- and then Nkind_In (N, N_Block_Statement,
- N_Subprogram_Body,
- N_Subprogram_Declaration)
+ and then Nkind (N) in N_Block_Statement
+ | N_Subprogram_Body
+ | N_Subprogram_Declaration
then
EWA_Inner_Scope_Level := EWA_Inner_Scope_Level - 1;
@@ -21849,9 +23081,9 @@ package body Sem_Util is
-- In case of a build-in-place call, the call will no longer be a
-- call; it will have been rewritten.
- if Nkind_In (Par, N_Entry_Call_Statement,
- N_Function_Call,
- N_Procedure_Call_Statement)
+ if Nkind (Par) in N_Entry_Call_Statement
+ | N_Function_Call
+ | N_Procedure_Call_Statement
then
return First_Named_Actual (Par);
@@ -21939,36 +23171,34 @@ package body Sem_Util is
Comp : Entity_Id;
begin
- Comp := First_Entity (Typ);
+ Comp := First_Component (Typ);
while Present (Comp) loop
-- Only look at E_Component entities. No need to look at
-- E_Discriminant entities, and we must ignore internal
-- subtypes generated for constrained components.
- if Ekind (Comp) = E_Component then
- declare
- Comp_Type : constant Entity_Id :=
- Underlying_Type (Etype (Comp));
+ declare
+ Comp_Type : constant Entity_Id :=
+ Underlying_Type (Etype (Comp));
- begin
- if Is_Record_Type (Comp_Type)
- or else
- Is_Protected_Type (Comp_Type)
- then
- if not Caller_Known_Size_Record (Comp_Type) then
- return False;
- end if;
+ begin
+ if Is_Record_Type (Comp_Type)
+ or else
+ Is_Protected_Type (Comp_Type)
+ then
+ if not Caller_Known_Size_Record (Comp_Type) then
+ return False;
+ end if;
- elsif Is_Array_Type (Comp_Type) then
- if Size_Depends_On_Discriminant (Comp_Type) then
- return False;
- end if;
+ elsif Is_Array_Type (Comp_Type) then
+ if Size_Depends_On_Discriminant (Comp_Type) then
+ return False;
end if;
- end;
- end if;
+ end if;
+ end;
- Next_Entity (Comp);
+ Next_Component (Comp);
end loop;
end;
@@ -22015,41 +23245,39 @@ package body Sem_Util is
Comp : Entity_Id;
begin
- Comp := First_Entity (Typ);
+ Comp := First_Component (Typ);
while Present (Comp) loop
- if Ekind (Comp) = E_Component then
- declare
- Comp_Type : constant Entity_Id :=
- Underlying_Type (Etype (Comp));
+ declare
+ Comp_Type : constant Entity_Id :=
+ Underlying_Type (Etype (Comp));
- Hi : Node_Id;
- Indx : Node_Id;
- Ityp : Entity_Id;
+ Hi : Node_Id;
+ Indx : Node_Id;
+ Ityp : Entity_Id;
- begin
- if Is_Array_Type (Comp_Type) then
- Indx := First_Index (Comp_Type);
-
- while Present (Indx) loop
- Ityp := Etype (Indx);
- Hi := Type_High_Bound (Ityp);
-
- if Nkind (Hi) = N_Identifier
- and then Ekind (Entity (Hi)) = E_Discriminant
- and then Is_Large_Discrete_Type (Ityp)
- and then Is_Large_Discrete_Type
- (Etype (Entity (Hi)))
- then
- return True;
- end if;
+ begin
+ if Is_Array_Type (Comp_Type) then
+ Indx := First_Index (Comp_Type);
+
+ while Present (Indx) loop
+ Ityp := Etype (Indx);
+ Hi := Type_High_Bound (Ityp);
+
+ if Nkind (Hi) = N_Identifier
+ and then Ekind (Entity (Hi)) = E_Discriminant
+ and then Is_Large_Discrete_Type (Ityp)
+ and then Is_Large_Discrete_Type
+ (Etype (Entity (Hi)))
+ then
+ return True;
+ end if;
- Next_Index (Indx);
- end loop;
- end if;
- end;
- end if;
+ Next_Index (Indx);
+ end loop;
+ end if;
+ end;
- Next_Entity (Comp);
+ Next_Component (Comp);
end loop;
end;
end if;
@@ -22134,6 +23362,7 @@ package body Sem_Util is
------------------------
function No_Caching_Enabled (Id : Entity_Id) return Boolean is
+ pragma Assert (Ekind (Id) = E_Variable);
Prag : constant Node_Id := Get_Pragma (Id, Pragma_No_Caching);
Arg1 : Node_Id;
@@ -22167,7 +23396,7 @@ package body Sem_Util is
function No_Heap_Finalization (Typ : Entity_Id) return Boolean is
begin
- if Ekind_In (Typ, E_Access_Type, E_General_Access_Type)
+ if Ekind (Typ) in E_Access_Type | E_General_Access_Type
and then Is_Library_Level_Entity (Typ)
then
-- A global No_Heap_Finalization pragma applies to all library-level
@@ -22397,9 +23626,9 @@ package body Sem_Util is
then
if No (Actuals)
and then
- Nkind_In (Parent (N), N_Procedure_Call_Statement,
- N_Function_Call,
- N_Parameter_Association)
+ Nkind (Parent (N)) in N_Procedure_Call_Statement
+ | N_Function_Call
+ | N_Parameter_Association
and then Ekind (S) /= E_Function
then
Set_Etype (N, Etype (S));
@@ -22551,15 +23780,13 @@ package body Sem_Util is
end if;
end;
- elsif Nkind_In (Exp, N_Type_Conversion,
- N_Unchecked_Type_Conversion)
+ elsif Nkind (Exp) in N_Type_Conversion | N_Unchecked_Type_Conversion
then
Exp := Expression (Exp);
goto Continue;
- elsif Nkind_In (Exp, N_Slice,
- N_Indexed_Component,
- N_Selected_Component)
+ elsif Nkind (Exp) in
+ N_Slice | N_Indexed_Component | N_Selected_Component
then
-- Special check, if the prefix is an access type, then return
-- since we are modifying the thing pointed to, not the prefix.
@@ -22620,7 +23847,7 @@ package body Sem_Util is
-- Follow renaming chain
- if (Ekind (Ent) = E_Variable or else Ekind (Ent) = E_Constant)
+ if Ekind (Ent) in E_Variable | E_Constant
and then Present (Renamed_Object (Ent))
then
Exp := Renamed_Object (Ent);
@@ -22643,8 +23870,8 @@ package body Sem_Util is
-- a modification of the container.
elsif Comes_From_Source (Original_Node (Exp))
- and then Nkind_In (Original_Node (Exp), N_Selected_Component,
- N_Indexed_Component)
+ and then Nkind (Original_Node (Exp)) in
+ N_Selected_Component | N_Indexed_Component
then
Exp := Prefix (Original_Node (Exp));
goto Continue;
@@ -22737,13 +23964,12 @@ package body Sem_Util is
function Is_Null_Excluding_Def (Def : Node_Id) return Boolean is
begin
- return
- Nkind_In (Def, N_Access_Definition,
- N_Access_Function_Definition,
- N_Access_Procedure_Definition,
- N_Access_To_Object_Definition,
- N_Component_Definition,
- N_Derived_Type_Definition)
+ return Nkind (Def) in N_Access_Definition
+ | N_Access_Function_Definition
+ | N_Access_Procedure_Definition
+ | N_Access_To_Object_Definition
+ | N_Component_Definition
+ | N_Derived_Type_Definition
and then Null_Exclusion_Present (Def);
end Is_Null_Excluding_Def;
@@ -22765,12 +23991,12 @@ package body Sem_Util is
if Is_Imported (Id) or else Is_Exported (Id) then
return Unknown;
- elsif Nkind_In (Decl, N_Component_Declaration,
- N_Discriminant_Specification,
- N_Formal_Object_Declaration,
- N_Object_Declaration,
- N_Object_Renaming_Declaration,
- N_Parameter_Specification)
+ elsif Nkind (Decl) in N_Component_Declaration
+ | N_Discriminant_Specification
+ | N_Formal_Object_Declaration
+ | N_Object_Declaration
+ | N_Object_Renaming_Declaration
+ | N_Parameter_Specification
then
-- A component declaration yields a non-null value when either
-- its component definition or access definition carries a null
@@ -22891,9 +24117,9 @@ package body Sem_Util is
-- Taking the 'Access of something yields a non-null value
elsif Nkind (N) = N_Attribute_Reference
- and then Nam_In (Attribute_Name (N), Name_Access,
- Name_Unchecked_Access,
- Name_Unrestricted_Access)
+ and then Attribute_Name (N) in Name_Access
+ | Name_Unchecked_Access
+ | Name_Unrestricted_Access
then
return Is_Non_Null;
@@ -22937,7 +24163,8 @@ package body Sem_Util is
if Nkind (N) = N_Null then
return Present (Typ) and then Is_Descendant_Of_Address (Typ);
- elsif Nkind_In (N, N_Op_Eq, N_Op_Ge, N_Op_Gt, N_Op_Le, N_Op_Lt, N_Op_Ne)
+ elsif Nkind (N) in
+ N_Op_Eq | N_Op_Ge | N_Op_Gt | N_Op_Le | N_Op_Lt | N_Op_Ne
then
declare
L : constant Node_Id := Left_Opnd (N);
@@ -23061,18 +24288,31 @@ package body Sem_Util is
-- Local variables
- E : Entity_Id;
+ E : Entity_Id;
+ Orig_Obj : Node_Id := Original_Node (Obj);
+ Orig_Pre : Node_Id;
-- Start of processing for Object_Access_Level
begin
- if Nkind (Obj) = N_Defining_Identifier
- or else Is_Entity_Name (Obj)
+ -- In the case of an expanded implicit dereference we swap the original
+ -- object to be the expanded conversion.
+
+ if Nkind (Obj) = N_Explicit_Dereference
+ and then Nkind (Orig_Obj) /= N_Explicit_Dereference
+ then
+ Orig_Obj := Obj;
+ end if;
+
+ -- Calculate the object node's accessibility level
+
+ if Nkind (Orig_Obj) = N_Defining_Identifier
+ or else Is_Entity_Name (Orig_Obj)
then
- if Nkind (Obj) = N_Defining_Identifier then
- E := Obj;
+ if Nkind (Orig_Obj) = N_Defining_Identifier then
+ E := Orig_Obj;
else
- E := Entity (Obj);
+ E := Entity (Orig_Obj);
end if;
if Is_Prival (E) then
@@ -23085,7 +24325,7 @@ package body Sem_Util is
-- than the level of any visible named access type (see 3.10.2(21)).
if Is_Type (E) then
- return Type_Access_Level (E) + 1;
+ return Type_Access_Level (E) + 1;
elsif Present (Renamed_Object (E)) then
return Object_Access_Level (Renamed_Object (E));
@@ -23102,31 +24342,27 @@ package body Sem_Util is
then
return Type_Access_Level (Scope (E)) + 1;
- else
- -- Aliased formals of functions take their access level from the
- -- point of call, i.e. require a dynamic check. For static check
- -- purposes, this is smaller than the level of the subprogram
- -- itself. For procedures the aliased makes no difference.
-
- if Is_Formal (E)
- and then Is_Aliased (E)
- and then Ekind (Scope (E)) = E_Function
- then
- return Type_Access_Level (Etype (E));
+ -- An object of a named access type gets its level from its
+ -- associated type.
- else
- return Scope_Depth (Enclosing_Dynamic_Scope (E));
- end if;
+ elsif Is_Named_Access_Type (Etype (E)) then
+ return Type_Access_Level (Etype (E));
+
+ else
+ return Scope_Depth (Enclosing_Dynamic_Scope (E));
end if;
- elsif Nkind_In (Obj, N_Indexed_Component, N_Selected_Component) then
- if Is_Access_Type (Etype (Prefix (Obj))) then
- return Type_Access_Level (Etype (Prefix (Obj)));
+ elsif Nkind (Orig_Obj) in N_Indexed_Component | N_Selected_Component then
+ Orig_Pre := Original_Node (Prefix (Orig_Obj));
+
+ if Is_Access_Type (Etype (Orig_Pre)) then
+ return Type_Access_Level (Etype (Orig_Pre));
else
- return Object_Access_Level (Prefix (Obj));
+ return Object_Access_Level (Prefix (Orig_Obj));
end if;
- elsif Nkind (Obj) = N_Explicit_Dereference then
+ elsif Nkind (Orig_Obj) = N_Explicit_Dereference then
+ Orig_Pre := Original_Node (Prefix (Orig_Obj));
-- If the prefix is a selected access discriminant then we make a
-- recursive call on the prefix, which will in turn check the level
@@ -23138,46 +24374,47 @@ package body Sem_Util is
-- otherwise expansion will already have transformed the prefix into
-- a temporary.
- if Nkind (Prefix (Obj)) = N_Selected_Component
- and then Ekind (Etype (Prefix (Obj))) = E_Anonymous_Access_Type
+ if Nkind (Orig_Pre) = N_Selected_Component
+ and then Ekind (Etype (Orig_Pre)) = E_Anonymous_Access_Type
and then
- Ekind (Entity (Selector_Name (Prefix (Obj)))) = E_Discriminant
+ Ekind (Entity (Selector_Name (Orig_Pre))) = E_Discriminant
and then
(not Has_Implicit_Dereference
- (Entity (Selector_Name (Prefix (Obj))))
+ (Entity (Selector_Name (Orig_Pre)))
or else Nkind (Parent (Obj)) /= N_Selected_Component)
then
- return Object_Access_Level (Prefix (Obj));
+ return Object_Access_Level (Prefix (Orig_Obj));
-- Detect an interface conversion in the context of a dispatching
-- call. Use the original form of the conversion to find the access
-- level of the operand.
- elsif Is_Interface (Etype (Obj))
- and then Is_Interface_Conversion (Prefix (Obj))
- and then Nkind (Original_Node (Obj)) = N_Type_Conversion
+ elsif Is_Interface (Etype (Orig_Obj))
+ and then Is_Interface_Conversion (Orig_Pre)
+ and then Nkind (Orig_Obj) = N_Type_Conversion
then
- return Object_Access_Level (Original_Node (Obj));
+ return Object_Access_Level (Orig_Obj);
- elsif not Comes_From_Source (Obj) then
+ elsif not Comes_From_Source (Orig_Obj) then
declare
- Ref : constant Node_Id := Reference_To (Obj);
+ Ref : constant Node_Id := Reference_To (Orig_Obj);
begin
if Present (Ref) then
return Object_Access_Level (Ref);
else
- return Type_Access_Level (Etype (Prefix (Obj)));
+ return Type_Access_Level (Etype (Prefix (Orig_Obj)));
end if;
end;
else
- return Type_Access_Level (Etype (Prefix (Obj)));
+ return Type_Access_Level (Etype (Prefix (Orig_Obj)));
end if;
- elsif Nkind_In (Obj, N_Type_Conversion, N_Unchecked_Type_Conversion) then
- return Object_Access_Level (Expression (Obj));
+ elsif Nkind (Orig_Obj) in N_Type_Conversion | N_Unchecked_Type_Conversion
+ then
+ return Object_Access_Level (Expression (Orig_Obj));
- elsif Nkind (Obj) = N_Function_Call then
+ elsif Nkind (Orig_Obj) = N_Function_Call then
-- Function results are objects, so we get either the access level of
-- the function or, in the case of an indirect call, the level of the
@@ -23188,10 +24425,10 @@ package body Sem_Util is
-- compiled with -gnat95. ???)
if Ada_Version < Ada_2005 then
- if Is_Entity_Name (Name (Obj)) then
- return Subprogram_Access_Level (Entity (Name (Obj)));
+ if Is_Entity_Name (Name (Orig_Obj)) then
+ return Subprogram_Access_Level (Entity (Name (Orig_Obj)));
else
- return Type_Access_Level (Etype (Prefix (Name (Obj))));
+ return Type_Access_Level (Etype (Prefix (Name (Orig_Obj))));
end if;
-- For Ada 2005, the level of the result object of a function call is
@@ -23291,6 +24528,9 @@ package body Sem_Util is
-- Start of processing for Return_Master_Scope_Depth_Of_Call
begin
+ -- Expanded code may have clobbered the scoping data from the
+ -- original object node - so use the expanded one.
+
return Innermost_Master_Scope_Depth (Obj);
end Return_Master_Scope_Depth_Of_Call;
end if;
@@ -23298,15 +24538,34 @@ package body Sem_Util is
-- For convenience we handle qualified expressions, even though they
-- aren't technically object names.
- elsif Nkind (Obj) = N_Qualified_Expression then
- return Object_Access_Level (Expression (Obj));
+ elsif Nkind (Orig_Obj) = N_Qualified_Expression then
+ return Object_Access_Level (Expression (Orig_Obj));
-- Ditto for aggregates. They have the level of the temporary that
-- will hold their value.
- elsif Nkind (Obj) = N_Aggregate then
+ elsif Nkind (Orig_Obj) = N_Aggregate then
+ return Object_Access_Level (Current_Scope);
+
+ -- Treat an Old/Loop_Entry attribute reference like an aggregate.
+ -- AARM 6.1.1(27.d) says "... the implicit constant declaration
+ -- defines the accessibility level of X'Old", so that is what
+ -- we are trying to implement here.
+
+ elsif Nkind (Orig_Obj) = N_Attribute_Reference
+ and then Attribute_Name (Orig_Obj) in Name_Old | Name_Loop_Entry
+ then
return Object_Access_Level (Current_Scope);
+ -- Move up the attribute reference when we encounter a 'Access variation
+
+ elsif Nkind (Orig_Obj) = N_Attribute_Reference
+ and then Attribute_Name (Orig_Obj) in Name_Access
+ | Name_Unchecked_Access
+ | Name_Unrestricted_Access
+ then
+ return Object_Access_Level (Prefix (Orig_Obj));
+
-- Otherwise return the scope level of Standard. (If there are cases
-- that fall through to this point they will be treated as having
-- global accessibility for now. ???)
@@ -23424,7 +24683,7 @@ package body Sem_Util is
Item_Nam : Name_Id;
begin
- pragma Assert (Nkind_In (N, N_Aspect_Specification, N_Pragma));
+ pragma Assert (Nkind (N) in N_Aspect_Specification | N_Pragma);
Item := N;
@@ -23463,8 +24722,7 @@ package body Sem_Util is
elsif Item_Nam = Name_Pre then
Item_Nam := Name_uPre;
- elsif Nam_In (Item_Nam, Name_Type_Invariant,
- Name_Type_Invariant_Class)
+ elsif Item_Nam in Name_Type_Invariant | Name_Type_Invariant_Class
then
Item_Nam := Name_uType_Invariant;
@@ -23572,7 +24830,7 @@ package body Sem_Util is
-- The current Check_Policy pragma matches the requested policy or
-- appears in the single argument form (Assertion, policy_id).
- if Nam_In (Chars (Arg1), Name_Assertion, Policy) then
+ if Chars (Arg1) in Name_Assertion | Policy then
return Chars (Arg2);
end if;
@@ -23619,7 +24877,7 @@ package body Sem_Util is
-- assertions, unless they are disabled. Force Name_Check on
-- ignored assertions.
- if Nam_In (Kind, Name_Ignore, Name_Off)
+ if Kind in Name_Ignore | Name_Off
and then (CodePeer_Mode or GNATprove_Mode)
then
Kind := Name_Check;
@@ -23628,6 +24886,17 @@ package body Sem_Util is
return Kind;
end Policy_In_Effect;
+ -----------------------
+ -- Predicate_Enabled --
+ -----------------------
+
+ function Predicate_Enabled (Typ : Entity_Id) return Boolean is
+ begin
+ return Present (Predicate_Function (Typ))
+ and then not Predicates_Ignored (Typ)
+ and then not Predicate_Checks_Suppressed (Empty);
+ end Predicate_Enabled;
+
----------------------------------
-- Predicate_Tests_On_Arguments --
----------------------------------
@@ -23966,19 +25235,6 @@ package body Sem_Util is
Get_Decoded_Name_String (Chars (Endl));
Set_Sloc (Endl, Sloc (Endl) + Source_Ptr (Name_Len));
-
- else
- -- In SPARK mode, no missing label is allowed for packages and
- -- subprogram bodies. Detect those cases by testing whether
- -- Process_End_Label was called for a body (Typ = 't') or a package.
-
- if Restriction_Check_Required (SPARK_05)
- and then (Typ = 't' or else Ekind (Ent) = E_Package)
- then
- Error_Msg_Node_1 := Endl;
- Check_SPARK_05_Restriction
- ("`END &` required", Endl, Force => True);
- end if;
end if;
-- Now generate the e/t reference
@@ -24046,13 +25302,11 @@ package body Sem_Util is
-- The setting of the attributes is intentionally conservative. This
-- prevents accidental clobbering of enabled attributes.
- if Has_Inherited_DIC (From_Typ)
- and then not Has_Inherited_DIC (Typ)
- then
+ if Has_Inherited_DIC (From_Typ) then
Set_Has_Inherited_DIC (Typ);
end if;
- if Has_Own_DIC (From_Typ) and then not Has_Own_DIC (Typ) then
+ if Has_Own_DIC (From_Typ) then
Set_Has_Own_DIC (Typ);
end if;
@@ -24090,21 +25344,15 @@ package body Sem_Util is
-- The setting of the attributes is intentionally conservative. This
-- prevents accidental clobbering of enabled attributes.
- if Has_Inheritable_Invariants (From_Typ)
- and then not Has_Inheritable_Invariants (Typ)
- then
+ if Has_Inheritable_Invariants (From_Typ) then
Set_Has_Inheritable_Invariants (Typ);
end if;
- if Has_Inherited_Invariants (From_Typ)
- and then not Has_Inherited_Invariants (Typ)
- then
+ if Has_Inherited_Invariants (From_Typ) then
Set_Has_Inherited_Invariants (Typ);
end if;
- if Has_Own_Invariants (From_Typ)
- and then not Has_Own_Invariants (Typ)
- then
+ if Has_Own_Invariants (From_Typ) then
Set_Has_Own_Invariants (Typ);
end if;
@@ -24119,6 +25367,48 @@ package body Sem_Util is
end if;
end Propagate_Invariant_Attributes;
+ ------------------------------------
+ -- Propagate_Predicate_Attributes --
+ ------------------------------------
+
+ procedure Propagate_Predicate_Attributes
+ (Typ : Entity_Id;
+ From_Typ : Entity_Id)
+ is
+ Pred_Func : Entity_Id;
+ Pred_Func_M : Entity_Id;
+
+ begin
+ if Present (Typ) and then Present (From_Typ) then
+ pragma Assert (Is_Type (Typ) and then Is_Type (From_Typ));
+
+ -- Nothing to do if both the source and the destination denote the
+ -- same type.
+
+ if From_Typ = Typ then
+ return;
+ end if;
+
+ Pred_Func := Predicate_Function (From_Typ);
+ Pred_Func_M := Predicate_Function_M (From_Typ);
+
+ -- The setting of the attributes is intentionally conservative. This
+ -- prevents accidental clobbering of enabled attributes.
+
+ if Has_Predicates (From_Typ) then
+ Set_Has_Predicates (Typ);
+ end if;
+
+ if Present (Pred_Func) and then No (Predicate_Function (Typ)) then
+ Set_Predicate_Function (Typ, Pred_Func);
+ end if;
+
+ if Present (Pred_Func_M) and then No (Predicate_Function_M (Typ)) then
+ Set_Predicate_Function_M (Typ, Pred_Func_M);
+ end if;
+ end if;
+ end Propagate_Predicate_Attributes;
+
---------------------------------------
-- Record_Possible_Part_Of_Reference --
---------------------------------------
@@ -24316,7 +25606,7 @@ package body Sem_Util is
-- The entity denotes a primitive subprogram. Remove it from the list of
-- primitives of the associated controlling type.
- if Ekind_In (Id, E_Function, E_Procedure) and then Is_Primitive (Id) then
+ if Ekind (Id) in E_Function | E_Procedure and then Is_Primitive (Id) then
Formal := First_Formal (Id);
while Present (Formal) loop
if Is_Controlling_Formal (Formal) then
@@ -24369,11 +25659,64 @@ package body Sem_Util is
function Requires_Transient_Scope (Id : Entity_Id) return Boolean is
Old_Result : constant Boolean := Old_Requires_Transient_Scope (Id);
+ procedure Ensure_Minimum_Decoration (Typ : Entity_Id);
+ -- If Typ is not frozen then add to Typ the minimum decoration required
+ -- by Requires_Transient_Scope to reliably provide its functionality;
+ -- otherwise no action is performed.
+
+ -------------------------------
+ -- Ensure_Minimum_Decoration --
+ -------------------------------
+
+ procedure Ensure_Minimum_Decoration (Typ : Entity_Id) is
+ begin
+ -- Do not set Has_Controlled_Component on a class-wide equivalent
+ -- type. See Make_CW_Equivalent_Type.
+
+ if Present (Typ)
+ and then not Is_Frozen (Typ)
+ and then (Is_Record_Type (Typ)
+ or else Is_Concurrent_Type (Typ)
+ or else Is_Incomplete_Or_Private_Type (Typ))
+ and then not Is_Class_Wide_Equivalent_Type (Typ)
+ then
+ declare
+ Comp : Entity_Id;
+
+ begin
+ Comp := First_Component (Typ);
+ while Present (Comp) loop
+ if Has_Controlled_Component (Etype (Comp))
+ or else
+ (Chars (Comp) /= Name_uParent
+ and then Is_Controlled (Etype (Comp)))
+ or else
+ (Is_Protected_Type (Etype (Comp))
+ and then
+ Present (Corresponding_Record_Type (Etype (Comp)))
+ and then
+ Has_Controlled_Component
+ (Corresponding_Record_Type (Etype (Comp))))
+ then
+ Set_Has_Controlled_Component (Typ);
+ exit;
+ end if;
+
+ Next_Component (Comp);
+ end loop;
+ end;
+ end if;
+ end Ensure_Minimum_Decoration;
+
+ -- Start of processing for Requires_Transient_Scope
+
begin
if Debug_Flag_QQ then
return Old_Result;
end if;
+ Ensure_Minimum_Decoration (Id);
+
declare
New_Result : constant Boolean := New_Requires_Transient_Scope (Id);
@@ -24500,23 +25843,25 @@ package body Sem_Util is
is
begin
-- The only entities for which we track constant values are variables
- -- which are not renamings, constants, out parameters, and in out
- -- parameters, so check if we have this case.
+ -- which are not renamings, constants and formal parameters, so check
+ -- if we have this case.
-- Note: it may seem odd to track constant values for constants, but in
-- fact this routine is used for other purposes than simply capturing
- -- the value. In particular, the setting of Known[_Non]_Null.
+ -- the value. In particular, the setting of Known[_Non]_Null and
+ -- Is_Known_Valid.
if (Ekind (Ent) = E_Variable and then No (Renamed_Object (Ent)))
- or else
- Ekind_In (Ent, E_Constant, E_Out_Parameter, E_In_Out_Parameter)
+ or else
+ Ekind (Ent) = E_Constant
+ or else
+ Is_Formal (Ent)
then
null;
- -- For conditionals, we also allow loop parameters and all formals,
- -- including in parameters.
+ -- For conditionals, we also allow loop parameters
- elsif Cond and then Ekind_In (Ent, E_Loop_Parameter, E_In_Parameter) then
+ elsif Cond and then Ekind (Ent) = E_Loop_Parameter then
null;
-- For all other cases, not just unsafe, but impossible to capture
@@ -24556,7 +25901,7 @@ package body Sem_Util is
while R_Scope /= Standard_Standard loop
exit when R_Scope = E_Scope;
- if not Ekind_In (R_Scope, E_Package, E_Block, E_Loop) then
+ if Ekind (R_Scope) not in E_Package | E_Block | E_Loop then
return False;
else
R_Scope := Scope (R_Scope);
@@ -24670,7 +26015,7 @@ package body Sem_Util is
EN2 : constant Entity_Id := Entity (N2);
begin
if Present (EN1) and then Present (EN2)
- and then (Ekind_In (EN1, E_Variable, E_Constant)
+ and then (Ekind (EN1) in E_Variable | E_Constant
or else Is_Formal (EN1))
and then EN1 = EN2
then
@@ -24960,8 +26305,8 @@ package body Sem_Util is
Typ : constant Entity_Id := Etype (E);
begin
- if Ekind_In (Typ, E_Anonymous_Access_Type,
- E_Anonymous_Access_Subprogram_Type)
+ if Ekind (Typ) in E_Anonymous_Access_Type
+ | E_Anonymous_Access_Subprogram_Type
and then not Has_Convention_Pragma (Typ)
then
Basic_Set_Convention (Typ, Val);
@@ -25099,7 +26444,7 @@ package body Sem_Util is
begin
while Present (Indx) loop
Set_Debug_Info_Needed_If_Not_Set (Etype (Indx));
- Indx := Next_Index (Indx);
+ Next_Index (Indx);
end loop;
end;
@@ -25166,6 +26511,17 @@ package body Sem_Util is
end if;
end Set_Debug_Info_Needed;
+ --------------------------------
+ -- Set_Debug_Info_Defining_Id --
+ --------------------------------
+
+ procedure Set_Debug_Info_Defining_Id (N : Node_Id) is
+ begin
+ if Comes_From_Source (Defining_Identifier (N)) then
+ Set_Debug_Info_Needed (Defining_Identifier (N));
+ end if;
+ end Set_Debug_Info_Defining_Id;
+
----------------------------
-- Set_Entity_With_Checks --
----------------------------
@@ -25279,7 +26635,7 @@ package body Sem_Util is
or else
(Present (Scope (Val))
and then Is_Implementation_Defined (Scope (Val))))
- and then not (Ekind_In (Val, E_Package, E_Generic_Package)
+ and then not (Is_Package_Or_Generic_Package (Val)
and then Is_Library_Level_Entity (Val))
then
Check_Restriction (No_Implementation_Identifiers, Post_Node);
@@ -25418,8 +26774,8 @@ package body Sem_Util is
if No (N) then
return False;
- elsif Nkind_In (N, N_Handled_Sequence_Of_Statements,
- N_If_Statement)
+ elsif Nkind (N) in
+ N_Handled_Sequence_Of_Statements | N_If_Statement
then
return True;
end if;
@@ -25445,8 +26801,8 @@ package body Sem_Util is
-- never needs to be made public and furthermore, making it public can
-- cause back end problems.
- elsif Nkind_In (Parent (Id), N_Object_Declaration,
- N_Function_Specification)
+ elsif Nkind (Parent (Id)) in
+ N_Object_Declaration | N_Function_Specification
and then Within_HSS_Or_If (Id)
then
return;
@@ -25478,7 +26834,7 @@ package body Sem_Util is
begin
-- Deal with indexed or selected component where prefix is modified
- if Nkind_In (N, N_Indexed_Component, N_Selected_Component) then
+ if Nkind (N) in N_Indexed_Component | N_Selected_Component then
Pref := Prefix (N);
-- If prefix is access type, then it is the designated object that is
@@ -25643,6 +26999,34 @@ package body Sem_Util is
end if;
end Static_Integer;
+ -------------------------------
+ -- Statically_Denotes_Entity --
+ -------------------------------
+ function Statically_Denotes_Entity (N : Node_Id) return Boolean is
+ E : Entity_Id;
+ begin
+ if not Is_Entity_Name (N) then
+ return False;
+ else
+ E := Entity (N);
+ end if;
+
+ return
+ Nkind (Parent (E)) /= N_Object_Renaming_Declaration
+ or else Is_Prival (E)
+ or else Statically_Denotes_Entity (Renamed_Object (E));
+ end Statically_Denotes_Entity;
+
+ -------------------------------
+ -- Statically_Denotes_Object --
+ -------------------------------
+
+ function Statically_Denotes_Object (N : Node_Id) return Boolean is
+ begin
+ return Statically_Denotes_Entity (N)
+ and then Is_Object_Reference (N);
+ end Statically_Denotes_Object;
+
--------------------------
-- Statically_Different --
--------------------------
@@ -25658,6 +27042,162 @@ package body Sem_Util is
and then not Is_Formal (Entity (R2));
end Statically_Different;
+ -----------------------------
+ -- Statically_Names_Object --
+ -----------------------------
+
+ function Statically_Names_Object (N : Node_Id) return Boolean is
+ begin
+ if Statically_Denotes_Object (N) then
+ return True;
+ elsif Is_Entity_Name (N) then
+ declare
+ E : constant Entity_Id := Entity (N);
+ begin
+ return Nkind (Parent (E)) = N_Object_Renaming_Declaration
+ and then Statically_Names_Object (Renamed_Object (E));
+ end;
+ end if;
+
+ case Nkind (N) is
+ when N_Indexed_Component =>
+ if Is_Access_Type (Etype (Prefix (N))) then
+ -- treat implicit dereference same as explicit
+ return False;
+ end if;
+
+ if not Is_Constrained (Etype (Prefix (N))) then
+ return False;
+ end if;
+
+ declare
+ Indx : Node_Id := First_Index (Etype (Prefix (N)));
+ Expr : Node_Id := First (Expressions (N));
+ Index_Subtype : Node_Id;
+ begin
+ loop
+ Index_Subtype := Etype (Indx);
+
+ if not Is_Static_Subtype (Index_Subtype) then
+ return False;
+ end if;
+ if not Is_OK_Static_Expression (Expr) then
+ return False;
+ end if;
+
+ declare
+ Index_Value : constant Uint := Expr_Value (Expr);
+ Low_Value : constant Uint :=
+ Expr_Value (Type_Low_Bound (Index_Subtype));
+ High_Value : constant Uint :=
+ Expr_Value (Type_High_Bound (Index_Subtype));
+ begin
+ if (Index_Value < Low_Value)
+ or (Index_Value > High_Value)
+ then
+ return False;
+ end if;
+ end;
+
+ Next_Index (Indx);
+ Expr := Next (Expr);
+ pragma Assert ((Present (Indx) = Present (Expr))
+ or else (Serious_Errors_Detected > 0));
+ exit when not (Present (Indx) and Present (Expr));
+ end loop;
+ end;
+
+ when N_Selected_Component =>
+ if Is_Access_Type (Etype (Prefix (N))) then
+ -- treat implicit dereference same as explicit
+ return False;
+ end if;
+
+ if Ekind (Entity (Selector_Name (N))) not in
+ E_Component | E_Discriminant
+ then
+ return False;
+ end if;
+
+ declare
+ Comp : constant Entity_Id :=
+ Original_Record_Component (Entity (Selector_Name (N)));
+ begin
+ -- AI12-0373 confirms that we should not call
+ -- Has_Discriminant_Dependent_Constraint here which would be
+ -- too strong.
+
+ if Is_Declared_Within_Variant (Comp) then
+ return False;
+ end if;
+ end;
+
+ when others => -- includes N_Slice, N_Explicit_Dereference
+ return False;
+ end case;
+
+ pragma Assert (Present (Prefix (N)));
+
+ return Statically_Names_Object (Prefix (N));
+ end Statically_Names_Object;
+
+ ---------------------------------
+ -- String_From_Numeric_Literal --
+ ---------------------------------
+
+ function String_From_Numeric_Literal (N : Node_Id) return String_Id is
+ Loc : constant Source_Ptr := Sloc (N);
+ Sbuffer : constant Source_Buffer_Ptr :=
+ Source_Text (Get_Source_File_Index (Loc));
+ Src_Ptr : Source_Ptr := Loc;
+
+ C : Character := Sbuffer (Src_Ptr);
+ -- Current source program character
+
+ function Belongs_To_Numeric_Literal (C : Character) return Boolean;
+ -- Return True if C belongs to the numeric literal
+
+ --------------------------------
+ -- Belongs_To_Numeric_Literal --
+ --------------------------------
+
+ function Belongs_To_Numeric_Literal (C : Character) return Boolean is
+ begin
+ case C is
+ when '0' .. '9'
+ | '_' | '.' | 'e' | '#' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
+ =>
+ return True;
+
+ -- Make sure '+' or '-' is part of an exponent
+
+ when '+' | '-' =>
+ declare
+ Prev_C : constant Character := Sbuffer (Src_Ptr - 1);
+ begin
+ return Prev_C = 'e' or else Prev_C = 'E';
+ end;
+
+ -- Other characters cannot belong to a numeric literal
+
+ when others =>
+ return False;
+ end case;
+ end Belongs_To_Numeric_Literal;
+
+ -- Start of processing for String_From_Numeric_Literal
+
+ begin
+ Start_String;
+ while Belongs_To_Numeric_Literal (C) loop
+ Store_String_Char (C);
+ Src_Ptr := Src_Ptr + 1;
+ C := Sbuffer (Src_Ptr);
+ end loop;
+
+ return End_String;
+ end String_From_Numeric_Literal;
+
--------------------------------------
-- Subject_To_Loop_Entry_Attributes --
--------------------------------------
@@ -25672,7 +27212,7 @@ package body Sem_Util is
-- 'Loop_Entry attribute into a conditional block. Infinite loops lack
-- the conditional part.
- if Nkind_In (Stmt, N_Block_Statement, N_If_Statement)
+ if Nkind (Stmt) in N_Block_Statement | N_If_Statement
and then Nkind (Original_Node (N)) = N_Loop_Statement
then
Stmt := Original_Node (N);
@@ -26334,10 +27874,10 @@ package body Sem_Util is
begin
Pref := N;
- while Nkind_In (Pref, N_Explicit_Dereference,
- N_Indexed_Component,
- N_Selected_Component,
- N_Slice)
+ while Nkind (Pref) in N_Explicit_Dereference
+ | N_Indexed_Component
+ | N_Selected_Component
+ | N_Slice
loop
Pref := Prefix (Pref);
end loop;
@@ -26808,9 +28348,9 @@ package body Sem_Util is
-- Recurse to handle unlikely case of multiple levels of qualification
-- and/or conversion.
- if Nkind_In (Expr, N_Qualified_Expression,
- N_Type_Conversion,
- N_Unchecked_Type_Conversion)
+ if Nkind (Expr) in N_Qualified_Expression
+ | N_Type_Conversion
+ | N_Unchecked_Type_Conversion
then
return Unqual_Conv (Expression (Expr));
@@ -26964,9 +28504,9 @@ package body Sem_Util is
Par := N;
while Present (Par) loop
- if Nkind_In (Par, N_Entry_Call_Statement,
- N_Function_Call,
- N_Procedure_Call_Statement)
+ if Nkind (Par) in N_Entry_Call_Statement
+ | N_Function_Call
+ | N_Procedure_Call_Statement
then
return True;
@@ -27040,8 +28580,8 @@ package body Sem_Util is
if No (E) then
return False;
- elsif not Ekind_In (E, E_Discriminant, E_Component)
- or else Nam_In (Chars (E), Name_uTag, Name_uParent)
+ elsif Ekind (E) not in E_Discriminant | E_Component
+ or else Chars (E) in Name_uTag | Name_uParent
then
Next_Entity (E);
@@ -27096,12 +28636,12 @@ package body Sem_Util is
then
return;
- -- In an instance, there is an ongoing problem with completion of
+ -- In an instance, there is an ongoing problem with completion of
-- types derived from private types. Their structure is what Gigi
- -- expects, but the Etype is the parent type rather than the
- -- derived private type itself. Do not flag error in this case. The
- -- private completion is an entity without a parent, like an Itype.
- -- Similarly, full and partial views may be incorrect in the instance.
+ -- expects, but the Etype is the parent type rather than the derived
+ -- private type itself. Do not flag error in this case. The private
+ -- completion is an entity without a parent, like an Itype. Similarly,
+ -- full and partial views may be incorrect in the instance.
-- There is no simple way to insure that it is consistent ???
-- A similar view discrepancy can happen in an inlined body, for the
@@ -27195,7 +28735,7 @@ package body Sem_Util is
elsif Is_Integer_Type (Expec_Type)
and then Is_RTE (Found_Type, RE_Address)
- and then Nkind_In (Parent (Expr), N_Op_Add, N_Op_Subtract)
+ and then Nkind (Parent (Expr)) in N_Op_Add | N_Op_Subtract
and then Expr = Left_Opnd (Parent (Expr))
and then Is_Integer_Type (Etype (Right_Opnd (Parent (Expr))))
then
@@ -27285,7 +28825,7 @@ package body Sem_Util is
Error_Msg_N ("\\found package name!", Expr);
elsif Is_Entity_Name (Expr)
- and then Ekind_In (Entity (Expr), E_Procedure, E_Generic_Procedure)
+ and then Ekind (Entity (Expr)) in E_Procedure | E_Generic_Procedure
then
if Ekind (Expec_Type) = E_Access_Subprogram_Type then
Error_Msg_N
@@ -27333,7 +28873,7 @@ package body Sem_Util is
if Expec_Type = Standard_Boolean
and then Is_Modular_Integer_Type (Found_Type)
- and then Nkind_In (Parent (Expr), N_Op_And, N_Op_Or, N_Op_Xor)
+ and then Nkind (Parent (Expr)) in N_Op_And | N_Op_Or | N_Op_Xor
and then Nkind (Right_Opnd (Parent (Expr))) in N_Op_Compare
then
declare
@@ -27472,7 +29012,7 @@ package body Sem_Util is
begin
-- Integer and real literals are of a universal type
- if Nkind_In (N, N_Integer_Literal, N_Real_Literal) then
+ if Nkind (N) in N_Integer_Literal | N_Real_Literal then
return True;
-- The values of certain attributes are of a universal type
@@ -27490,26 +29030,113 @@ package body Sem_Util is
package body Interval_Lists is
+ procedure Check_Consistency (Intervals : Discrete_Interval_List);
+ -- Check that list is sorted, lacks null intervals, and has gaps
+ -- between intervals.
+
+ function Chosen_Interval (Choice : Node_Id) return Discrete_Interval;
+ -- Given an element of a Discrete_Choices list, a
+ -- Static_Discrete_Predicate list, or an Others_Discrete_Choices
+ -- list (but not an N_Others_Choice node) return the corresponding
+ -- interval. If an element that does not represent a single
+ -- contiguous interval due to a static predicate (or which
+ -- represents a single contiguous interval whose bounds depend on
+ -- a static predicate) is encountered, then that is an error on the
+ -- part of whoever built the list in question.
+
function In_Interval
(Value : Uint; Interval : Discrete_Interval) return Boolean;
-- Does the given value lie within the given interval?
- -----------------
- -- In_Interval --
- -----------------
- function In_Interval
- (Value : Uint; Interval : Discrete_Interval) return Boolean is
+ procedure Normalize_Interval_List
+ (List : in out Discrete_Interval_List; Last : out Nat);
+ -- Perform sorting and merging as required by Check_Consistency.
+
+ -------------------------
+ -- Aggregate_Intervals --
+ -------------------------
+
+ function Aggregate_Intervals (N : Node_Id) return Discrete_Interval_List
+ is
+ pragma Assert (Nkind (N) = N_Aggregate
+ and then Is_Array_Type (Etype (N)));
+
+ function Unmerged_Intervals_Count return Nat;
+ -- Count the number of intervals given in the aggregate N; the others
+ -- choice (if present) is not taken into account.
+
+ function Unmerged_Intervals_Count return Nat is
+ Count : Nat := 0;
+ Choice : Node_Id;
+ Comp : Node_Id;
+ begin
+ Comp := First (Component_Associations (N));
+ while Present (Comp) loop
+ Choice := First (Choices (Comp));
+
+ while Present (Choice) loop
+ if Nkind (Choice) /= N_Others_Choice then
+ Count := Count + 1;
+ end if;
+
+ Next (Choice);
+ end loop;
+
+ Next (Comp);
+ end loop;
+
+ return Count;
+ end Unmerged_Intervals_Count;
+
+ -- Local variables
+
+ Comp : Node_Id;
+ Max_I : constant Nat := Unmerged_Intervals_Count;
+ Intervals : Discrete_Interval_List (1 .. Max_I);
+ Num_I : Nat := 0;
+
+ -- Start of processing for Aggregate_Intervals
+
begin
- return Value >= Interval.Low and then Value <= Interval.High;
- end In_Interval;
+ -- No action needed if there are no intervals
- procedure Check_Consistency (Intervals : Discrete_Interval_List);
- -- Check that list is sorted, lacks null intervals, and has gaps
- -- between intervals.
+ if Max_I = 0 then
+ return Intervals;
+ end if;
+
+ -- Internally store all the unsorted intervals
+
+ Comp := First (Component_Associations (N));
+ while Present (Comp) loop
+ declare
+ Choice_Intervals : constant Discrete_Interval_List
+ := Choice_List_Intervals (Choices (Comp));
+ begin
+ for J in Choice_Intervals'Range loop
+ Num_I := Num_I + 1;
+ Intervals (Num_I) := Choice_Intervals (J);
+ end loop;
+ end;
+
+ Next (Comp);
+ end loop;
+
+ -- Normalize the lists sorting and merging the intervals
+
+ declare
+ Aggr_Intervals : Discrete_Interval_List (1 .. Num_I)
+ := Intervals (1 .. Num_I);
+ begin
+ Normalize_Interval_List (Aggr_Intervals, Num_I);
+ Check_Consistency (Aggr_Intervals (1 .. Num_I));
+ return Aggr_Intervals (1 .. Num_I);
+ end;
+ end Aggregate_Intervals;
------------------------
-- Check_Consistency --
------------------------
+
procedure Check_Consistency (Intervals : Discrete_Interval_List) is
begin
if Serious_Errors_Detected > 0 then
@@ -27530,19 +29157,79 @@ package body Sem_Util is
end loop;
end Check_Consistency;
- function Chosen_Interval (Choice : Node_Id) return Discrete_Interval;
- -- Given an element of a Discrete_Choices list, a
- -- Static_Discrete_Predicate list, or an Others_Discrete_Choices
- -- list (but not an N_Others_Choice node) return the corresponding
- -- interval. If an element that does not represent a single
- -- contiguous interval due to a static predicate (or which
- -- represents a single contiguous interval whose bounds depend on
- -- a static predicate) is encountered, then that is an error on the
- -- part of whoever built the list in question.
+ ---------------------------
+ -- Choice_List_Intervals --
+ ---------------------------
+
+ function Choice_List_Intervals
+ (Discrete_Choices : List_Id) return Discrete_Interval_List
+ is
+ function Unmerged_Choice_Count return Nat;
+ -- The number of intervals before adjacent intervals are merged.
+
+ ---------------------------
+ -- Unmerged_Choice_Count --
+ ---------------------------
+
+ function Unmerged_Choice_Count return Nat is
+ Choice : Node_Id := First (Discrete_Choices);
+ Count : Nat := 0;
+ begin
+ while Present (Choice) loop
+ -- Non-contiguous choices involving static predicates
+ -- have already been normalized away.
+
+ if Nkind (Choice) = N_Others_Choice then
+ Count :=
+ Count + List_Length (Others_Discrete_Choices (Choice));
+ else
+ Count := Count + 1; -- an ordinary expression or range
+ end if;
+
+ Next (Choice);
+ end loop;
+ return Count;
+ end Unmerged_Choice_Count;
+
+ -- Local variables
+
+ Choice : Node_Id := First (Discrete_Choices);
+ Result : Discrete_Interval_List (1 .. Unmerged_Choice_Count);
+ Count : Nat := 0;
+
+ -- Start of processing for Choice_List_Intervals
+
+ begin
+ while Present (Choice) loop
+ if Nkind (Choice) = N_Others_Choice then
+ declare
+ Others_Choice : Node_Id
+ := First (Others_Discrete_Choices (Choice));
+ begin
+ while Present (Others_Choice) loop
+ Count := Count + 1;
+ Result (Count) := Chosen_Interval (Others_Choice);
+ Next (Others_Choice);
+ end loop;
+ end;
+ else
+ Count := Count + 1;
+ Result (Count) := Chosen_Interval (Choice);
+ end if;
+
+ Next (Choice);
+ end loop;
+
+ pragma Assert (Count = Result'Last);
+ Normalize_Interval_List (Result, Count);
+ Check_Consistency (Result (1 .. Count));
+ return Result (1 .. Count);
+ end Choice_List_Intervals;
---------------------
-- Chosen_Interval --
---------------------
+
function Chosen_Interval (Choice : Node_Id) return Discrete_Interval is
begin
case Nkind (Choice) is
@@ -27575,97 +29262,105 @@ package body Sem_Util is
end case;
end Chosen_Interval;
- --------------------
- -- Type_Intervals --
- --------------------
- function Type_Intervals
- (Typ : Entity_Id) return Discrete_Interval_List
+ -----------------
+ -- In_Interval --
+ -----------------
+
+ function In_Interval
+ (Value : Uint; Interval : Discrete_Interval) return Boolean is
+ begin
+ return Value >= Interval.Low and then Value <= Interval.High;
+ end In_Interval;
+
+ ---------------
+ -- Is_Subset --
+ ---------------
+
+ function Is_Subset
+ (Subset, Of_Set : Discrete_Interval_List) return Boolean
is
+ -- Returns True iff for each interval of Subset we can find
+ -- a single interval of Of_Set which contains the Subset interval.
begin
- if Has_Static_Predicate (Typ) then
- declare
- -- No sorting or merging needed
- SDP_List : constant List_Id := Static_Discrete_Predicate (Typ);
- Range_Or_Expr : Node_Id := First (SDP_List);
- Result :
- Discrete_Interval_List (1 .. List_Length (SDP_List));
- begin
- for Idx in Result'Range loop
- Result (Idx) := Chosen_Interval (Range_Or_Expr);
- Range_Or_Expr := Next (Range_Or_Expr);
+ if Of_Set'Length = 0 then
+ return Subset'Length = 0;
+ end if;
+
+ declare
+ Set_Index : Pos range Of_Set'Range := Of_Set'First;
+
+ begin
+ for Ss_Idx in Subset'Range loop
+ while not In_Interval
+ (Value => Subset (Ss_Idx).Low,
+ Interval => Of_Set (Set_Index))
+ loop
+ if Set_Index = Of_Set'Last then
+ return False;
+ end if;
+
+ Set_Index := Set_Index + 1;
end loop;
- pragma Assert (not Present (Range_Or_Expr));
- Check_Consistency (Result);
- return Result;
- end;
- else
- declare
- Low : constant Uint := Expr_Value (Type_Low_Bound (Typ));
- High : constant Uint := Expr_Value (Type_High_Bound (Typ));
- begin
- if Low > High then
- declare
- Null_Array : Discrete_Interval_List (1 .. 0);
- begin
- return Null_Array;
- end;
- else
- return (1 => (Low => Low, High => High));
+
+ if not In_Interval
+ (Value => Subset (Ss_Idx).High,
+ Interval => Of_Set (Set_Index))
+ then
+ return False;
end if;
- end;
- end if;
- end Type_Intervals;
+ end loop;
+ end;
- procedure Normalize_Interval_List
- (List : in out Discrete_Interval_List; Last : out Nat);
- -- Perform sorting and merging as required by Check_Consistency.
+ return True;
+ end Is_Subset;
-----------------------------
-- Normalize_Interval_List --
-----------------------------
+
procedure Normalize_Interval_List
- (List : in out Discrete_Interval_List; Last : out Nat) is
+ (List : in out Discrete_Interval_List; Last : out Nat)
+ is
+ Temp_0 : Discrete_Interval := (others => Uint_0);
+ -- Cope with Heap_Sort_G idiosyncrasies.
- procedure Move_Interval (From, To : Natural);
- -- Copy interval from one location to another
+ function Is_Null (Idx : Pos) return Boolean;
+ -- True iff List (Idx) defines a null range
function Lt_Interval (Idx1, Idx2 : Natural) return Boolean;
-- Compare two list elements
- Temp_0 : Discrete_Interval := (others => Uint_0);
- -- cope with Heap_Sort_G idiosyncrasies.
+ procedure Merge_Intervals (Null_Interval_Count : out Nat);
+ -- Merge contiguous ranges by replacing one with merged range and
+ -- the other with a null value. Return a count of the null intervals,
+ -- both preexisting and those introduced by merging.
+
+ procedure Move_Interval (From, To : Natural);
+ -- Copy interval from one location to another
function Read_Interval (From : Natural) return Discrete_Interval;
-- Normal array indexing unless From = 0
- -------------------
- -- Read_Interval --
- -------------------
- function Read_Interval (From : Natural) return Discrete_Interval is
- begin
- if From = 0 then
- return Temp_0;
- else
- return List (Pos (From));
- end if;
- end Read_Interval;
+ ----------------------
+ -- Interval_Sorting --
+ ----------------------
- -------------------
- -- Move_Interval --
- -------------------
- procedure Move_Interval (From, To : Natural) is
- Rhs : constant Discrete_Interval := Read_Interval (From);
+ package Interval_Sorting is
+ new Gnat.Heap_Sort_G (Move_Interval, Lt_Interval);
+
+ -------------
+ -- Is_Null --
+ -------------
+
+ function Is_Null (Idx : Pos) return Boolean is
begin
- if To = 0 then
- Temp_0 := Rhs;
- else
- List (Pos (To)) := Rhs;
- end if;
- end Move_Interval;
+ return List (Idx).Low > List (Idx).High;
+ end Is_Null;
-----------------
-- Lt_Interval --
-----------------
+
function Lt_Interval (Idx1, Idx2 : Natural) return Boolean is
Elem1 : constant Discrete_Interval := Read_Interval (Idx1);
Elem2 : constant Discrete_Interval := Read_Interval (Idx2);
@@ -27675,33 +29370,19 @@ package body Sem_Util is
if Null_1 /= Null_2 then
-- So that sorting moves null intervals to high end
return Null_2;
+
elsif Elem1.Low /= Elem2.Low then
return Elem1.Low < Elem2.Low;
+
else
return Elem1.High < Elem2.High;
end if;
end Lt_Interval;
- package Interval_Sorting is
- new Gnat.Heap_Sort_G (Move_Interval, Lt_Interval);
-
- function Is_Null (Idx : Pos) return Boolean;
- -- True iff List (Idx) defines a null range
-
- function Is_Null (Idx : Pos) return Boolean is
- begin
- return List (Idx).Low > List (Idx).High;
- end Is_Null;
-
- procedure Merge_Intervals (Null_Interval_Count : out Nat);
- -- Merge contiguous ranges by replacing one with merged range
- -- and the other with a null value. Return a count of the
- -- null intervals, both preexisting and those introduced by
- -- merging.
-
---------------------
-- Merge_Intervals --
---------------------
+
procedure Merge_Intervals (Null_Interval_Count : out Nat) is
Not_Null : Pos range List'Range;
-- Index of the most recently examined non-null interval
@@ -27717,30 +29398,74 @@ package body Sem_Util is
Null_Interval_Count := 0;
Not_Null := List'First;
+
for Idx in List'First + 1 .. List'Last loop
if Is_Null (Idx) then
+
-- all remaining elements are null
+
Null_Interval_Count :=
Null_Interval_Count + List (Idx .. List'Last)'Length;
return;
+
elsif List (Idx).Low = List (Not_Null).High + 1 then
+
-- Merge the two intervals into one; discard the other
+
List (Not_Null).High := List (Idx).High;
List (Idx) := Null_Interval;
Null_Interval_Count := Null_Interval_Count + 1;
+
else
+ if List (Idx).Low <= List (Not_Null).High then
+ raise Intervals_Error;
+ end if;
+
pragma Assert (List (Idx).Low > List (Not_Null).High);
Not_Null := Idx;
end if;
end loop;
end Merge_Intervals;
+
+ -------------------
+ -- Move_Interval --
+ -------------------
+
+ procedure Move_Interval (From, To : Natural) is
+ Rhs : constant Discrete_Interval := Read_Interval (From);
+ begin
+ if To = 0 then
+ Temp_0 := Rhs;
+ else
+ List (Pos (To)) := Rhs;
+ end if;
+ end Move_Interval;
+
+ -------------------
+ -- Read_Interval --
+ -------------------
+
+ function Read_Interval (From : Natural) return Discrete_Interval is
+ begin
+ if From = 0 then
+ return Temp_0;
+ else
+ return List (Pos (From));
+ end if;
+ end Read_Interval;
+
+ -- Start of processing for Normalize_Interval_Lists
+
begin
Interval_Sorting.Sort (Natural (List'Last));
+
declare
Null_Interval_Count : Nat;
+
begin
Merge_Intervals (Null_Interval_Count);
Last := List'Last - Null_Interval_Count;
+
if Null_Interval_Count /= 0 then
-- Move null intervals introduced during merging to high end
Interval_Sorting.Sort (Natural (List'Last));
@@ -27748,104 +29473,47 @@ package body Sem_Util is
end;
end Normalize_Interval_List;
- ---------------------------
- -- Choice_List_Intervals --
- ---------------------------
- function Choice_List_Intervals
- (Discrete_Choices : List_Id) return Discrete_Interval_List
- is
- function Unmerged_Choice_Count return Nat;
- -- The number of intervals before adjacent intervals are merged.
-
- ---------------------------
- -- Unmerged_Choice_Count --
- ---------------------------
- function Unmerged_Choice_Count return Nat is
- Choice : Node_Id := First (Discrete_Choices);
- Count : Nat := 0;
- begin
- while Present (Choice) loop
- -- Non-contiguous choices involving static predicates
- -- have already been normalized away.
-
- if Nkind (Choice) = N_Others_Choice then
- Count :=
- Count + List_Length (Others_Discrete_Choices (Choice));
- else
- Count := Count + 1; -- an ordinary expression or range
- end if;
-
- Choice := Next (Choice);
- end loop;
- return Count;
- end Unmerged_Choice_Count;
-
- Choice : Node_Id := First (Discrete_Choices);
- Result : Discrete_Interval_List (1 .. Unmerged_Choice_Count);
- Count : Nat := 0;
- begin
- while Present (Choice) loop
- if Nkind (Choice) = N_Others_Choice then
- declare
- Others_Choice : Node_Id
- := First (Others_Discrete_Choices (Choice));
- begin
- while Present (Others_Choice) loop
- Count := Count + 1;
- Result (Count) := Chosen_Interval (Others_Choice);
- Others_Choice := Next (Others_Choice);
- end loop;
- end;
- else
- Count := Count + 1;
- Result (Count) := Chosen_Interval (Choice);
- end if;
- Choice := Next (Choice);
- end loop;
- pragma Assert (Count = Result'Last);
- Normalize_Interval_List (Result, Count);
- Check_Consistency (Result (1 .. Count));
- return Result (1 .. Count);
- end Choice_List_Intervals;
+ --------------------
+ -- Type_Intervals --
+ --------------------
- ---------------
- -- Is_Subset --
- ---------------
- function Is_Subset
- (Subset, Of_Set : Discrete_Interval_List) return Boolean
+ function Type_Intervals (Typ : Entity_Id) return Discrete_Interval_List
is
- -- Returns True iff for each interval of Subset we can find
- -- a single interval of Of_Set which contains the Subset interval.
begin
- if Of_Set'Length = 0 then
- return Subset'Length = 0;
- end if;
+ if Has_Static_Predicate (Typ) then
+ declare
+ -- No sorting or merging needed
+ SDP_List : constant List_Id := Static_Discrete_Predicate (Typ);
+ Range_Or_Expr : Node_Id := First (SDP_List);
+ Result : Discrete_Interval_List (1 .. List_Length (SDP_List));
- declare
- Set_Index : Pos range Of_Set'Range := Of_Set'First;
- begin
- for Ss_Idx in Subset'Range loop
- while not In_Interval
- (Value => Subset (Ss_Idx).Low,
- Interval => Of_Set (Set_Index))
- loop
- if Set_Index = Of_Set'Last then
- return False;
- end if;
- Set_Index := Set_Index + 1;
+ begin
+ for Idx in Result'Range loop
+ Result (Idx) := Chosen_Interval (Range_Or_Expr);
+ Next (Range_Or_Expr);
end loop;
- if not In_Interval
- (Value => Subset (Ss_Idx).High,
- Interval => Of_Set (Set_Index))
- then
- return False;
+ pragma Assert (not Present (Range_Or_Expr));
+ Check_Consistency (Result);
+ return Result;
+ end;
+ else
+ declare
+ Low : constant Uint := Expr_Value (Type_Low_Bound (Typ));
+ High : constant Uint := Expr_Value (Type_High_Bound (Typ));
+ begin
+ if Low > High then
+ declare
+ Null_Array : Discrete_Interval_List (1 .. 0);
+ begin
+ return Null_Array;
+ end;
+ else
+ return (1 => (Low => Low, High => High));
end if;
- end loop;
- end;
-
- return True;
- end Is_Subset;
+ end;
+ end if;
+ end Type_Intervals;
end Interval_Lists;