diff options
author | Robert Dewar <dewar@adacore.com> | 2005-09-05 09:47:26 +0200 |
---|---|---|
committer | Arnaud Charlet <charlet@gcc.gnu.org> | 2005-09-05 09:47:26 +0200 |
commit | 630d30e96d138be05bea2e2769026ef819fb417d (patch) | |
tree | c73b6d3daab6c005edab3f279a15da80c4f077c3 | |
parent | 1a2c495da918ad782b233126773e4fc34bdacbe5 (diff) | |
download | gcc-630d30e96d138be05bea2e2769026ef819fb417d.zip gcc-630d30e96d138be05bea2e2769026ef819fb417d.tar.gz gcc-630d30e96d138be05bea2e2769026ef819fb417d.tar.bz2 |
exp_ch4.adb (Expand_N_In): Replace test of expression in its own type by valid test and generate warning.
2005-09-01 Robert Dewar <dewar@adacore.com>
Gary Dismukes <dismukes@adacore.com>
Javier Miranda <miranda@adacore.com>
* exp_ch4.adb (Expand_N_In): Replace test of expression in its own
type by valid test and generate warning.
(Tagged_Membership): Generate call to the run-time
subprogram IW_Membership in case of "Iface_CW_Typ in Typ'Class"
Change formal name Subtype_Mark to Result_Definition in several calls to
Make_Function_Specification.
(Expand_Allocator_Expression): Add tests for suppression of the AI-344
check for proper accessibility of the operand of a class-wide allocator.
The check can be left out if checks are suppressed or if the expression
has a specific tagged type whose level is known to be safe.
* exp_ch5.adb (Expand_N_Assignment_Statement): Simplify the code that
generates the run-time check associated with null-excluding entities.
(Expand_N_Return_Statement): Add tests to determine if the accessibility
check on the level of the return expression of a class-wide function
can be elided. The check usually isn't needed if the expression has a
specific type (unless it's a conversion or a formal parameter). Also
add a test for whether accessibility checks are suppressed. Augment
the comments to describe the conditions for performing the check.
From-SVN: r103849
-rw-r--r-- | gcc/ada/exp_ch4.adb | 144 | ||||
-rw-r--r-- | gcc/ada/exp_ch5.adb | 28 |
2 files changed, 129 insertions, 43 deletions
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 4385264..fbdb701 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -444,21 +444,24 @@ package body Exp_Ch4 is Expression => Node)); end if; - -- Ada 2005 (AI-344): - -- For an allocator with a class-wide designated type, generate an - -- accessibility check to verify that the level of the type of the - -- created object is not deeper than the level of the access type. - -- If the type of the qualified expression is class-wide, then - -- always generate the check. Otherwise, only generate the check - -- if the level of the qualified expression type is statically deeper - -- than the access type. Although the static accessibility will - -- generally have been performed as a legality check, it won't have - -- been done in cases where the allocator appears in a generic body, - -- so the run-time check is needed in general. (Not yet doing the - -- optimization to suppress the check for the static level case.???) + -- Ada 2005 (AI-344): For an allocator with a class-wide designated + -- type, generate an accessibility check to verify that the level of + -- the type of the created object is not deeper than the level of the + -- access type. If the type of the qualified expression is class- + -- wide, then always generate the check. Otherwise, only generate the + -- check if the level of the qualified expression type is statically + -- deeper than the access type. Although the static accessibility + -- will generally have been performed as a legality check, it won't + -- have been done in cases where the allocator appears in generic + -- body, so a run-time check is needed in general. if Ada_Version >= Ada_05 and then Is_Class_Wide_Type (Designated_Type (PtrT)) + and then not Scope_Suppress (Accessibility_Check) + and then + (Is_Class_Wide_Type (Etype (Exp)) + or else + Type_Access_Level (Etype (Exp)) > Type_Access_Level (PtrT)) then Insert_Action (N, Make_Raise_Program_Error (Loc, @@ -1388,7 +1391,7 @@ package body Exp_Ch4 is Make_Function_Specification (Loc, Defining_Unit_Name => Func_Name, Parameter_Specifications => Formals, - Subtype_Mark => New_Reference_To (Standard_Boolean, Loc)), + Result_Definition => New_Reference_To (Standard_Boolean, Loc)), Declarations => Decls, @@ -1833,7 +1836,7 @@ package body Exp_Ch4 is -- end loop; -- end if; - -- . . . + -- ... -- if Sn'Length /= 0 then -- P := Sn'First; @@ -2215,7 +2218,7 @@ package body Exp_Ch4 is Make_Function_Specification (Loc, Defining_Unit_Name => Func_Id, Parameter_Specifications => Param_Specs, - Subtype_Mark => New_Reference_To (Base_Typ, Loc)); + Result_Definition => New_Reference_To (Base_Typ, Loc)); -- Construct L's object declaration @@ -3034,22 +3037,81 @@ package body Exp_Ch4 is Rop : constant Node_Id := Right_Opnd (N); Static : constant Boolean := Is_OK_Static_Expression (N); + procedure Substitute_Valid_Check; + -- Replaces node N by Lop'Valid. This is done when we have an explicit + -- test for the left operand being in range of its subtype. + + ---------------------------- + -- Substitute_Valid_Check -- + ---------------------------- + + procedure Substitute_Valid_Check is + begin + Rewrite (N, + Make_Attribute_Reference (Loc, + Prefix => Relocate_Node (Lop), + Attribute_Name => Name_Valid)); + + Analyze_And_Resolve (N, Rtyp); + + Error_Msg_N ("?explicit membership test may be optimized away", N); + Error_Msg_N ("\?use ''Valid attribute instead", N); + return; + end Substitute_Valid_Check; + + -- Start of processing for Expand_N_In + begin - -- If we have an explicit range, do a bit of optimization based - -- on range analysis (we may be able to kill one or both checks). + -- Check case of explicit test for an expression in range of its + -- subtype. This is suspicious usage and we replace it with a 'Valid + -- test and give a warning. + + if Is_Scalar_Type (Etype (Lop)) + and then Nkind (Rop) in N_Has_Entity + and then Etype (Lop) = Entity (Rop) + and then Comes_From_Source (N) + then + Substitute_Valid_Check; + return; + end if; + + -- Case of explicit range if Nkind (Rop) = N_Range then declare - Lcheck : constant Compare_Result := - Compile_Time_Compare (Lop, Low_Bound (Rop)); - Ucheck : constant Compare_Result := - Compile_Time_Compare (Lop, High_Bound (Rop)); + Lo : constant Node_Id := Low_Bound (Rop); + Hi : constant Node_Id := High_Bound (Rop); + + Lo_Orig : constant Node_Id := Original_Node (Lo); + Hi_Orig : constant Node_Id := Original_Node (Hi); + + Lcheck : constant Compare_Result := Compile_Time_Compare (Lop, Lo); + Ucheck : constant Compare_Result := Compile_Time_Compare (Lop, Hi); begin - -- If either check is known to fail, replace result - -- by False, since the other check does not matter. - -- Preserve the static flag for legality checks, because - -- we are constant-folding beyond RM 4.9. + -- If test is explicit x'first .. x'last, replace by valid check + + if Is_Scalar_Type (Etype (Lop)) + and then Nkind (Lo_Orig) = N_Attribute_Reference + and then Attribute_Name (Lo_Orig) = Name_First + and then Nkind (Prefix (Lo_Orig)) in N_Has_Entity + and then Entity (Prefix (Lo_Orig)) = Etype (Lop) + and then Nkind (Hi_Orig) = N_Attribute_Reference + and then Attribute_Name (Hi_Orig) = Name_Last + and then Nkind (Prefix (Hi_Orig)) in N_Has_Entity + and then Entity (Prefix (Hi_Orig)) = Etype (Lop) + and then Comes_From_Source (N) + then + Substitute_Valid_Check; + return; + end if; + + -- If we have an explicit range, do a bit of optimization based + -- on range analysis (we may be able to kill one or both checks). + + -- If either check is known to fail, replace result by False since + -- the other check does not matter. Preserve the static flag for + -- legality checks, because we are constant-folding beyond RM 4.9. if Lcheck = LT or else Ucheck = GT then Rewrite (N, @@ -3452,8 +3514,9 @@ package body Exp_Ch4 is -- can be done. This avoids needing to duplicate this expansion code. procedure Expand_N_Not_In (N : Node_Id) is - Loc : constant Source_Ptr := Sloc (N); - Typ : constant Entity_Id := Etype (N); + Loc : constant Source_Ptr := Sloc (N); + Typ : constant Entity_Id := Etype (N); + Cfs : constant Boolean := Comes_From_Source (N); begin Rewrite (N, @@ -3461,7 +3524,16 @@ package body Exp_Ch4 is Right_Opnd => Make_In (Loc, Left_Opnd => Left_Opnd (N), - Right_Opnd => Right_Opnd (N)))); + Right_Opnd => Right_Opnd (N)))); + + -- We want this tp appear as coming from source if original does (see + -- tranformations in Expand_N_In). + + Set_Comes_From_Source (N, Cfs); + Set_Comes_From_Source (Right_Opnd (N), Cfs); + + -- Now analyze tranformed node + Analyze_And_Resolve (N, Typ); end Expand_N_Not_In; @@ -3995,7 +4067,7 @@ package body Exp_Ch4 is -- Obj1 : Enclosing_Non_UU_Type; -- Obj2 : Enclosing_Non_UU_Type (1); - -- . . . Obj1 = Obj2 . . . + -- ... Obj1 = Obj2 ... -- Generated code: @@ -5446,7 +5518,7 @@ package body Exp_Ch4 is Make_Parameter_Specification (Loc, Defining_Identifier => A, Parameter_Type => New_Reference_To (Typ, Loc))), - Subtype_Mark => New_Reference_To (Typ, Loc)), + Result_Definition => New_Reference_To (Typ, Loc)), Declarations => New_List ( Make_Object_Declaration (Loc, @@ -7715,7 +7787,7 @@ package body Exp_Ch4 is Make_Function_Specification (Loc, Defining_Unit_Name => Func_Name, Parameter_Specifications => Formals, - Subtype_Mark => New_Reference_To (Standard_Boolean, Loc)), + Result_Definition => New_Reference_To (Standard_Boolean, Loc)), Declarations => New_List ( Make_Object_Declaration (Loc, @@ -7846,7 +7918,7 @@ package body Exp_Ch4 is Make_Function_Specification (Loc, Defining_Unit_Name => Func_Name, Parameter_Specifications => Formals, - Subtype_Mark => New_Reference_To (Typ, Loc)), + Result_Definition => New_Reference_To (Typ, Loc)), Declarations => New_List ( Make_Object_Declaration (Loc, @@ -8052,7 +8124,12 @@ package body Exp_Ch4 is -- Ada 2005 (AI-251): Class-wide applied to interfaces - if Is_Interface (Etype (Class_Wide_Type (Right_Type))) then + if Is_Interface (Etype (Class_Wide_Type (Right_Type))) + + -- Give support to: "Iface_CW_Typ in Typ'Class" + + or else Is_Interface (Left_Type) + then return Make_Function_Call (Loc, Name => New_Occurrence_Of (RTE (RE_IW_Membership), Loc), @@ -8087,7 +8164,6 @@ package body Exp_Ch4 is New_Reference_To (Node (First_Elmt (Access_Disp_Table (Right_Type))), Loc)); end if; - end Tagged_Membership; ------------------------------ diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index 4880b4d..54da8cb4 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -1542,7 +1542,7 @@ package body Exp_Ch5 is -- create dereferences but are not semantic aliasings. elsif Is_Private_Type (Etype (Lhs)) - and then Has_Discriminants (Typ) + and then Has_Discriminants (Typ) and then Nkind (Lhs) = N_Explicit_Dereference and then Comes_From_Source (Lhs) then @@ -1621,17 +1621,13 @@ package body Exp_Ch5 is (Expression (Rhs), Designated_Type (Etype (Lhs))); end if; - -- Ada 2005 (AI-231): Generate conversion to the null-excluding - -- type to force the corresponding run-time check + -- Ada 2005 (AI-231): Generate the run-time check if Is_Access_Type (Typ) - and then - ((Is_Entity_Name (Lhs) and then Can_Never_Be_Null (Entity (Lhs))) - or else Can_Never_Be_Null (Etype (Lhs))) + and then Can_Never_Be_Null (Etype (Lhs)) + and then not Can_Never_Be_Null (Etype (Rhs)) then - Rewrite (Rhs, Convert_To (Etype (Lhs), - Relocate_Node (Rhs))); - Analyze_And_Resolve (Rhs, Etype (Lhs)); + Apply_Constraint_Check (Rhs, Etype (Lhs)); end if; -- If we are assigning an access type and the left side is an @@ -2833,9 +2829,23 @@ package body Exp_Ch5 is -- Ada 2005 (AI-344): If the result type is class-wide, then insert -- a check that the level of the return expression's underlying type -- is not deeper than the level of the master enclosing the function. + -- Always generate the check when the type of the return expression + -- is class-wide, when it's a type conversion, or when it's a formal + -- parameter. Otherwise, suppress the check in the case where the + -- return expression has a specific type whose level is known not to + -- be statically deeper than the function's result type. elsif Ada_Version >= Ada_05 and then Is_Class_Wide_Type (Return_Type) + and then not Scope_Suppress (Accessibility_Check) + and then + (Is_Class_Wide_Type (Etype (Exp)) + or else Nkind (Exp) = N_Type_Conversion + or else Nkind (Exp) = N_Unchecked_Type_Conversion + or else (Is_Entity_Name (Exp) + and then Ekind (Entity (Exp)) in Formal_Kind) + or else Scope_Depth (Enclosing_Dynamic_Scope (Etype (Exp))) > + Scope_Depth (Enclosing_Dynamic_Scope (Scope_Id))) then Insert_Action (Exp, Make_Raise_Program_Error (Loc, |