[multiple changes]
2017-01-12 Ed Schonberg <schonberg@adacore.com> * sem_attr.adb (Analyze_Attribute_Reference, case Loop_Entry): Hnadle properly the attribute reference when it appears as part of an expression in another loop aspect. 2017-01-12 Ed Schonberg <schonberg@adacore.com> * exp_ch3.adb (Check_Predicated_Discriminant): New procedure, subsidiary of Build_Initialization_Call, to complete generation of predicate checks on discriminants whose (sub)types have predicates, and to add checks on variants that do not have an others clause. * sem_util.adb (Gather_Components): A missing Others alternative is not an error when the type of the discriminant is a static predicate (and coverage has been checked when analyzing the case statement). A runtime check is generated to verify that a given discriminant satisfies the predicate (RM 3.8.1. (21.1/2)). 2017-01-12 Yannick Moy <moy@adacore.com> * gnat1drv.adb (Adjust_Global_Switches): Only perform checking of exception mechanism when generating code. 2017-01-12 Justin Squirek <squirek@adacore.com> * exp_ch7.adb (Add_Type_Invariants, Process_Array_Component): Remove handling of access component with invariant. (Build_Invariant_Procedure_Declaration): Remove return on class wide type. * freeze.adb (Freeze_Array_Type, Freeze_Record_Type): Remove conditional exception for component or array so Has_Own_Invariants flag is not falsly set. * sem_ch3.adb (Make_Class_Wide_Type): Initialize copy of class wide type to have no invariant flags. From-SVN: r244366
This commit is contained in:
parent
2168d7cc3b
commit
0289a8d7ef
@ -1,3 +1,39 @@
|
||||
2017-01-12 Ed Schonberg <schonberg@adacore.com>
|
||||
|
||||
* sem_attr.adb (Analyze_Attribute_Reference, case Loop_Entry):
|
||||
Hnadle properly the attribute reference when it appears as part
|
||||
of an expression in another loop aspect.
|
||||
|
||||
2017-01-12 Ed Schonberg <schonberg@adacore.com>
|
||||
|
||||
* exp_ch3.adb (Check_Predicated_Discriminant): New procedure,
|
||||
subsidiary of Build_Initialization_Call, to complete generation
|
||||
of predicate checks on discriminants whose (sub)types have
|
||||
predicates, and to add checks on variants that do not have an
|
||||
others clause.
|
||||
* sem_util.adb (Gather_Components): A missing Others alternative is
|
||||
not an error when the type of the discriminant is a static predicate
|
||||
(and coverage has been checked when analyzing the case statement). A
|
||||
runtime check is generated to verify that a given discriminant
|
||||
satisfies the predicate (RM 3.8.1. (21.1/2)).
|
||||
|
||||
2017-01-12 Yannick Moy <moy@adacore.com>
|
||||
|
||||
* gnat1drv.adb (Adjust_Global_Switches): Only
|
||||
perform checking of exception mechanism when generating code.
|
||||
|
||||
2017-01-12 Justin Squirek <squirek@adacore.com>
|
||||
|
||||
* exp_ch7.adb (Add_Type_Invariants, Process_Array_Component):
|
||||
Remove handling of access component with invariant.
|
||||
(Build_Invariant_Procedure_Declaration): Remove return on class
|
||||
wide type.
|
||||
* freeze.adb (Freeze_Array_Type, Freeze_Record_Type): Remove
|
||||
conditional exception for component or array so Has_Own_Invariants
|
||||
flag is not falsly set.
|
||||
* sem_ch3.adb (Make_Class_Wide_Type): Initialize copy of class
|
||||
wide type to have no invariant flags.
|
||||
|
||||
2017-01-12 Hristian Kirtchev <kirtchev@adacore.com>
|
||||
|
||||
* exp_ch9.adb, sem_prag.adb, s-tassta.adb, sem_util.adb, s-tarest.adb,
|
||||
|
@ -1286,7 +1286,118 @@ package body Exp_Ch3 is
|
||||
With_Default_Init : Boolean := False;
|
||||
Constructor_Ref : Node_Id := Empty) return List_Id
|
||||
is
|
||||
Res : constant List_Id := New_List;
|
||||
Res : constant List_Id := New_List;
|
||||
|
||||
Full_Type : Entity_Id;
|
||||
|
||||
procedure Check_Predicated_Discriminant
|
||||
(Val : Node_Id;
|
||||
Discr : Entity_Id);
|
||||
-- Discriminants whose subtypes have predicates are checked in two
|
||||
-- cases:
|
||||
-- a) When an object is default-initialized and assertions are enabled
|
||||
-- we check that the value of the discriminant obeys the predicate.
|
||||
|
||||
-- b) In all cases, if the discriminant controls a variant and the
|
||||
-- variant has no others_choice, Constraint_Error must be raised if
|
||||
-- the predicate is violated, because there is no variant covered
|
||||
-- by the illegal discriminant value.
|
||||
|
||||
-----------------------------------
|
||||
-- Check_Predicated_Discriminant --
|
||||
-----------------------------------
|
||||
|
||||
procedure Check_Predicated_Discriminant
|
||||
(Val : Node_Id;
|
||||
Discr : Entity_Id)
|
||||
is
|
||||
Typ : constant Entity_Id := Etype (Discr);
|
||||
|
||||
procedure Check_Missing_Others (V : Node_Id);
|
||||
-- ???
|
||||
|
||||
--------------------------
|
||||
-- Check_Missing_Others --
|
||||
--------------------------
|
||||
|
||||
procedure Check_Missing_Others (V : Node_Id) is
|
||||
Alt : Node_Id;
|
||||
Choice : Node_Id;
|
||||
Last_Var : Node_Id;
|
||||
|
||||
begin
|
||||
Last_Var := Last_Non_Pragma (Variants (V));
|
||||
Choice := First (Discrete_Choices (Last_Var));
|
||||
|
||||
-- An others_choice is added during expansion for gcc use, but
|
||||
-- does not cover the illegality.
|
||||
|
||||
if Entity (Name (V)) = Discr then
|
||||
if Present (Choice)
|
||||
and then (Nkind (Choice) /= N_Others_Choice
|
||||
or else not Comes_From_Source (Choice))
|
||||
then
|
||||
Check_Expression_Against_Static_Predicate (Val, Typ);
|
||||
|
||||
if not Is_Static_Expression (Val) then
|
||||
Prepend_To (Res,
|
||||
Make_Raise_Constraint_Error (Loc,
|
||||
Condition =>
|
||||
Make_Op_Not (Loc,
|
||||
Right_Opnd => Make_Predicate_Call (Typ, Val)),
|
||||
Reason => CE_Invalid_Data));
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Check whether some nested variant is ruled by the predicated
|
||||
-- discriminant.
|
||||
|
||||
Alt := First (Variants (V));
|
||||
while Present (Alt) loop
|
||||
if Nkind (Alt) = N_Variant
|
||||
and then Present (Variant_Part (Component_List (Alt)))
|
||||
then
|
||||
Check_Missing_Others
|
||||
(Variant_Part (Component_List (Alt)));
|
||||
end if;
|
||||
|
||||
Next (Alt);
|
||||
end loop;
|
||||
end Check_Missing_Others;
|
||||
|
||||
-- Local variables
|
||||
|
||||
Def : Node_Id;
|
||||
|
||||
-- Start of processing for Check_Predicated_Discriminant
|
||||
|
||||
begin
|
||||
if Ekind (Base_Type (Full_Type)) = E_Record_Type then
|
||||
Def := Type_Definition (Parent (Base_Type (Full_Type)));
|
||||
else
|
||||
return;
|
||||
end if;
|
||||
|
||||
if Policy_In_Effect (Name_Assert) = Name_Check
|
||||
and then not Predicates_Ignored (Etype (Discr))
|
||||
then
|
||||
Prepend_To (Res, Make_Predicate_Check (Typ, Val));
|
||||
end if;
|
||||
|
||||
-- If discriminant controls a variant, verify that predicate is
|
||||
-- obeyed or else an Others_Choice is present.
|
||||
|
||||
if Nkind (Def) = N_Record_Definition
|
||||
and then Present (Variant_Part (Component_List (Def)))
|
||||
and then Policy_In_Effect (Name_Assert) = Name_Ignore
|
||||
then
|
||||
Check_Missing_Others (Variant_Part (Component_List (Def)));
|
||||
end if;
|
||||
end Check_Predicated_Discriminant;
|
||||
|
||||
-- Local variables
|
||||
|
||||
Arg : Node_Id;
|
||||
Args : List_Id;
|
||||
Decls : List_Id;
|
||||
@ -1294,11 +1405,12 @@ package body Exp_Ch3 is
|
||||
Discr : Entity_Id;
|
||||
First_Arg : Node_Id;
|
||||
Full_Init_Type : Entity_Id;
|
||||
Full_Type : Entity_Id;
|
||||
Init_Call : Node_Id;
|
||||
Init_Type : Entity_Id;
|
||||
Proc : Entity_Id;
|
||||
|
||||
-- Start of processing for Build_Initialization_Call
|
||||
|
||||
begin
|
||||
pragma Assert (Constructor_Ref = Empty
|
||||
or else Is_CPP_Constructor_Call (Constructor_Ref));
|
||||
@ -1490,14 +1602,10 @@ package body Exp_Ch3 is
|
||||
-- of the discriminant, insert it ahead of the call.
|
||||
|
||||
Arg := New_Copy_Tree (Arg, New_Sloc => Loc);
|
||||
end if;
|
||||
|
||||
if Has_Predicates (Etype (Discr))
|
||||
and then not Predicate_Checks_Suppressed (Empty)
|
||||
and then not Predicates_Ignored (Etype (Discr))
|
||||
then
|
||||
Prepend_To (Res,
|
||||
Make_Predicate_Check (Etype (Discr), Arg));
|
||||
end if;
|
||||
if Has_Predicates (Etype (Discr)) then
|
||||
Check_Predicated_Discriminant (Arg, Discr);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
|
@ -3605,60 +3605,6 @@ package body Exp_Ch7 is
|
||||
|
||||
Produced_Check := True;
|
||||
end if;
|
||||
|
||||
-- In a rare case the designated type of an access component may
|
||||
-- have an invariant. In this case verify the dereference of the
|
||||
-- component.
|
||||
|
||||
if Is_Access_Type (Comp_Typ)
|
||||
and then Has_Invariants (Designated_Type (Comp_Typ))
|
||||
then
|
||||
Proc_Id :=
|
||||
Invariant_Procedure (Base_Type (Designated_Type (Comp_Typ)));
|
||||
|
||||
-- The designated type should have an invariant procedure if it
|
||||
-- has invariants of its own or inherits class-wide invariants
|
||||
-- from parent or interface types.
|
||||
|
||||
pragma Assert (Present (Proc_Id));
|
||||
|
||||
-- Generate:
|
||||
-- if _object (<Indexes>) /= null then
|
||||
-- <Desig_Comp_Typ>Invariant (_object (<Indices>).all);
|
||||
-- end if;
|
||||
|
||||
-- Note that the invariant procedure may have a null body if
|
||||
-- assertions are disabled or Assertion_Polity Ignore is in
|
||||
-- effect.
|
||||
|
||||
if not Has_Null_Body (Proc_Id) then
|
||||
Append_New_To (Comp_Checks,
|
||||
Make_If_Statement (Loc,
|
||||
Condition =>
|
||||
Make_Op_Ne (Loc,
|
||||
Left_Opnd =>
|
||||
Make_Indexed_Component (Loc,
|
||||
Prefix => New_Occurrence_Of (Obj_Id, Loc),
|
||||
Expressions => New_Copy_List (Indices)),
|
||||
Right_Opnd => Make_Null (Loc)),
|
||||
|
||||
Then_Statements => New_List (
|
||||
Make_Procedure_Call_Statement (Loc,
|
||||
Name =>
|
||||
New_Occurrence_Of (Proc_Id, Loc),
|
||||
|
||||
Parameter_Associations => New_List (
|
||||
Make_Explicit_Dereference (Loc,
|
||||
Prefix =>
|
||||
Make_Indexed_Component (Loc,
|
||||
Prefix =>
|
||||
New_Occurrence_Of (Obj_Id, Loc),
|
||||
Expressions =>
|
||||
New_Copy_List (Indices))))))));
|
||||
end if;
|
||||
|
||||
Produced_Check := True;
|
||||
end if;
|
||||
end Process_Array_Component;
|
||||
|
||||
---------------------------
|
||||
@ -4001,65 +3947,6 @@ package body Exp_Ch7 is
|
||||
Produced_Component_Check := True;
|
||||
end if;
|
||||
|
||||
-- In a rare case the designated type of an access component may
|
||||
-- have a invariant. In this case verify the dereference of the
|
||||
-- component.
|
||||
|
||||
if Is_Access_Type (Comp_Typ)
|
||||
and then Has_Invariants (Designated_Type (Comp_Typ))
|
||||
then
|
||||
Proc_Id :=
|
||||
Invariant_Procedure (Base_Type (Designated_Type (Comp_Typ)));
|
||||
|
||||
-- The designated type should have an invariant procedure if it
|
||||
-- has invariants of its own or inherits class-wide invariants
|
||||
-- from parent or interface types.
|
||||
|
||||
pragma Assert (Present (Proc_Id));
|
||||
|
||||
-- Generate:
|
||||
-- if T (_object).<Comp_Id> /= null then
|
||||
-- <Desig_Comp_Typ>Invariant (T (_object).<Comp_Id>.all);
|
||||
-- end if;
|
||||
|
||||
-- Note that the invariant procedure may have a null body if
|
||||
-- assertions are disabled or Assertion_Polity Ignore is in
|
||||
-- effect.
|
||||
|
||||
if not Has_Null_Body (Proc_Id) then
|
||||
Append_New_To (Comp_Checks,
|
||||
Make_If_Statement (Loc,
|
||||
Condition =>
|
||||
Make_Op_Ne (Loc,
|
||||
Left_Opnd =>
|
||||
Make_Selected_Component (Loc,
|
||||
Prefix =>
|
||||
Unchecked_Convert_To
|
||||
(T, New_Occurrence_Of (Obj_Id, Loc)),
|
||||
Selector_Name =>
|
||||
New_Occurrence_Of (Comp_Id, Loc)),
|
||||
Right_Opnd => Make_Null (Loc)),
|
||||
|
||||
Then_Statements => New_List (
|
||||
Make_Procedure_Call_Statement (Loc,
|
||||
Name =>
|
||||
New_Occurrence_Of (Proc_Id, Loc),
|
||||
|
||||
Parameter_Associations => New_List (
|
||||
Make_Explicit_Dereference (Loc,
|
||||
Prefix =>
|
||||
Make_Selected_Component (Loc,
|
||||
Prefix =>
|
||||
Unchecked_Convert_To
|
||||
(T, New_Occurrence_Of (Obj_Id, Loc)),
|
||||
Selector_Name =>
|
||||
New_Occurrence_Of (Comp_Id, Loc))))))));
|
||||
end if;
|
||||
|
||||
Produced_Check := True;
|
||||
Produced_Component_Check := True;
|
||||
end if;
|
||||
|
||||
if Produced_Component_Check and then Has_Unchecked_Union (T) then
|
||||
Error_Msg_NE
|
||||
("invariants cannot be checked on components of "
|
||||
@ -4525,15 +4412,10 @@ package body Exp_Ch7 is
|
||||
|
||||
pragma Assert (Has_Invariants (Work_Typ));
|
||||
|
||||
-- ??? invariants of class-wide types are not properly implemented
|
||||
|
||||
if Is_Class_Wide_Type (Work_Typ) then
|
||||
return;
|
||||
|
||||
-- Nothing to do for interface types as their class-wide invariants are
|
||||
-- inherited by implementing types.
|
||||
|
||||
elsif Is_Interface (Work_Typ) then
|
||||
if Is_Interface (Work_Typ) then
|
||||
return;
|
||||
end if;
|
||||
|
||||
@ -4849,15 +4731,10 @@ package body Exp_Ch7 is
|
||||
|
||||
pragma Assert (Has_Invariants (Work_Typ));
|
||||
|
||||
-- ??? invariants of class-wide types are not properly implemented
|
||||
|
||||
if Is_Class_Wide_Type (Work_Typ) then
|
||||
return;
|
||||
|
||||
-- Nothing to do for interface types as their class-wide invariants are
|
||||
-- inherited by implementing types.
|
||||
|
||||
elsif Is_Interface (Work_Typ) then
|
||||
if Is_Interface (Work_Typ) then
|
||||
return;
|
||||
|
||||
-- Nothing to do if the type already has a "partial" invariant procedure
|
||||
|
@ -2377,12 +2377,7 @@ package body Freeze is
|
||||
-- The array type requires its own invariant procedure in order to
|
||||
-- verify the component invariant over all elements.
|
||||
|
||||
if Has_Invariants (Component_Type (Arr))
|
||||
or else
|
||||
(Is_Access_Type (Component_Type (Arr))
|
||||
and then Has_Invariants
|
||||
(Designated_Type (Component_Type (Arr))))
|
||||
then
|
||||
if Has_Invariants (Component_Type (Arr)) then
|
||||
Set_Has_Own_Invariants (Arr);
|
||||
|
||||
-- The array type is an implementation base type. Propagate the
|
||||
@ -4305,12 +4300,7 @@ package body Freeze is
|
||||
-- parent class-wide invariants are always inherited.
|
||||
|
||||
if Comes_From_Source (Comp)
|
||||
and then
|
||||
(Has_Invariants (Etype (Comp))
|
||||
or else
|
||||
(Is_Access_Type (Etype (Comp))
|
||||
and then Has_Invariants
|
||||
(Designated_Type (Etype (Comp)))))
|
||||
and then Has_Invariants (Etype (Comp))
|
||||
then
|
||||
Set_Has_Own_Invariants (Rec);
|
||||
end if;
|
||||
|
@ -521,28 +521,35 @@ procedure Gnat1drv is
|
||||
Targparm.Frontend_Layout_On_Target := True;
|
||||
end if;
|
||||
|
||||
-- Set and check exception mechanism
|
||||
-- Set and check exception mechanism. This is only meaningful when
|
||||
-- compiling, and in particular not meaningful for special modes used
|
||||
-- for program analysis rather than compilation: ASIS mode, CodePeer
|
||||
-- mode and GNATprove mode.
|
||||
|
||||
case Targparm.Frontend_Exceptions_On_Target is
|
||||
when True =>
|
||||
case Targparm.ZCX_By_Default_On_Target is
|
||||
when True =>
|
||||
Write_Line
|
||||
("Run-time library configured incorrectly");
|
||||
Write_Line
|
||||
("(requesting support for Frontend ZCX exceptions)");
|
||||
raise Unrecoverable_Error;
|
||||
when False =>
|
||||
Exception_Mechanism := Front_End_SJLJ;
|
||||
end case;
|
||||
when False =>
|
||||
case Targparm.ZCX_By_Default_On_Target is
|
||||
when True =>
|
||||
Exception_Mechanism := Back_End_ZCX;
|
||||
when False =>
|
||||
Exception_Mechanism := Back_End_SJLJ;
|
||||
end case;
|
||||
end case;
|
||||
if Operating_Mode = Generate_Code
|
||||
and then not (ASIS_Mode or CodePeer_Mode or GNATprove_Mode)
|
||||
then
|
||||
case Targparm.Frontend_Exceptions_On_Target is
|
||||
when True =>
|
||||
case Targparm.ZCX_By_Default_On_Target is
|
||||
when True =>
|
||||
Write_Line
|
||||
("Run-time library configured incorrectly");
|
||||
Write_Line
|
||||
("(requesting support for Frontend ZCX exceptions)");
|
||||
raise Unrecoverable_Error;
|
||||
when False =>
|
||||
Exception_Mechanism := Front_End_SJLJ;
|
||||
end case;
|
||||
when False =>
|
||||
case Targparm.ZCX_By_Default_On_Target is
|
||||
when True =>
|
||||
Exception_Mechanism := Back_End_ZCX;
|
||||
when False =>
|
||||
Exception_Mechanism := Back_End_SJLJ;
|
||||
end case;
|
||||
end case;
|
||||
end if;
|
||||
|
||||
-- Set proper status for overflow check mechanism
|
||||
|
||||
|
@ -4465,7 +4465,17 @@ package body Sem_Attr is
|
||||
-- purpose if they appear in an appropriate location in a loop,
|
||||
-- which was already checked by the top level pragma circuit).
|
||||
|
||||
if No (Enclosing_Pragma) then
|
||||
-- Loop_Entry also denotes a value and as such can appear within an
|
||||
-- expression that is an argument for another loop aspect. In that
|
||||
-- case it will have been expanded into the corresponding assignment.
|
||||
|
||||
if Expander_Active
|
||||
and then Nkind (Parent (N)) = N_Assignment_Statement
|
||||
and then not Comes_From_Source (Parent (N))
|
||||
then
|
||||
null;
|
||||
|
||||
elsif No (Enclosing_Pragma) then
|
||||
Error_Attr ("attribute% must appear within appropriate pragma", N);
|
||||
end if;
|
||||
|
||||
@ -4519,7 +4529,9 @@ package body Sem_Attr is
|
||||
-- early transformation also avoids the generation of a useless loop
|
||||
-- entry constant.
|
||||
|
||||
if Is_Ignored (Enclosing_Pragma) then
|
||||
if Present (Enclosing_Pragma)
|
||||
and then Is_Ignored (Enclosing_Pragma)
|
||||
then
|
||||
Rewrite (N, Relocate_Node (P));
|
||||
Preanalyze_And_Resolve (N);
|
||||
|
||||
@ -11039,7 +11051,7 @@ package body Sem_Attr is
|
||||
|
||||
if Is_Entity_Name (P)
|
||||
and then (Attr_Id = Attribute_Unrestricted_Access
|
||||
or else Is_Subprogram (Entity (P)))
|
||||
or else Is_Subprogram (Entity (P)))
|
||||
then
|
||||
Set_Address_Taken (Entity (P));
|
||||
end if;
|
||||
|
@ -18307,7 +18307,8 @@ package body Sem_Ch3 is
|
||||
Set_Freeze_Node (CW_Type, Empty);
|
||||
|
||||
-- Customize the class-wide type: It has no prim. op., it cannot be
|
||||
-- abstract and its Etype points back to the specific root type.
|
||||
-- abstract, its Etype points back to the specific root type, and it
|
||||
-- cannot have any invariants.
|
||||
|
||||
Set_Ekind (CW_Type, E_Class_Wide_Type);
|
||||
Set_Is_Tagged_Type (CW_Type, True);
|
||||
@ -18316,6 +18317,9 @@ package body Sem_Ch3 is
|
||||
Set_Is_Constrained (CW_Type, False);
|
||||
Set_Is_First_Subtype (CW_Type, Is_First_Subtype (T));
|
||||
Set_Default_SSO (CW_Type);
|
||||
Set_Has_Inheritable_Invariants (CW_Type, False);
|
||||
Set_Has_Inherited_Invariants (CW_Type, False);
|
||||
Set_Has_Own_Invariants (CW_Type, False);
|
||||
|
||||
if Ekind (T) = E_Class_Wide_Subtype then
|
||||
Set_Etype (CW_Type, Etype (Base_Type (T)));
|
||||
|
@ -7572,7 +7572,14 @@ package body Sem_Util is
|
||||
end loop Find_Discrete_Value;
|
||||
end Search_For_Discriminant_Value;
|
||||
|
||||
if No (Variant) then
|
||||
-- The case statement must include a variant that corresponds to the
|
||||
-- value of the discriminant, unless the discriminant type has a
|
||||
-- static predicate. In that case the absence of an others_choice that
|
||||
-- would cover this value becomes a run-time error (3.8,1 (21.1/2)).
|
||||
|
||||
if No (Variant)
|
||||
and then not Has_Static_Predicate (Etype (Discrim_Name))
|
||||
then
|
||||
Error_Msg_NE
|
||||
("value of discriminant & is out of range", Discrim_Value, Discrim);
|
||||
Report_Errors := True;
|
||||
@ -7583,8 +7590,10 @@ package body Sem_Util is
|
||||
-- components to the Into list. The nested components are part of
|
||||
-- the same record type.
|
||||
|
||||
Gather_Components
|
||||
(Typ, Component_List (Variant), Governed_By, Into, Report_Errors);
|
||||
if Present (Variant) then
|
||||
Gather_Components
|
||||
(Typ, Component_List (Variant), Governed_By, Into, Report_Errors);
|
||||
end if;
|
||||
end Gather_Components;
|
||||
|
||||
------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user