aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArnaud Charlet <charlet@gcc.gnu.org>2014-02-06 10:53:00 +0100
committerArnaud Charlet <charlet@gcc.gnu.org>2014-02-06 10:53:00 +0100
commit97779c340acc02f574fa943d059f68a74d36c4ca (patch)
tree0ee2912d63a73536733f817f576811cb7ab23f41 /gcc
parentc801e24619405cf2ca3eb3faea28c45f10ce00d7 (diff)
downloadgcc-97779c340acc02f574fa943d059f68a74d36c4ca.zip
gcc-97779c340acc02f574fa943d059f68a74d36c4ca.tar.gz
gcc-97779c340acc02f574fa943d059f68a74d36c4ca.tar.bz2
[multiple changes]
2014-02-06 Robert Dewar <dewar@adacore.com> * sprint.adb: Minor reformatting. 2014-02-06 Hristian Kirtchev <kirtchev@adacore.com> * exp_ch4.adb (Process_Transient_Object): Add local variable Temp_Ins. When the transient object is initialized by an aggregate, the hook must capture the object after the last component assignment takes place. * exp_ch7.adb (Detect_Subprogram_Call): Expose the subprogram to routine Is_Subprogram_Call. (Is_Subprogram_Call): Inspect an aggregate that has been heavily expanded for subprogram calls. (Process_Transient_Objects): Add local variables Expr, Ptr_Id and Temp_Ins. Remove the nested declare block and adjust the indentation. When the transient object is initialized by an aggregate, the hook must capture the object after the last component assignment takes place. 2014-02-06 Hristian Kirtchev <kirtchev@adacore.com> * sem_prag.adb (Analyze_Global_Item): Detect illegal uses of external states with enabled properties that do not match the global mode. (Property_Error): New routine. * sem_res.adb (Property_Error): New routine. (Resolve_Actuals): Detect illegal uses of external variables with enabled properties in procedure calls that do not match the mode of the corresponding formal parameter. 2014-02-06 Hristian Kirtchev <kirtchev@adacore.com> * sem_util.adb (Has_Enabled_Property): Rename formal parameter Prop_Nam to Property. Update the comment on usage and all occurrences in the body. Add local variable Prop_Nam. When inspecting a property with an expression, the property name appears as the first choice of the component association. From-SVN: r207534
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ada/ChangeLog39
-rw-r--r--gcc/ada/exp_ch4.adb18
-rw-r--r--gcc/ada/exp_ch7.adb161
-rw-r--r--gcc/ada/sem_prag.adb50
-rw-r--r--gcc/ada/sem_res.adb63
-rw-r--r--gcc/ada/sem_util.adb25
-rw-r--r--gcc/ada/sprint.adb2
7 files changed, 281 insertions, 77 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 8417198..0ee4e1e 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,42 @@
+2014-02-06 Robert Dewar <dewar@adacore.com>
+
+ * sprint.adb: Minor reformatting.
+
+2014-02-06 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_ch4.adb (Process_Transient_Object): Add local variable
+ Temp_Ins. When the transient object is initialized by an
+ aggregate, the hook must capture the object after the last
+ component assignment takes place.
+ * exp_ch7.adb (Detect_Subprogram_Call): Expose the subprogram to
+ routine Is_Subprogram_Call.
+ (Is_Subprogram_Call): Inspect an
+ aggregate that has been heavily expanded for subprogram calls.
+ (Process_Transient_Objects): Add local variables Expr, Ptr_Id
+ and Temp_Ins. Remove the nested declare block and adjust the
+ indentation. When the transient object is initialized by an
+ aggregate, the hook must capture the object after the last
+ component assignment takes place.
+
+2014-02-06 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_prag.adb (Analyze_Global_Item): Detect illegal uses of
+ external states with enabled properties that do not match the
+ global mode.
+ (Property_Error): New routine.
+ * sem_res.adb (Property_Error): New routine.
+ (Resolve_Actuals): Detect illegal uses of external variables with
+ enabled properties in procedure calls that do not match the mode of
+ the corresponding formal parameter.
+
+2014-02-06 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_util.adb (Has_Enabled_Property): Rename
+ formal parameter Prop_Nam to Property. Update the comment on usage
+ and all occurrences in the body. Add local variable Prop_Nam. When
+ inspecting a property with an expression, the property name
+ appears as the first choice of the component association.
+
2014-02-04 Robert Dewar <dewar@adacore.com>
* exp_ch5.adb, einfo.ads, freeze.adb, sem_ch8.adb: Minor reformatting.
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 7232ec8..d0ee791 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -12386,6 +12386,7 @@ package body Exp_Ch4 is
Fin_Stmts : List_Id;
Ptr_Id : Entity_Id;
Temp_Id : Entity_Id;
+ Temp_Ins : Node_Id;
-- Start of processing for Process_Transient_Object
@@ -12463,7 +12464,22 @@ package body Exp_Ch4 is
-- <or>
-- Temp := Obj_Id'Unrestricted_Access;
- Insert_After_And_Analyze (Decl,
+ -- When the transient object is initialized by an aggregate, the hook
+ -- must capture the object after the last component assignment takes
+ -- place. Only then is the object fully initialized.
+
+ if Ekind (Obj_Id) = E_Variable
+ and then Present (Last_Aggregate_Assignment (Obj_Id))
+ then
+ Temp_Ins := Last_Aggregate_Assignment (Obj_Id);
+
+ -- Otherwise the hook seizes the related object immediately
+
+ else
+ Temp_Ins := Decl;
+ end if;
+
+ Insert_After_And_Analyze (Temp_Ins,
Make_Assignment_Statement (Loc,
Name => New_Reference_To (Temp_Id, Loc),
Expression => Expr));
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index ddf6d7e..5e90723 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -2454,11 +2454,22 @@ package body Exp_Ch7 is
Expression => Make_Integer_Literal (Loc, Counter_Val));
-- Insert the counter after all initialization has been done. The
- -- place of insertion depends on the context. When dealing with a
- -- controlled function, the counter is inserted directly after the
- -- declaration because such objects lack init calls.
+ -- place of insertion depends on the context. If an object is being
+ -- initialized via an aggregate, then the counter must be inserted
+ -- after the last aggregate assignment.
- Find_Last_Init (Decl, Obj_Typ, Count_Ins, Body_Ins);
+ if Ekind (Obj_Id) = E_Variable
+ and then Present (Last_Aggregate_Assignment (Obj_Id))
+ then
+ Count_Ins := Last_Aggregate_Assignment (Obj_Id);
+ Body_Ins := Empty;
+
+ -- In all other cases the counter is inserted after the last call to
+ -- either [Deep_]Initialize or the type specific init proc.
+
+ else
+ Find_Last_Init (Decl, Obj_Typ, Count_Ins, Body_Ins);
+ end if;
Insert_After (Count_Ins, Inc_Decl);
Analyze (Inc_Decl);
@@ -4419,17 +4430,25 @@ package body Exp_Ch7 is
function Is_Subprogram_Call (N : Node_Id) return Traverse_Result;
-- Determine whether an arbitrary node denotes a subprogram call
+ procedure Detect_Subprogram_Call is
+ new Traverse_Proc (Is_Subprogram_Call);
+
------------------------
-- Is_Subprogram_Call --
------------------------
function Is_Subprogram_Call (N : Node_Id) return Traverse_Result is
begin
- -- A regular procedure or function call
+ -- Aggregates are usually rewritten into component by component
+ -- assignments and replaced by a reference to a temporary in the
+ -- original tree. Peek in the aggregate to detect function calls.
- if Nkind (N) in N_Subprogram_Call then
- Must_Hook := True;
- return Abandon;
+ if Nkind (N) = N_Identifier
+ and then Nkind_In (Original_Node (N), N_Aggregate,
+ N_Extension_Aggregate)
+ then
+ Detect_Subprogram_Call (Original_Node (N));
+ return OK;
-- Detect a call to a function that returns on the secondary stack
@@ -4439,6 +4458,12 @@ package body Exp_Ch7 is
Must_Hook := True;
return Abandon;
+ -- A regular procedure or function call
+
+ elsif Nkind (N) in N_Subprogram_Call then
+ Must_Hook := True;
+ return Abandon;
+
-- Keep searching
else
@@ -4446,13 +4471,11 @@ package body Exp_Ch7 is
end if;
end Is_Subprogram_Call;
- procedure Detect_Subprogram_Call is
- new Traverse_Proc (Is_Subprogram_Call);
-
-- Local variables
Built : Boolean := False;
Desig_Typ : Entity_Id;
+ Expr : Node_Id;
Fin_Block : Node_Id;
Fin_Data : Finalization_Exception_Data;
Fin_Decls : List_Id;
@@ -4462,9 +4485,11 @@ package body Exp_Ch7 is
Obj_Ref : Node_Id;
Obj_Typ : Entity_Id;
Prev_Fin : Node_Id := Empty;
+ Ptr_Id : Entity_Id;
Stmt : Node_Id;
Stmts : List_Id;
Temp_Id : Entity_Id;
+ Temp_Ins : Node_Id;
-- Start of processing for Process_Transient_Objects
@@ -4505,11 +4530,10 @@ package body Exp_Ch7 is
-- time around.
if not Built then
+ Built := True;
Fin_Decls := New_List;
Build_Object_Declarations (Fin_Data, Fin_Decls, Loc);
-
- Built := True;
end if;
-- Transient variables associated with subprogram calls need
@@ -4524,69 +4548,80 @@ package body Exp_Ch7 is
-- "hooks" are picked up by the finalization machinery.
if Must_Hook then
- declare
- Expr : Node_Id;
- Ptr_Id : Entity_Id;
- begin
- -- Step 1: Create an access type which provides a
- -- reference to the transient object. Generate:
+ -- Step 1: Create an access type which provides a reference
+ -- to the transient object. Generate:
- -- Ann : access [all] <Desig_Typ>;
+ -- Ann : access [all] <Desig_Typ>;
- Ptr_Id := Make_Temporary (Loc, 'A');
+ Ptr_Id := Make_Temporary (Loc, 'A');
- Insert_Action (Stmt,
- Make_Full_Type_Declaration (Loc,
- Defining_Identifier => Ptr_Id,
- Type_Definition =>
- Make_Access_To_Object_Definition (Loc,
- All_Present =>
- Ekind (Obj_Typ) = E_General_Access_Type,
- Subtype_Indication =>
- New_Reference_To (Desig_Typ, Loc))));
+ Insert_Action (Stmt,
+ Make_Full_Type_Declaration (Loc,
+ Defining_Identifier => Ptr_Id,
+ Type_Definition =>
+ Make_Access_To_Object_Definition (Loc,
+ All_Present =>
+ Ekind (Obj_Typ) = E_General_Access_Type,
+ Subtype_Indication =>
+ New_Reference_To (Desig_Typ, Loc))));
- -- Step 2: Create a temporary which acts as a hook to
- -- the transient object. Generate:
+ -- Step 2: Create a temporary which acts as a hook to the
+ -- transient object. Generate:
- -- Temp : Ptr_Id := null;
+ -- Temp : Ptr_Id := null;
- Temp_Id := Make_Temporary (Loc, 'T');
+ Temp_Id := Make_Temporary (Loc, 'T');
- Insert_Action (Stmt,
- Make_Object_Declaration (Loc,
- Defining_Identifier => Temp_Id,
- Object_Definition =>
- New_Reference_To (Ptr_Id, Loc)));
+ Insert_Action (Stmt,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Temp_Id,
+ Object_Definition =>
+ New_Reference_To (Ptr_Id, Loc)));
- -- Mark the temporary as a transient hook. This signals
- -- the machinery in Build_Finalizer to recognize this
- -- special case.
+ -- Mark the temporary as a transient hook. This signals the
+ -- machinery in Build_Finalizer to recognize this special
+ -- case.
- Set_Status_Flag_Or_Transient_Decl (Temp_Id, Stmt);
+ Set_Status_Flag_Or_Transient_Decl (Temp_Id, Stmt);
- -- Step 3: Hook the transient object to the temporary
+ -- Step 3: Hook the transient object to the temporary
- if Is_Access_Type (Obj_Typ) then
- Expr :=
- Convert_To (Ptr_Id, New_Reference_To (Obj_Id, Loc));
- else
- Expr :=
- Make_Attribute_Reference (Loc,
- Prefix => New_Reference_To (Obj_Id, Loc),
- Attribute_Name => Name_Unrestricted_Access);
- end if;
+ if Is_Access_Type (Obj_Typ) then
+ Expr :=
+ Convert_To (Ptr_Id, New_Reference_To (Obj_Id, Loc));
+ else
+ Expr :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Obj_Id, Loc),
+ Attribute_Name => Name_Unrestricted_Access);
+ end if;
- -- Generate:
- -- Temp := Ptr_Id (Obj_Id);
- -- <or>
- -- Temp := Obj_Id'Unrestricted_Access;
-
- Insert_After_And_Analyze (Stmt,
- Make_Assignment_Statement (Loc,
- Name => New_Reference_To (Temp_Id, Loc),
- Expression => Expr));
- end;
+ -- Generate:
+ -- Temp := Ptr_Id (Obj_Id);
+ -- <or>
+ -- Temp := Obj_Id'Unrestricted_Access;
+
+ -- When the transient object is initialized by an aggregate,
+ -- the hook must capture the object after the last component
+ -- assignment takes place. Only then is the object fully
+ -- initialized.
+
+ if Ekind (Obj_Id) = E_Variable
+ and then Present (Last_Aggregate_Assignment (Obj_Id))
+ then
+ Temp_Ins := Last_Aggregate_Assignment (Obj_Id);
+
+ -- Otherwise the hook seizes the related object immediately
+
+ else
+ Temp_Ins := Stmt;
+ end if;
+
+ Insert_After_And_Analyze (Temp_Ins,
+ Make_Assignment_Statement (Loc,
+ Name => New_Reference_To (Temp_Id, Loc),
+ Expression => Expr));
end if;
Stmts := New_List;
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index dce9b8d..344bd27 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -1861,8 +1861,34 @@ package body Sem_Prag is
(Item : Node_Id;
Global_Mode : Name_Id)
is
+ procedure Property_Error
+ (State_Id : Entity_Id;
+ Prop_Nam : Name_Id);
+ -- Emit an error concerning state State_Id with enabled property
+ -- Async_Readers, Effective_Reads or Effective_Writes that is not
+ -- marked as In_Out or Output item.
+
+ --------------------
+ -- Property_Error --
+ --------------------
+
+ procedure Property_Error
+ (State_Id : Entity_Id;
+ Prop_Nam : Name_Id)
+ is
+ begin
+ Error_Msg_Name_1 := Prop_Nam;
+ Error_Msg_NE
+ ("external state & with enabled property % must have mode "
+ & "In_Out or Output (SPARK RM 7.1.2(7))", Item, State_Id);
+ end Property_Error;
+
+ -- Local variables
+
Item_Id : Entity_Id;
+ -- Start of processing for Analyze_Global_Item
+
begin
-- Detect one of the following cases
@@ -1941,6 +1967,30 @@ package body Sem_Prag is
Ref => Item);
end if;
+ -- Detect an external state with an enabled property that
+ -- does not match the mode of the state.
+
+ if Global_Mode = Name_Input then
+ if Async_Readers_Enabled (Item_Id) then
+ Property_Error (Item_Id, Name_Async_Readers);
+
+ elsif Effective_Reads_Enabled (Item_Id) then
+ Property_Error (Item_Id, Name_Effective_Reads);
+
+ elsif Effective_Writes_Enabled (Item_Id) then
+ Property_Error (Item_Id, Name_Effective_Writes);
+ end if;
+
+ elsif Global_Mode = Name_Output
+ and then Async_Writers_Enabled (Item_Id)
+ then
+ Error_Msg_Name_1 := Name_Async_Writers;
+ Error_Msg_NE
+ ("external state & with enabled property % must have "
+ & "mode Input or In_Out (SPARK RM 7.1.2(7))",
+ Item, Item_Id);
+ end if;
+
-- Variable related checks
else
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index 7cb47f2..c7a7e08 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -3020,8 +3020,9 @@ package body Sem_Res is
procedure Resolve_Actuals (N : Node_Id; Nam : Entity_Id) is
Loc : constant Source_Ptr := Sloc (N);
A : Node_Id;
- F : Entity_Id;
+ A_Id : Entity_Id;
A_Typ : Entity_Id;
+ F : Entity_Id;
F_Typ : Entity_Id;
Prev : Node_Id := Empty;
Orig_A : Node_Id;
@@ -3043,6 +3044,14 @@ package body Sem_Res is
-- an instance of the default expression. The insertion is always
-- a named association.
+ procedure Property_Error
+ (Var : Node_Id;
+ Var_Id : Entity_Id;
+ Prop_Nam : Name_Id);
+ -- Emit an error concerning variable Var with entity Var_Id that has
+ -- enabled property Prop_Nam when it acts as an actual parameter in a
+ -- call and the corresponding formal parameter is of mode IN.
+
function Same_Ancestor (T1, T2 : Entity_Id) return Boolean;
-- Check whether T1 and T2, or their full views, are derived from a
-- common type. Used to enforce the restrictions on array conversions
@@ -3374,6 +3383,23 @@ package body Sem_Res is
Prev := Actval;
end Insert_Default;
+ --------------------
+ -- Property_Error --
+ --------------------
+
+ procedure Property_Error
+ (Var : Node_Id;
+ Var_Id : Entity_Id;
+ Prop_Nam : Name_Id)
+ is
+ begin
+ Error_Msg_Name_1 := Prop_Nam;
+ Error_Msg_NE
+ ("external variable & with enabled property % cannot appear as "
+ & "actual in procedure call (SPARK RM 7.1.3(11))", Var, Var_Id);
+ Error_Msg_N ("\\corresponding formal parameter has mode In", Var);
+ end Property_Error;
+
-------------------
-- Same_Ancestor --
-------------------
@@ -4288,6 +4314,41 @@ package body Sem_Res is
("volatile object cannot act as actual in a call (SPARK "
& "RM 7.1.3(12))", A);
end if;
+
+ -- Detect an external variable with an enabled property that
+ -- does not match the mode of the corresponding formal in a
+ -- procedure call.
+
+ -- why only procedure calls ???
+
+ if Ekind (Nam) = E_Procedure
+ and then Is_Entity_Name (A)
+ and then Present (Entity (A))
+ and then Ekind (Entity (A)) = E_Variable
+ then
+ A_Id := Entity (A);
+
+ if Ekind (F) = E_In_Parameter then
+ if Async_Readers_Enabled (A_Id) then
+ Property_Error (A, A_Id, Name_Async_Readers);
+ elsif Effective_Reads_Enabled (A_Id) then
+ Property_Error (A, A_Id, Name_Effective_Reads);
+ elsif Effective_Writes_Enabled (A_Id) then
+ Property_Error (A, A_Id, Name_Effective_Writes);
+ end if;
+
+ elsif Ekind (F) = E_Out_Parameter
+ and then Async_Writers_Enabled (A_Id)
+ then
+ Error_Msg_Name_1 := Name_Async_Writers;
+ Error_Msg_NE
+ ("external variable & with enabled property % cannot "
+ & "appear as actual in procedure call (SPARK RM "
+ & "7.1.3(11))", A, A_Id);
+ Error_Msg_N
+ ("\\corresponding formal parameter has mode Out", A);
+ end if;
+ end if;
end if;
Next_Actual (A);
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 12704a6..ba978e1 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -115,10 +115,10 @@ package body Sem_Util is
function Has_Enabled_Property
(State_Id : Node_Id;
- Prop_Nam : Name_Id) return Boolean;
+ Property : Name_Id) return Boolean;
-- Subsidiary to routines Async_xxx_Enabled and Effective_xxx_Enabled.
-- Determine whether an abstract state denoted by its entity State_Id has
- -- enabled property Prop_Name.
+ -- 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.
@@ -7255,13 +7255,14 @@ package body Sem_Util is
function Has_Enabled_Property
(State_Id : Node_Id;
- Prop_Nam : Name_Id) return Boolean
+ Property : Name_Id) return Boolean
is
- Decl : constant Node_Id := Parent (State_Id);
- Opt : Node_Id;
- Opt_Nam : Node_Id;
- Prop : Node_Id;
- Props : Node_Id;
+ Decl : constant Node_Id := Parent (State_Id);
+ Opt : Node_Id;
+ Opt_Nam : Node_Id;
+ Prop : Node_Id;
+ Prop_Nam : Node_Id;
+ Props : Node_Id;
begin
-- The declaration of an external abstract state appears as an extension
@@ -7305,7 +7306,7 @@ package body Sem_Util is
Prop := First (Expressions (Props));
while Present (Prop) loop
- if Chars (Prop) = Prop_Nam then
+ if Chars (Prop) = Property then
return True;
end if;
@@ -7316,7 +7317,9 @@ package body Sem_Util is
Prop := First (Component_Associations (Props));
while Present (Prop) loop
- if Chars (Prop) = Prop_Nam then
+ Prop_Nam := First (Choices (Prop));
+
+ if Chars (Prop_Nam) = Property then
return Is_True (Expr_Value (Expression (Prop)));
end if;
@@ -7326,7 +7329,7 @@ package body Sem_Util is
-- Single property
else
- return Chars (Props) = Prop_Nam;
+ return Chars (Props) = Property;
end if;
end if;
diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb
index e909474..49adb11 100644
--- a/gcc/ada/sprint.adb
+++ b/gcc/ada/sprint.adb
@@ -204,7 +204,7 @@ package body Sprint is
(Node : Node_Id;
Default : Node_Id);
-- Print the end label for a Handled_Sequence_Of_Statements in a body.
- -- If there is not end label, use the defining identifier of the enclosing
+ -- If there is no end label, use the defining identifier of the enclosing
-- construct. If the end label is present, treat it as a reference to the
-- defining entity of the construct: this guarantees that it carries the
-- proper sloc information for debugging purposes.