aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sem_ch13.adb
diff options
context:
space:
mode:
authorHristian Kirtchev <kirtchev@adacore.com>2015-05-26 10:46:58 +0000
committerArnaud Charlet <charlet@gcc.gnu.org>2015-05-26 12:46:58 +0200
commit241ebe892af143aaf8cce4bfd80f9b8dce97fe72 (patch)
treebed88940e055630033e81202254038ad081b708f /gcc/ada/sem_ch13.adb
parent138cac6426259ed3ed98371f0aa0989df32c0724 (diff)
downloadgcc-241ebe892af143aaf8cce4bfd80f9b8dce97fe72.zip
gcc-241ebe892af143aaf8cce4bfd80f9b8dce97fe72.tar.gz
gcc-241ebe892af143aaf8cce4bfd80f9b8dce97fe72.tar.bz2
exp_ch3.adb (Expand_N_Full_Type_Declaration): Capture, set and restore the Ghost mode.
2015-05-26 Hristian Kirtchev <kirtchev@adacore.com> * exp_ch3.adb (Expand_N_Full_Type_Declaration): Capture, set and restore the Ghost mode. (Expand_N_Object_Declaration): Capture, set and restore the Ghost mode. (Freeze_Type): Update the call to Set_Ghost_Mode. (Restore_Globals): New routine. * exp_ch5.adb Add with and use clauses for Ghost. (Expand_N_Assignment_Statement): Capture, set and restore the Ghost mode. (Restore_Globals): New routine. * exp_ch6.adb Add with and use clauses for Ghost. (Expand_N_Procedure_Call_Statement): Capture, set and restore the Ghost mode. (Expand_N_Subprogram_Body): Code cleanup. Capture, set and restore the Ghost mode. (Expand_N_Subprogram_Declaration): Capture, set and restore the Ghost mode. (Restore_Globals): New routine. * exp_ch7.adb Add with and use clauses for Ghost. (Expand_N_Package_Body): Capture, set and restore the Ghost mode. (Expand_N_Package_Declaration): Capture, set and restore the Ghost mode. (Wrap_HSS_In_Block): Create a proper identifier for the block. * exp_ch8.adb Add with and use clauses for Ghost. (Expand_N_Exception_Renaming_Declaration): Code cleanup. Capture, set and restore the Ghost mode. (Expand_N_Object_Renaming_Declaration): Capture, set and restore the Ghost mode. (Expand_N_Package_Renaming_Declaration): Capture, set and restore the Ghost mode. (Expand_N_Subprogram_Renaming_Declaration): Capture, set and restore the Ghost mode. * exp_ch11.adb (Expand_N_Exception_Declaration): Code cleanup. Capture, set and restore the Ghost mode. * exp_disp.adb (Make_DT): Update the call to Set_Ghost_Mode. Do not initialize the dispatch table slot of a Ghost subprogram. * exp_prag.adb Add with and use clauses for Ghost. (Expand_Pragma_Check): Capture, set and restore the Ghost mode. (Expand_Pragma_Contract_Cases): Capture, set and restore the Ghost mode. (Expand_Pragma_Initial_Condition): Capture, set and restore the Ghost mode. (Expand_Pragma_Loop_Variant): Capture, set and restore the Ghost mode. (Restore_Globals): New routine. * exp_util.adb Add with and use clauses for Ghost. (Make_Predicate_Call): Code cleanup. Capture, set and restore the Ghost mode. (Restore_Globals): New routine. * freeze.adb (Freeze_Entity): Code cleanup. Update the call to Set_Ghost_Mode. * ghost.adb Add with and use clause for Sem_Prag. (Check_Ghost_Completion): Code cleanup. (Check_Ghost_Overriding): New routine. (Check_Ghost_Policy): Code cleanup. (Ghost_Entity): New routine. (Is_Ghost_Declaration): Removed. (Is_Ghost_Statement_Or_Pragma): Removed. (Is_OK_Context): Reimplemented. (Is_OK_Declaration): New routine. (Is_OK_Pragma): New routine. (Is_OK_Statement): New routine. (Mark_Full_View_As_Ghost): New routine. (Mark_Pragma_As_Ghost): New routine. (Mark_Renaming_As_Ghost): New routine. (Propagate_Ignored_Ghost_Code): Update the comment on usage. (Set_From_Entity): New routine. (Set_From_Policy): New routine. (Set_Ghost_Mode): This routine now handles pragmas and freeze nodes. (Set_Ghost_Mode_For_Freeze): Removed. (Set_Ghost_Mode_From_Entity): New routine. (Set_Ghost_Mode_From_Policy): Removed. * ghost.ads (Check_Ghost_Overriding): New routine. (Mark_Full_View_As_Ghost): New routine. (Mark_Pragma_As_Ghost): New routine. (Mark_Renaming_As_Ghost): New routine. (Set_Ghost_Mode): Update the parameter profile. Update the comment on usage. (Set_Ghost_Mode_For_Freeze): Removed. (Set_Ghost_Mode_From_Entity): New routine. * sem_ch3.adb (Analyze_Full_Type_Declaration): Capture and restore the Ghost mode. Mark a type as Ghost regardless of whether it comes from source. (Analyze_Incomplete_Type_Decl): Capture, set and restore the Ghost mode. (Analyze_Number_Declaration): Capture and restore the Ghost mode. (Analyze_Object_Declaration): Capture and restore the Ghost mode. (Analyze_Private_Extension_Declaration): Capture and restore the Ghost mode. (Analyze_Subtype_Declaration): Capture and restore the Ghost mode. (Process_Full_View): The full view inherits all Ghost-related attributes from the private view. (Restore_Globals): New routine. * sem_ch5.adb (Analyze_Assignment): Capture and restore the Ghost mode. (Restore_Globals): New routine. * sem_ch6.adb (Analyze_Abstract_Subprogram_Declaration): Code cleanup. Capture and restore the Ghost mode. Mark a subprogram as Ghost regarless of whether it comes from source. (Analyze_Procedure_Call): Capture and restore the Ghost mode. (Analyze_Subprogram_Body_Helper): Capture and restore the Ghost mode. (Analyze_Subprogram_Declaration): Capture and restore the Ghost mode. (New_Overloaded_Entity): Ensure that a parent subprogram and an overriding subprogram have compatible Ghost policies. * sem_ch7.adb (Analyze_Package_Body_Helper): Capture and restore the Ghost mode. (Analyze_Package_Declaration): Capture and restore the Ghost mode. Mark a package as Ghost when it is declared in a Ghost region. (Analyze_Private_Type_Declaration): Capture and restore the Ghost mode. (Restore_Globals): New routine. * sem_ch8.adb (Analyze_Exception_Renaming): Code reformatting. Capture and restore the Ghost mode. A renaming becomes Ghost when its name references a Ghost entity. (Analyze_Generic_Renaming): Capture and restore the Ghost mode. A renaming becomes Ghost when its name references a Ghost entity. (Analyze_Object_Renaming): Capture and restore the Ghost mode. A renaming becomes Ghost when its name references a Ghost entity. (Analyze_Package_Renaming): Capture and restore the Ghost mode. A renaming becomes Ghost when its name references a Ghost entity. (Analyze_Subprogram_Renaming): Capture and restore the Ghost mode. A renaming becomes Ghost when its name references a Ghost entity. * sem_ch11.adb (Analyze_Exception_Declaration): Capture, set and restore the Ghost mode. * sem_ch12.adb (Analyze_Generic_Package_Declaration): Capture and restore the Ghost mode. (Analyze_Generic_Subprogram_Declaration): Capture and restore the Ghost mode. * sem_ch13.adb Add with and use clauses for Ghost. (Add_Invariant): New routine. (Add_Invariants): Factor out code. (Add_Predicate): New routine. (Add_Predicates): Factor out code. (Build_Invariant_Procedure_Declaration): Code cleanup. Capture, set and restore the Ghost mode. (Build_Invariant_Procedure): Code cleanup. (Build_Predicate_Functions): Capture, set and restore the Ghost mode. Mark the generated functions as Ghost. * sem_prag.adb (Analyze_Contract_Cases_In_Decl_Part): Capture, set and restore the Ghost mode. (Analyze_External_Property_In_Decl_Part): Capture, set and restore the Ghost mode. (Analyze_Initial_Condition_In_Decl_Part): Capture, set and restore the Ghost mode. (Analyze_Pragma): Code cleanup. Capture, set and restore the Ghost mode. Flag pragmas Linker_Section, No_Return, Unmodified, Unreferenced and Unreferenced_Objects as illegal when it applies to both Ghost and living arguments. Pragma Ghost cannot apply to synchronized objects. (Check_Kind): Moved to the spec of Sem_Prag. (Process_Inline): Flag the pragma as illegal when it applies to both Ghost and living arguments. (Restore_Globals): New routine. * sem_prag.ads Add pragma Default_Initial_Condition to table Assertion_Expression_Pragma. Add new table Is_Aspect_Specifying_Pragma. (Check_Kind): Moved from body of Sem_Prag. * sem_util.adb Add with and use clauses for Ghost. (Build_Default_Init_Cond_Procedure_Body): Capture, set and restore the Ghost mode. (Build_Default_Init_Cond_Procedure_Declaration): Capture, set and restore the Ghost mode. Mark the default initial condition procedure as Ghost when it is declared in a Ghost region. (Is_Renaming_Declaration): New routine. (Policy_In_List): Account for the single argument version of Check_Pragma. * sem_util.ads (Is_Renaming_Declaration): New routine. * sinfo.adb (Is_Ghost_Pragma): New routine. (Set_Is_Ghost_Pragma): New routine. * sinfo.ads New attribute Is_Ghost_Pragma. (Is_Ghost_Pragma): New routine along with pragma Inline. (Set_Is_Ghost_Pragma): New routine along with pragma Inline. From-SVN: r223684
Diffstat (limited to 'gcc/ada/sem_ch13.adb')
-rw-r--r--gcc/ada/sem_ch13.adb706
1 files changed, 374 insertions, 332 deletions
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 7abf871..8db5b50 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -34,6 +34,7 @@ with Exp_Disp; use Exp_Disp;
with Exp_Tss; use Exp_Tss;
with Exp_Util; use Exp_Util;
with Freeze; use Freeze;
+with Ghost; use Ghost;
with Lib; use Lib;
with Lib.Xref; use Lib.Xref;
with Namet; use Namet;
@@ -7762,21 +7763,25 @@ package body Sem_Ch13 is
function Build_Invariant_Procedure_Declaration
(Typ : Entity_Id) return Node_Id
is
- Loc : constant Source_Ptr := Sloc (Typ);
- Object_Entity : constant Entity_Id :=
- Make_Defining_Identifier (Loc, New_Internal_Name ('I'));
- Spec : Node_Id;
- SId : Entity_Id;
+ GM : constant Ghost_Mode_Type := Ghost_Mode;
+ Loc : constant Source_Ptr := Sloc (Typ);
+ Decl : Node_Id;
+ Obj_Id : Entity_Id;
+ SId : Entity_Id;
begin
- Set_Etype (Object_Entity, Typ);
-
- -- Check for duplicate definiations.
+ -- Check for duplicate definiations
if Has_Invariants (Typ) and then Present (Invariant_Procedure (Typ)) then
return Empty;
end if;
+ -- The related type may be subject to pragma Ghost with policy Ignore.
+ -- Set the mode now to ensure that the predicate functions are properly
+ -- flagged as ignored Ghost.
+
+ Set_Ghost_Mode_From_Entity (Typ);
+
SId :=
Make_Defining_Identifier (Loc,
Chars => New_External_Name (Chars (Typ), "Invariant"));
@@ -7786,15 +7791,31 @@ package body Sem_Ch13 is
Set_Is_Invariant_Procedure (SId);
Set_Invariant_Procedure (Typ, SId);
- Spec :=
- Make_Procedure_Specification (Loc,
- Defining_Unit_Name => SId,
- Parameter_Specifications => New_List (
- Make_Parameter_Specification (Loc,
- Defining_Identifier => Object_Entity,
- Parameter_Type => New_Occurrence_Of (Typ, Loc))));
+ -- Mark the invariant procedure explicitly as Ghost because it does not
+ -- come from source.
+
+ if Ghost_Mode > None then
+ Set_Is_Ghost_Entity (SId);
+ end if;
+
+ Obj_Id := Make_Defining_Identifier (Loc, New_Internal_Name ('I'));
+ Set_Etype (Obj_Id, Typ);
+
+ Decl :=
+ Make_Subprogram_Declaration (Loc,
+ Make_Procedure_Specification (Loc,
+ Defining_Unit_Name => SId,
+ Parameter_Specifications => New_List (
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => Obj_Id,
+ Parameter_Type => New_Occurrence_Of (Typ, Loc)))));
+
+ -- Restore the original Ghost mode once analysis and expansion have
+ -- taken place.
+
+ Ghost_Mode := GM;
- return Make_Subprogram_Declaration (Loc, Specification => Spec);
+ return Decl;
end Build_Invariant_Procedure_Declaration;
-------------------------------
@@ -7813,6 +7834,9 @@ package body Sem_Ch13 is
-- end typInvariant;
procedure Build_Invariant_Procedure (Typ : Entity_Id; N : Node_Id) is
+ Priv_Decls : constant List_Id := Private_Declarations (N);
+ Vis_Decls : constant List_Id := Visible_Declarations (N);
+
Loc : constant Source_Ptr := Sloc (Typ);
Stmts : List_Id;
Spec : Node_Id;
@@ -7820,13 +7844,11 @@ package body Sem_Ch13 is
PDecl : Node_Id;
PBody : Node_Id;
- Nam : Name_Id;
- -- Name for Check pragma, usually Invariant, but might be Type_Invariant
- -- if we come from a Type_Invariant aspect, we make sure to build the
- -- Check pragma with the right name, so that Check_Policy works right.
+ Object_Entity : Node_Id;
+ -- The entity of the formal for the procedure
- Visible_Decls : constant List_Id := Visible_Declarations (N);
- Private_Decls : constant List_Id := Private_Declarations (N);
+ Object_Name : Name_Id;
+ -- Name for argument of invariant procedure
procedure Add_Invariants (T : Entity_Id; Inherit : Boolean);
-- Appends statements to Stmts for any invariants in the rep item chain
@@ -7836,246 +7858,229 @@ package body Sem_Ch13 is
-- "inherited" to the exception message and generating an informational
-- message about the inheritance of an invariant.
- Object_Name : Name_Id;
- -- Name for argument of invariant procedure
-
- Object_Entity : Node_Id;
- -- The entity of the formal for the procedure
-
--------------------
-- Add_Invariants --
--------------------
procedure Add_Invariants (T : Entity_Id; Inherit : Boolean) is
- Ritem : Node_Id;
- Arg1 : Node_Id;
- Arg2 : Node_Id;
- Arg3 : Node_Id;
- Exp : Node_Id;
- Loc : Source_Ptr;
- Assoc : List_Id;
- Str : String_Id;
-
- procedure Replace_Type_Reference (N : Node_Id);
- -- Replace a single occurrence N of the subtype name with a reference
- -- to the formal of the predicate function. N can be an identifier
- -- referencing the subtype, or a selected component, representing an
- -- appropriately qualified occurrence of the subtype name.
-
- procedure Replace_Type_References is
- new Replace_Type_References_Generic (Replace_Type_Reference);
- -- Traverse an expression replacing all occurrences of the subtype
- -- name with appropriate references to the object that is the formal
- -- parameter of the predicate function. Note that we must ensure
- -- that the type and entity information is properly set in the
- -- replacement node, since we will do a Preanalyze call of this
- -- expression without proper visibility of the procedure argument.
+ procedure Add_Invariant (Prag : Node_Id);
+ -- Create a runtime check to verify the exression of invariant pragma
+ -- Prag. All generated code is added to list Stmts.
- ----------------------------
- -- Replace_Type_Reference --
- ----------------------------
+ -------------------
+ -- Add_Invariant --
+ -------------------
- -- Note: See comments in Add_Predicates.Replace_Type_Reference
- -- regarding handling of Sloc and Comes_From_Source.
+ procedure Add_Invariant (Prag : Node_Id) is
+ procedure Replace_Type_Reference (N : Node_Id);
+ -- Replace a single occurrence N of the subtype name with a
+ -- reference to the formal of the predicate function. N can be an
+ -- identifier referencing the subtype, or a selected component,
+ -- representing an appropriately qualified occurrence of the
+ -- subtype name.
+
+ procedure Replace_Type_References is
+ new Replace_Type_References_Generic (Replace_Type_Reference);
+ -- Traverse an expression replacing all occurrences of the subtype
+ -- name with appropriate references to the formal of the predicate
+ -- function. Note that we must ensure that the type and entity
+ -- information is properly set in the replacement node, since we
+ -- will do a Preanalyze call of this expression without proper
+ -- visibility of the procedure argument.
+
+ ----------------------------
+ -- Replace_Type_Reference --
+ ----------------------------
+
+ -- Note: See comments in Add_Predicates.Replace_Type_Reference
+ -- regarding handling of Sloc and Comes_From_Source.
+
+ procedure Replace_Type_Reference (N : Node_Id) is
+ Nloc : constant Source_Ptr := Sloc (N);
- procedure Replace_Type_Reference (N : Node_Id) is
- begin
+ begin
+ -- Add semantic information to node to be rewritten, for ASIS
+ -- navigation needs.
- -- Add semantic information to node to be rewritten, for ASIS
- -- navigation needs.
+ if Nkind (N) = N_Identifier then
+ Set_Entity (N, T);
+ Set_Etype (N, T);
- if Nkind (N) = N_Identifier then
- Set_Entity (N, T);
- Set_Etype (N, T);
+ elsif Nkind (N) = N_Selected_Component then
+ Analyze (Prefix (N));
+ Set_Entity (Selector_Name (N), T);
+ Set_Etype (Selector_Name (N), T);
+ end if;
- elsif Nkind (N) = N_Selected_Component then
- Analyze (Prefix (N));
- Set_Entity (Selector_Name (N), T);
- Set_Etype (Selector_Name (N), T);
- end if;
+ -- Invariant'Class, replace with T'Class (obj)
- -- Invariant'Class, replace with T'Class (obj)
- -- In ASIS mode, an inherited item is analyzed already, and the
- -- replacement has been done, so do not repeat transformation
- -- to prevent ill-formed tree.
+ if Class_Present (Prag) then
- if Class_Present (Ritem) then
- if ASIS_Mode
- and then Nkind (Parent (N)) = N_Attribute_Reference
- and then Attribute_Name (Parent (N)) = Name_Class
- then
- null;
+ -- In ASIS mode, an inherited item is already analyzed,
+ -- and the replacement has been done, so do not repeat
+ -- the transformation to prevent a malformed tree.
- else
- Rewrite (N,
- Make_Type_Conversion (Sloc (N),
- Subtype_Mark =>
- Make_Attribute_Reference (Sloc (N),
- Prefix => New_Occurrence_Of (T, Sloc (N)),
- Attribute_Name => Name_Class),
- Expression =>
- Make_Identifier (Sloc (N), Object_Name)));
+ if ASIS_Mode
+ and then Nkind (Parent (N)) = N_Attribute_Reference
+ and then Attribute_Name (Parent (N)) = Name_Class
+ then
+ null;
- Set_Entity (Expression (N), Object_Entity);
- Set_Etype (Expression (N), Typ);
- end if;
+ else
+ Rewrite (N,
+ Make_Type_Conversion (Nloc,
+ Subtype_Mark =>
+ Make_Attribute_Reference (Nloc,
+ Prefix => New_Occurrence_Of (T, Nloc),
+ Attribute_Name => Name_Class),
+ Expression => Make_Identifier (Nloc, Object_Name)));
+
+ Set_Entity (Expression (N), Object_Entity);
+ Set_Etype (Expression (N), Typ);
+ end if;
- -- Invariant, replace with obj
+ -- Invariant, replace with obj
- else
- Rewrite (N, Make_Identifier (Sloc (N), Object_Name));
- Set_Entity (N, Object_Entity);
- Set_Etype (N, Typ);
- end if;
+ else
+ Rewrite (N, Make_Identifier (Nloc, Object_Name));
+ Set_Entity (N, Object_Entity);
+ Set_Etype (N, Typ);
+ end if;
- Set_Comes_From_Source (N, True);
- end Replace_Type_Reference;
+ Set_Comes_From_Source (N, True);
+ end Replace_Type_Reference;
- -- Start of processing for Add_Invariants
+ -- Local variables
- begin
- Ritem := First_Rep_Item (T);
- while Present (Ritem) loop
- if Nkind (Ritem) = N_Pragma
- and then Pragma_Name (Ritem) = Name_Invariant
- then
- Arg1 := First (Pragma_Argument_Associations (Ritem));
- Arg2 := Next (Arg1);
- Arg3 := Next (Arg2);
+ Asp : constant Node_Id := Corresponding_Aspect (Prag);
+ Nam : constant Name_Id := Original_Aspect_Pragma_Name (Prag);
+ Ploc : constant Source_Ptr := Sloc (Prag);
+ Arg1 : Node_Id;
+ Arg2 : Node_Id;
+ Arg3 : Node_Id;
+ Assoc : List_Id;
+ Expr : Node_Id;
+ Str : String_Id;
- Arg1 := Get_Pragma_Arg (Arg1);
- Arg2 := Get_Pragma_Arg (Arg2);
+ -- Start of processing for Add_Invariant
- -- For Inherit case, ignore Invariant, process only Class case
+ begin
+ -- Extract the arguments of the invariant pragma
- if Inherit then
- if not Class_Present (Ritem) then
- goto Continue;
- end if;
+ Arg1 := First (Pragma_Argument_Associations (Prag));
+ Arg2 := Next (Arg1);
+ Arg3 := Next (Arg2);
- -- For Inherit false, process only item for right type
+ Arg1 := Get_Pragma_Arg (Arg1);
+ Arg2 := Get_Pragma_Arg (Arg2);
- else
- if Entity (Arg1) /= Typ then
- goto Continue;
- end if;
- end if;
+ -- The caller requests processing of all Invariant'Class pragmas,
+ -- but the current pragma does not fall in this category. Return
+ -- as there is nothing left to do.
- if No (Stmts) then
- Stmts := Empty_List;
+ if Inherit then
+ if not Class_Present (Prag) then
+ return;
end if;
- Exp := New_Copy_Tree (Arg2);
+ -- Otherwise the pragma must apply to the current type
- -- Preserve sloc of original pragma Invariant
+ elsif Entity (Arg1) /= T then
+ return;
+ end if;
- Loc := Sloc (Ritem);
+ Expr := New_Copy_Tree (Arg2);
- -- We need to replace any occurrences of the name of the type
- -- with references to the object, converted to type'Class in
- -- the case of Invariant'Class aspects.
+ -- Replace all occurrences of the type's name with references to
+ -- the formal parameter of the invariant procedure.
- Replace_Type_References (Exp, T);
+ Replace_Type_References (Expr, T);
- -- If this invariant comes from an aspect, find the aspect
- -- specification, and replace the saved expression because
- -- we need the subtype references replaced for the calls to
- -- Preanalyze_Spec_Expressin in Check_Aspect_At_Freeze_Point
- -- and Check_Aspect_At_End_Of_Declarations.
+ -- If the invariant pragma comes from an aspect, replace the saved
+ -- expression because we need the subtype references replaced for
+ -- the calls to Preanalyze_Spec_Expression in Check_Aspect_At_xxx
+ -- routines.
- if From_Aspect_Specification (Ritem) then
- declare
- Aitem : Node_Id;
+ if Present (Asp) then
+ Set_Entity (Identifier (Asp), New_Copy_Tree (Expr));
+ end if;
- begin
- -- Loop to find corresponding aspect, note that this
- -- must be present given the pragma is marked delayed.
+ -- Preanalyze the invariant expression to capture the visibility
+ -- of the proper package part. In general the expression is not
+ -- fully analyzed until the body of the invariant procedure is
+ -- analyzed at the end of the private part, but that yields the
+ -- wrong visibility.
- -- Note: in practice Next_Rep_Item (Ritem) is Empty so
- -- this loop does nothing. Furthermore, why isn't this
- -- simply Corresponding_Aspect ???
+ -- Historic note: we used to set N as the parent, but a package
+ -- specification as the parent of an expression is bizarre.
- Aitem := Next_Rep_Item (Ritem);
- while Present (Aitem) loop
- if Nkind (Aitem) = N_Aspect_Specification
- and then Aspect_Rep_Item (Aitem) = Ritem
- then
- Set_Entity
- (Identifier (Aitem), New_Copy_Tree (Exp));
- exit;
- end if;
+ Set_Parent (Expr, Parent (Arg2));
+ Preanalyze_Assert_Expression (Expr, Any_Boolean);
- Aitem := Next_Rep_Item (Aitem);
- end loop;
- end;
- end if;
-
- -- Now we need to preanalyze the expression to properly capture
- -- the visibility in the visible part. The expression will not
- -- be analyzed for real until the body is analyzed, but that is
- -- at the end of the private part and has the wrong visibility.
+ -- A class-wide invariant may be inherited in a separate unit,
+ -- where the corresponding expression cannot be resolved by
+ -- visibility, because it refers to a local function. Propagate
+ -- semantic information to the original representation item, to
+ -- be used when an invariant procedure for a derived type is
+ -- constructed.
- Set_Parent (Exp, N);
- Preanalyze_Assert_Expression (Exp, Any_Boolean);
+ -- ??? Unclear how to handle class-wide invariants that are not
+ -- function calls.
- -- A class-wide invariant may be inherited in a separate unit,
- -- where the corresponding expression cannot be resolved by
- -- visibility, because it refers to a local function. Propagate
- -- semantic information to the original representation item, to
- -- be used when an invariant procedure for a derived type is
- -- constructed.
+ if not Inherit
+ and then Class_Present (Prag)
+ and then Nkind (Expr) = N_Function_Call
+ and then Nkind (Arg2) = N_Indexed_Component
+ then
+ Rewrite (Arg2,
+ Make_Function_Call (Ploc,
+ Name =>
+ New_Occurrence_Of (Entity (Name (Expr)), Ploc),
+ Parameter_Associations =>
+ New_Copy_List (Expressions (Arg2))));
+ end if;
- -- Unclear how to handle class-wide invariants that are not
- -- function calls ???
+ -- In ASIS mode, even if assertions are not enabled, we must
+ -- analyze the original expression in the aspect specification
+ -- because it is part of the original tree.
- if not Inherit
- and then Class_Present (Ritem)
- and then Nkind (Exp) = N_Function_Call
- and then Nkind (Arg2) = N_Indexed_Component
- then
- Rewrite (Arg2,
- Make_Function_Call (Loc,
- Name =>
- New_Occurrence_Of (Entity (Name (Exp)), Loc),
- Parameter_Associations =>
- New_Copy_List (Expressions (Arg2))));
- end if;
-
- -- In ASIS mode, even if assertions are not enabled, we must
- -- analyze the original expression in the aspect specification
- -- because it is part of the original tree.
+ if ASIS_Mode and then Present (Asp) then
+ declare
+ Orig_Expr : constant Node_Id := Expression (Asp);
+ begin
+ Replace_Type_References (Orig_Expr, T);
+ Preanalyze_Assert_Expression (Orig_Expr, Any_Boolean);
+ end;
+ end if;
- if ASIS_Mode and then From_Aspect_Specification (Ritem) then
- declare
- Inv : constant Node_Id :=
- Expression (Corresponding_Aspect (Ritem));
- begin
- Replace_Type_References (Inv, T);
- Preanalyze_Assert_Expression (Inv, Standard_Boolean);
- end;
- end if;
+ -- An ignored invariant must not generate a runtime check. Add a
+ -- null statement to ensure that the invariant procedure does get
+ -- a completing body.
- -- Get name to be used for Check pragma. Using the original
- -- name ensures that 'Class case is properly handled.
+ if No (Stmts) then
+ Stmts := Empty_List;
+ end if;
- Nam := Original_Aspect_Pragma_Name (Ritem);
+ if Is_Ignored (Prag) then
+ Append_To (Stmts, Make_Null_Statement (Ploc));
- -- Build first two arguments for Check pragma
+ -- Otherwise the invariant is checked. Build a Check pragma to
+ -- verify the expression at runtime.
- Assoc :=
- New_List (
- Make_Pragma_Argument_Association (Loc,
- Expression => Make_Identifier (Loc, Chars => Nam)),
- Make_Pragma_Argument_Association (Loc,
- Expression => Exp));
+ else
+ Assoc := New_List (
+ Make_Pragma_Argument_Association (Ploc,
+ Expression => Make_Identifier (Ploc, Nam)),
+ Make_Pragma_Argument_Association (Ploc,
+ Expression => Expr));
- -- Add message if present in Invariant pragma
+ -- Handle the String argument (if any)
if Present (Arg3) then
Str := Strval (Get_Pragma_Arg (Arg3));
- -- If inherited case, and message starts "failed invariant",
- -- change it to be "failed inherited invariant".
+ -- When inheriting an invariant, modify the message from
+ -- "failed invariant" to "failed inherited invariant".
if Inherit then
String_To_Name_Buffer (Str);
@@ -8087,30 +8092,45 @@ package body Sem_Ch13 is
end if;
Append_To (Assoc,
- Make_Pragma_Argument_Association (Loc,
- Expression => Make_String_Literal (Loc, Str)));
+ Make_Pragma_Argument_Association (Ploc,
+ Expression => Make_String_Literal (Ploc, Str)));
end if;
- -- Add Check pragma to list of statements
+ -- Generate:
+ -- pragma Check (Nam, Expr, Str);
Append_To (Stmts,
- Make_Pragma (Loc,
+ Make_Pragma (Ploc,
Pragma_Identifier =>
- Make_Identifier (Loc, Name_Check),
+ Make_Identifier (Ploc, Name_Check),
Pragma_Argument_Associations => Assoc));
+ end if;
- -- If Inherited case and option enabled, output info msg. Note
- -- that we know this is a case of Invariant'Class.
+ -- Output an info message when inheriting an invariant and the
+ -- listing option is enabled.
- if Inherit and Opt.List_Inherited_Aspects then
- Error_Msg_Sloc := Sloc (Ritem);
- Error_Msg_N
- ("info: & inherits `Invariant''Class` aspect from #?L?",
- Typ);
- end if;
+ if Inherit and Opt.List_Inherited_Aspects then
+ Error_Msg_Sloc := Sloc (Prag);
+ Error_Msg_N
+ ("info: & inherits `Invariant''Class` aspect from #?L?", Typ);
+ end if;
+ end Add_Invariant;
+
+ -- Local variables
+
+ Ritem : Node_Id;
+
+ -- Start of processing for Add_Invariants
+
+ begin
+ Ritem := First_Rep_Item (T);
+ while Present (Ritem) loop
+ if Nkind (Ritem) = N_Pragma
+ and then Pragma_Name (Ritem) = Name_Invariant
+ then
+ Add_Invariant (Ritem);
end if;
- <<Continue>>
Next_Rep_Item (Ritem);
end loop;
end Add_Invariants;
@@ -8228,13 +8248,13 @@ package body Sem_Ch13 is
-- If declaration is already analyzed, it was processed by the
-- generated pragma.
- if Present (Private_Decls) then
+ if Present (Priv_Decls) then
-- The spec goes at the end of visible declarations, but they have
-- already been analyzed, so we need to explicitly do the analyze.
if not Analyzed (PDecl) then
- Append_To (Visible_Decls, PDecl);
+ Append_To (Vis_Decls, PDecl);
Analyze (PDecl);
end if;
@@ -8243,7 +8263,7 @@ package body Sem_Ch13 is
-- analyze call. We skip this if there are no private declarations
-- (this is an error that will be caught elsewhere);
- Append_To (Private_Decls, PBody);
+ Append_To (Priv_Decls, PBody);
-- If the invariant appears on the full view of a type, the
-- analysis of the private part is complete, and we must
@@ -8261,8 +8281,8 @@ package body Sem_Ch13 is
-- that the type is about to be frozen.
elsif not Is_Private_Type (Typ) then
- Append_To (Visible_Decls, PDecl);
- Append_To (Visible_Decls, PBody);
+ Append_To (Vis_Decls, PDecl);
+ Append_To (Vis_Decls, PBody);
Analyze (PDecl);
Analyze (PBody);
end if;
@@ -8332,13 +8352,6 @@ package body Sem_Ch13 is
-- Inheritance of predicates for the parent type is done by calling the
-- Predicate_Function of the parent type, using Add_Call above.
- function Test_RE (N : Node_Id) return Traverse_Result;
- -- Used in Test_REs, tests one node for being a raise expression, and if
- -- so sets Raise_Expression_Present True.
-
- procedure Test_REs is new Traverse_Proc (Test_RE);
- -- Tests to see if Expr contains any raise expressions
-
function Process_RE (N : Node_Id) return Traverse_Result;
-- Used in Process REs, tests if node N is a raise expression, and if
-- so, marks it to be converted to return False.
@@ -8346,6 +8359,13 @@ package body Sem_Ch13 is
procedure Process_REs is new Traverse_Proc (Process_RE);
-- Marks any raise expressions in Expr_M to return False
+ function Test_RE (N : Node_Id) return Traverse_Result;
+ -- Used in Test_REs, tests one node for being a raise expression, and if
+ -- so sets Raise_Expression_Present True.
+
+ procedure Test_REs is new Traverse_Proc (Test_RE);
+ -- Tests to see if Expr contains any raise expressions
+
--------------
-- Add_Call --
--------------
@@ -8399,128 +8419,121 @@ package body Sem_Ch13 is
--------------------
procedure Add_Predicates is
- Ritem : Node_Id;
- Arg1 : Node_Id;
- Arg2 : Node_Id;
-
- procedure Replace_Type_Reference (N : Node_Id);
- -- Replace a single occurrence N of the subtype name with a reference
- -- to the formal of the predicate function. N can be an identifier
- -- referencing the subtype, or a selected component, representing an
- -- appropriately qualified occurrence of the subtype name.
+ procedure Add_Predicate (Prag : Node_Id);
+ -- Concatenate the expression of predicate pragma Prag to Expr by
+ -- using a short circuit "and then" operator.
- procedure Replace_Type_References is
- new Replace_Type_References_Generic (Replace_Type_Reference);
- -- Traverse an expression changing every occurrence of an identifier
- -- whose name matches the name of the subtype with a reference to
- -- the formal parameter of the predicate function.
+ -------------------
+ -- Add_Predicate --
+ -------------------
- ----------------------------
- -- Replace_Type_Reference --
- ----------------------------
+ procedure Add_Predicate (Prag : Node_Id) is
+ procedure Replace_Type_Reference (N : Node_Id);
+ -- Replace a single occurrence N of the subtype name with a
+ -- reference to the formal of the predicate function. N can be an
+ -- identifier referencing the subtype, or a selected component,
+ -- representing an appropriately qualified occurrence of the
+ -- subtype name.
+
+ procedure Replace_Type_References is
+ new Replace_Type_References_Generic (Replace_Type_Reference);
+ -- Traverse an expression changing every occurrence of an
+ -- identifier whose name matches the name of the subtype with a
+ -- reference to the formal parameter of the predicate function.
+
+ ----------------------------
+ -- Replace_Type_Reference --
+ ----------------------------
+
+ procedure Replace_Type_Reference (N : Node_Id) is
+ begin
+ Rewrite (N, Make_Identifier (Sloc (N), Object_Name));
+ -- Use the Sloc of the usage name, not the defining name
- procedure Replace_Type_Reference (N : Node_Id) is
- begin
- Rewrite (N, Make_Identifier (Sloc (N), Object_Name));
- -- Use the Sloc of the usage name, not the defining name
+ Set_Etype (N, Typ);
+ Set_Entity (N, Object_Entity);
- Set_Etype (N, Typ);
- Set_Entity (N, Object_Entity);
+ -- We want to treat the node as if it comes from source, so
+ -- that ASIS will not ignore it.
- -- We want to treat the node as if it comes from source, so that
- -- ASIS will not ignore it
+ Set_Comes_From_Source (N, True);
+ end Replace_Type_Reference;
- Set_Comes_From_Source (N, True);
- end Replace_Type_Reference;
+ -- Local variables
- -- Start of processing for Add_Predicates
+ Asp : constant Node_Id := Corresponding_Aspect (Prag);
+ Arg1 : Node_Id;
+ Arg2 : Node_Id;
- begin
- Ritem := First_Rep_Item (Typ);
+ -- Start of processing for Add_Predicate
- while Present (Ritem) loop
- if Nkind (Ritem) = N_Pragma
- and then Pragma_Name (Ritem) = Name_Predicate
- then
- -- Acquire arguments. The expression itself is copied for use
- -- in the predicate function, to preserve the original version
- -- for ASIS use.
-
- Arg1 := First (Pragma_Argument_Associations (Ritem));
- Arg2 := Next (Arg1);
+ begin
+ -- Extract the arguments of the pragma. The expression itself
+ -- is copied for use in the predicate function, to preserve the
+ -- original version for ASIS use.
- Arg1 := Get_Pragma_Arg (Arg1);
- Arg2 := New_Copy_Tree (Get_Pragma_Arg (Arg2));
+ Arg1 := First (Pragma_Argument_Associations (Prag));
+ Arg2 := Next (Arg1);
- -- See if this predicate pragma is for the current type or for
- -- its full view. A predicate on a private completion is placed
- -- on the partial view beause this is the visible entity that
- -- is frozen.
+ Arg1 := Get_Pragma_Arg (Arg1);
+ Arg2 := New_Copy_Tree (Get_Pragma_Arg (Arg2));
- if Entity (Arg1) = Typ
- or else Full_View (Entity (Arg1)) = Typ
- then
- -- We have a match, this entry is for our subtype
+ -- When the predicate pragma applies to the current type or its
+ -- full view, replace all occurrences of the subtype name with
+ -- references to the formal parameter of the predicate function.
- -- We need to replace any occurrences of the name of the
- -- type with references to the object.
+ if Entity (Arg1) = Typ
+ or else Full_View (Entity (Arg1)) = Typ
+ then
+ Replace_Type_References (Arg2, Typ);
- Replace_Type_References (Arg2, Typ);
+ -- If the predicate pragma comes from an aspect, replace the
+ -- saved expression because we need the subtype references
+ -- replaced for the calls to Preanalyze_Spec_Expression in
+ -- Check_Aspect_At_xxx routines.
- -- If this predicate comes from an aspect, find the aspect
- -- specification, and replace the saved expression because
- -- we need the subtype references replaced for the calls to
- -- Preanalyze_Spec_Expressin in Check_Aspect_At_Freeze_Point
- -- and Check_Aspect_At_End_Of_Declarations.
+ if Present (Asp) then
- if From_Aspect_Specification (Ritem) then
- declare
- Aitem : Node_Id;
- Orig_Expr : constant Node_Id :=
- Expression (Corresponding_Aspect (Ritem));
+ -- For ASIS use, perform semantic analysis of the original
+ -- predicate expression, which is otherwise not utilized.
- begin
+ if ASIS_Mode then
+ Preanalyze_And_Resolve (Expression (Asp));
+ end if;
- -- For ASIS use, perform semantic analysis of the
- -- original predicate expression, which is otherwise
- -- not utilized.
+ Set_Entity (Identifier (Asp), New_Copy_Tree (Arg2));
+ end if;
- if ASIS_Mode then
- Preanalyze_And_Resolve (Orig_Expr);
- end if;
+ -- Concatenate to the existing predicate expressions by using
+ -- "and then".
- -- Loop to find corresponding aspect, note that this
- -- must be present given the pragma is marked delayed.
+ if Present (Expr) then
+ Expr :=
+ Make_And_Then (Loc,
+ Left_Opnd => Relocate_Node (Expr),
+ Right_Opnd => Relocate_Node (Arg2));
- Aitem := Next_Rep_Item (Ritem);
- loop
- if Nkind (Aitem) = N_Aspect_Specification
- and then Aspect_Rep_Item (Aitem) = Ritem
- then
- Set_Entity
- (Identifier (Aitem), New_Copy_Tree (Arg2));
- exit;
- end if;
+ -- Otherwise this is the first predicate expression
- Aitem := Next_Rep_Item (Aitem);
- end loop;
- end;
- end if;
+ else
+ Expr := Relocate_Node (Arg2);
+ end if;
+ end if;
+ end Add_Predicate;
- -- Now we can add the expression
+ -- Local variables
- if No (Expr) then
- Expr := Relocate_Node (Arg2);
+ Ritem : Node_Id;
- -- There already was a predicate, so add to it
+ -- Start of processing for Add_Predicates
- else
- Expr :=
- Make_And_Then (Loc,
- Left_Opnd => Relocate_Node (Expr),
- Right_Opnd => Relocate_Node (Arg2));
- end if;
- end if;
+ begin
+ Ritem := First_Rep_Item (Typ);
+ while Present (Ritem) loop
+ if Nkind (Ritem) = N_Pragma
+ and then Pragma_Name (Ritem) = Name_Predicate
+ then
+ Add_Predicate (Ritem);
end if;
Next_Rep_Item (Ritem);
@@ -8555,6 +8568,10 @@ package body Sem_Ch13 is
end if;
end Test_RE;
+ -- Local variables
+
+ GM : constant Ghost_Mode_Type := Ghost_Mode;
+
-- Start of processing for Build_Predicate_Functions
begin
@@ -8566,6 +8583,12 @@ package body Sem_Ch13 is
return;
end if;
+ -- The related type may be subject to pragma Ghost with policy Ignore.
+ -- Set the mode now to ensure that the predicate functions are properly
+ -- flagged as ignored Ghost.
+
+ Set_Ghost_Mode_From_Entity (Typ);
+
-- Prepare to construct predicate expression
Expr := Empty;
@@ -8670,6 +8693,13 @@ package body Sem_Ch13 is
Set_Predicate_Function (Full_View (Typ), SId);
end if;
+ -- Mark the predicate function explicitly as Ghost because it does
+ -- not come from source.
+
+ if Ghost_Mode > None then
+ Set_Is_Ghost_Entity (SId);
+ end if;
+
Spec :=
Make_Function_Specification (Loc,
Defining_Unit_Name => SId,
@@ -8750,6 +8780,13 @@ package body Sem_Ch13 is
Set_Predicate_Function_M (Full_View (Typ), SId);
end if;
+ -- Mark the predicate function explicitly as Ghost because it
+ -- does not come from source.
+
+ if Ghost_Mode > None then
+ Set_Is_Ghost_Entity (SId);
+ end if;
+
Spec :=
Make_Function_Specification (Loc,
Defining_Unit_Name => SId,
@@ -8896,6 +8933,11 @@ package body Sem_Ch13 is
end if;
end;
end if;
+
+ -- Restore the original Ghost mode once analysis and expansion have
+ -- taken place.
+
+ Ghost_Mode := GM;
end Build_Predicate_Functions;
-----------------------------------------