Commit f2264ac2 by Robert Dewar Committed by Arnaud Charlet

sem_ch13.adb (Build_Invariant_Procedure): New calling sequence.

2010-10-26  Robert Dewar  <dewar@adacore.com>

	* sem_ch13.adb (Build_Invariant_Procedure): New calling sequence.
	(Build_Invariant_Procedure): Properly handle analysis of invariant
	expression with proper end-of-visible-decls visibility.
	* sem_ch13.ads (Build_Invariant_Procedure): Changed calling sequence.
	* sem_ch3.adb (Process_Full_View): Don't build invariant procedure
	(too late).
	(Analyze_Private_Extension_Declaration): Propagate invariant flags.
	* sem_ch7.adb (Analyze_Package_Specification): Build invariant
	procedures.

From-SVN: r165960
parent 1ce9dff3
2010-10-26 Robert Dewar <dewar@adacore.com>
* sem_ch13.adb (Build_Invariant_Procedure): New calling sequence.
(Build_Invariant_Procedure): Properly handle analysis of invariant
expression with proper end-of-visible-decls visibility.
* sem_ch13.ads (Build_Invariant_Procedure): Changed calling sequence.
* sem_ch3.adb (Process_Full_View): Don't build invariant procedure
(too late).
(Analyze_Private_Extension_Declaration): Propagate invariant flags.
* sem_ch7.adb (Analyze_Package_Specification): Build invariant
procedures.
2010-10-26 Vincent Celier <celier@adacore.com> 2010-10-26 Vincent Celier <celier@adacore.com>
* opt.ads (Old_Checksums, Old_Old_Checksums): New Boolean flags, * opt.ads (Old_Checksums, Old_Old_Checksums): New Boolean flags,
......
...@@ -3549,15 +3549,16 @@ package body Sem_Ch13 is ...@@ -3549,15 +3549,16 @@ package body Sem_Ch13 is
-- ... -- ...
-- end typInvariant; -- end typInvariant;
procedure Build_Invariant_Procedure procedure Build_Invariant_Procedure (Typ : Entity_Id; N : Node_Id) is
(Typ : Entity_Id;
PDecl : out Node_Id;
PBody : out Node_Id)
is
Loc : constant Source_Ptr := Sloc (Typ); Loc : constant Source_Ptr := Sloc (Typ);
Stmts : List_Id; Stmts : List_Id;
Spec : Node_Id; Spec : Node_Id;
SId : Entity_Id; SId : Entity_Id;
PDecl : Node_Id;
PBody : Node_Id;
Visible_Decls : constant List_Id := Visible_Declarations (N);
Private_Decls : constant List_Id := Private_Declarations (N);
procedure Add_Invariants (T : Entity_Id; Inherit : Boolean); procedure Add_Invariants (T : Entity_Id; Inherit : Boolean);
-- Appends statements to Stmts for any invariants in the rep item chain -- Appends statements to Stmts for any invariants in the rep item chain
...@@ -3570,6 +3571,10 @@ package body Sem_Ch13 is ...@@ -3570,6 +3571,10 @@ package body Sem_Ch13 is
Object_Name : constant Name_Id := New_Internal_Name ('I'); Object_Name : constant Name_Id := New_Internal_Name ('I');
-- Name for argument of invariant procedure -- Name for argument of invariant procedure
Object_Entity : constant Node_Id :=
Make_Defining_Identifier (Loc, Object_Name);
-- The procedure declaration entity for the argument
-------------------- --------------------
-- Add_Invariants -- -- Add_Invariants --
-------------------- --------------------
...@@ -3594,7 +3599,10 @@ package body Sem_Ch13 is ...@@ -3594,7 +3599,10 @@ package body Sem_Ch13 is
new Replace_Type_References_Generic (Replace_Type_Reference); new Replace_Type_References_Generic (Replace_Type_Reference);
-- Traverse an expression replacing all occurrences of the subtype -- Traverse an expression replacing all occurrences of the subtype
-- name with appropriate references to the object that is the formal -- name with appropriate references to the object that is the formal
-- parameter of the predicate function. -- 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.
---------------------------- ----------------------------
-- Replace_Type_Reference -- -- Replace_Type_Reference --
...@@ -3616,12 +3624,15 @@ package body Sem_Ch13 is ...@@ -3616,12 +3624,15 @@ package body Sem_Ch13 is
Make_Identifier (Loc, Make_Identifier (Loc,
Chars => Object_Name))); Chars => Object_Name)));
Set_Entity (Expression (N), Object_Entity);
Set_Etype (Expression (N), Typ);
-- Invariant, replace with obj -- Invariant, replace with obj
else else
Rewrite (N, Rewrite (N, Make_Identifier (Loc, Chars => Object_Name));
Make_Identifier (Loc, Set_Entity (N, Object_Entity);
Chars => Object_Name)); Set_Etype (N, Typ);
end if; end if;
end Replace_Type_Reference; end Replace_Type_Reference;
...@@ -3668,13 +3679,20 @@ package body Sem_Ch13 is ...@@ -3668,13 +3679,20 @@ package body Sem_Ch13 is
Replace_Type_References (Exp, Chars (T)); Replace_Type_References (Exp, Chars (T));
-- 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.
Set_Parent (Exp, N);
Preanalyze_Spec_Expression (Exp, Standard_Boolean);
-- Build first two arguments for Check pragma -- Build first two arguments for Check pragma
Assoc := New_List ( Assoc := New_List (
Make_Pragma_Argument_Association (Loc, Make_Pragma_Argument_Association (Loc,
Expression => Expression =>
Make_Identifier (Loc, Make_Identifier (Loc, Chars => Name_Invariant)),
Chars => Name_Invariant)),
Make_Pragma_Argument_Association (Loc, Make_Pragma_Argument_Association (Loc,
Expression => Exp)); Expression => Exp));
...@@ -3705,8 +3723,7 @@ package body Sem_Ch13 is ...@@ -3705,8 +3723,7 @@ package body Sem_Ch13 is
Append_To (Stmts, Append_To (Stmts,
Make_Pragma (Loc, Make_Pragma (Loc,
Pragma_Identifier => Pragma_Identifier =>
Make_Identifier (Loc, Make_Identifier (Loc, Chars => Name_Check),
Chars => Name_Check),
Pragma_Argument_Associations => Assoc)); Pragma_Argument_Associations => Assoc));
-- If Inherited case and option enabled, output info msg. Note -- If Inherited case and option enabled, output info msg. Note
...@@ -3731,6 +3748,7 @@ package body Sem_Ch13 is ...@@ -3731,6 +3748,7 @@ package body Sem_Ch13 is
Stmts := No_List; Stmts := No_List;
PDecl := Empty; PDecl := Empty;
PBody := Empty; PBody := Empty;
Set_Etype (Object_Entity, Typ);
-- Add invariants for the current type -- Add invariants for the current type
...@@ -3766,7 +3784,6 @@ package body Sem_Ch13 is ...@@ -3766,7 +3784,6 @@ package body Sem_Ch13 is
-- Build procedure declaration -- Build procedure declaration
pragma Assert (Has_Invariants (Typ));
SId := SId :=
Make_Defining_Identifier (Loc, Make_Defining_Identifier (Loc,
Chars => New_External_Name (Chars (Typ), "Invariant")); Chars => New_External_Name (Chars (Typ), "Invariant"));
...@@ -3778,15 +3795,10 @@ package body Sem_Ch13 is ...@@ -3778,15 +3795,10 @@ package body Sem_Ch13 is
Defining_Unit_Name => SId, Defining_Unit_Name => SId,
Parameter_Specifications => New_List ( Parameter_Specifications => New_List (
Make_Parameter_Specification (Loc, Make_Parameter_Specification (Loc,
Defining_Identifier => Defining_Identifier => Object_Entity,
Make_Defining_Identifier (Loc, Parameter_Type => New_Occurrence_Of (Typ, Loc))));
Chars => Object_Name),
Parameter_Type =>
New_Occurrence_Of (Typ, Loc))));
PDecl := PDecl := Make_Subprogram_Declaration (Loc, Specification => Spec);
Make_Subprogram_Declaration (Loc,
Specification => Spec);
-- Build procedure body -- Build procedure body
...@@ -3812,6 +3824,27 @@ package body Sem_Ch13 is ...@@ -3812,6 +3824,27 @@ package body Sem_Ch13 is
Handled_Statement_Sequence => Handled_Statement_Sequence =>
Make_Handled_Sequence_Of_Statements (Loc, Make_Handled_Sequence_Of_Statements (Loc,
Statements => Stmts)); Statements => Stmts));
-- Insert procedure declaration and spec at the appropriate points.
-- Skip this if there are no private declarations (that's an error
-- that will be diagnosed elsewhere, and there is no point in having
-- an invariant procedure set if the full declaration is missing).
if Present (Private_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.
Append_To (Visible_Decls, PDecl);
Analyze (PDecl);
-- The body goes at the end of the private declarations, which we
-- have not analyzed yet, so we do not need to perform an explicit
-- 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);
end if;
end if; end if;
end Build_Invariant_Procedure; end Build_Invariant_Procedure;
......
...@@ -52,17 +52,16 @@ package Sem_Ch13 is ...@@ -52,17 +52,16 @@ package Sem_Ch13 is
-- order is specified and there is at least one component clause. Adjusts -- order is specified and there is at least one component clause. Adjusts
-- component positions according to either Ada 95 or Ada 2005 (AI-133). -- component positions according to either Ada 95 or Ada 2005 (AI-133).
procedure Build_Invariant_Procedure procedure Build_Invariant_Procedure (Typ : Entity_Id; N : Node_Id);
(Typ : Entity_Id; -- Typ is a private type with invariants (indicated by Has_Invariants being
PDecl : out Node_Id; -- set for Typ, indicating the presence of pragma Invariant entries on the
PBody : out Node_Id); -- rep chain, note that Invariant aspects have already been converted to
-- If Typ has Invariants (indicated by Has_Invariants being set for Typ, -- pragma Invariant), then this procedure builds the spec and body for the
-- indicating the presence of pragma Invariant entries on the rep chain, -- corresponding Invariant procedure, inserting them at appropriate points
-- note that Invariant aspects are converted to pragma Invariant), then -- in the package specification N. Invariant_Procedure is set for Typ. Note
-- this procedure builds the spec and body for the corresponding Invariant -- that this procedure is called at the end of processing the declarations
-- procedure, returning themn in PDecl and PBody. Invariant_Procedure is -- in the visible part (i.e. the right point for visibility analysis of
-- set for Typ. In some error situations no procedure is built, in which -- the invariant expression).
-- case PDecl/PBody are empty on return.
procedure Check_Record_Representation_Clause (N : Node_Id); procedure Check_Record_Representation_Clause (N : Node_Id);
-- This procedure completes the analysis of a record representation clause -- This procedure completes the analysis of a record representation clause
......
...@@ -3731,6 +3731,15 @@ package body Sem_Ch3 is ...@@ -3731,6 +3731,15 @@ package body Sem_Ch3 is
Build_Derived_Record_Type (N, Parent_Type, T); Build_Derived_Record_Type (N, Parent_Type, T);
-- Propagate inherited invariant information. The new type has
-- invariants, if the parent type has inheritable invariants,
-- and these invariants can in turn be inherited.
if Has_Inheritable_Invariants (Parent_Type) then
Set_Has_Inheritable_Invariants (T);
Set_Has_Invariants (T);
end if;
-- Ada 2005 (AI-443): Synchronized private extension or a rewritten -- Ada 2005 (AI-443): Synchronized private extension or a rewritten
-- synchronized formal derived type. -- synchronized formal derived type.
...@@ -17439,58 +17448,15 @@ package body Sem_Ch3 is ...@@ -17439,58 +17448,15 @@ package body Sem_Ch3 is
Set_Has_Specified_Stream_Output (Full_T); Set_Has_Specified_Stream_Output (Full_T);
end if; end if;
-- Deal with invariants -- Propagate invariants to full type
if Has_Invariants (Full_T) if Has_Invariants (Priv_T) then
or else
Has_Invariants (Priv_T)
then
Set_Has_Invariants (Full_T); Set_Has_Invariants (Full_T);
Set_Has_Invariants (Priv_T); Set_Invariant_Procedure (Full_T, Invariant_Procedure (Priv_T));
end if; end if;
if Has_Inheritable_Invariants (Full_T) if Has_Inheritable_Invariants (Priv_T) then
or else
Has_Inheritable_Invariants (Priv_T)
then
Set_Has_Inheritable_Invariants (Full_T); Set_Has_Inheritable_Invariants (Full_T);
Set_Has_Inheritable_Invariants (Priv_T);
end if;
-- This is where we build the invariant procedure if needed
if Has_Invariants (Priv_T) then
declare
PDecl : Entity_Id;
PBody : Entity_Id;
Packg : constant Node_Id := Declaration_Node (Scope (Priv_T));
begin
Build_Invariant_Procedure (Full_T, PDecl, PBody);
-- Error defense, normally these should be set
if Present (PDecl) and then Present (PBody) then
-- Spec goes at the end of the public part of the package.
-- That's behind us, so we have to manually analyze the
-- inserted spec.
Append_To (Visible_Declarations (Packg), PDecl);
Analyze (PDecl);
-- Body goes at the end of the private part of the package.
-- That's ahead of us so it will get analyzed later on when
-- we come to it.
Append_To (Private_Declarations (Packg), PBody);
-- Copy Invariant procedure to private declaration
Set_Invariant_Procedure (Priv_T, Invariant_Procedure (Full_T));
Set_Has_Invariants (Priv_T);
end if;
end;
end if; end if;
-- Propagate predicates to full type -- Propagate predicates to full type
......
...@@ -1128,16 +1128,26 @@ package body Sem_Ch7 is ...@@ -1128,16 +1128,26 @@ package body Sem_Ch7 is
Analyze_Declarations (Vis_Decls); Analyze_Declarations (Vis_Decls);
end if; end if;
-- Verify that incomplete types have received full declarations -- Verify that incomplete types have received full declarations and
-- also build invariant procedures for any types with invariants.
E := First_Entity (Id); E := First_Entity (Id);
while Present (E) loop while Present (E) loop
-- Check on incomplete types
if Ekind (E) = E_Incomplete_Type if Ekind (E) = E_Incomplete_Type
and then No (Full_View (E)) and then No (Full_View (E))
then then
Error_Msg_N ("no declaration in visible part for incomplete}", E); Error_Msg_N ("no declaration in visible part for incomplete}", E);
end if; end if;
-- Build invariant procedures
if Is_Type (E) and then Has_Invariants (E) then
Build_Invariant_Procedure (E, N);
end if;
Next_Entity (E); Next_Entity (E);
end loop; end loop;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment