summaryrefslogtreecommitdiff
path: root/gcc/ada/exp_util.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/exp_util.adb')
-rw-r--r--gcc/ada/exp_util.adb257
1 files changed, 222 insertions, 35 deletions
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 82f3fcfc201..12fea51a197 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -336,7 +336,7 @@ package body Exp_Util is
-- component, whose prefix is the outer variable of the array type.
-- The n-dimensional array type has known indices Index, Index2...
-- Id_Ref is an indexed component form created by the enclosing init proc.
- -- Its successive indices are Val1, Val2,.. which are the loop variables
+ -- Its successive indices are Val1, Val2, ... which are the loop variables
-- in the loops that call the individual task init proc on each component.
-- The generated function has the following structure:
@@ -962,9 +962,16 @@ package body Exp_Util is
if Has_Entries (Typ)
or else Has_Interrupt_Handler (Typ)
or else (Has_Attach_Handler (Typ)
- and then not Restricted_Profile)
- or else (Ada_Version >= Ada_05
- and then Present (Interface_List (Parent (Typ))))
+ and then not Restricted_Profile)
+
+ -- A protected type without entries that covers an interface and
+ -- overrides the abstract routines with protected procedures is
+ -- considered equivalent to a protected type with entries in the
+ -- context of dispatching select statements. It is sufficent to
+ -- check for the presence of an interface list in the declaration
+ -- node to recognize this case.
+
+ or else Present (Interface_List (Parent (Typ)))
then
if Abort_Allowed
or else Restriction_Active (No_Entry_Queue) = False
@@ -1814,6 +1821,34 @@ package body Exp_Util is
return Node (Prim);
end Find_Prim_Op;
+ ----------------------------
+ -- Find_Protection_Object --
+ ----------------------------
+
+ function Find_Protection_Object (Scop : Entity_Id) return Entity_Id is
+ S : Entity_Id;
+
+ begin
+ S := Scop;
+ while Present (S) loop
+ if (Ekind (S) = E_Entry
+ or else Ekind (S) = E_Entry_Family
+ or else Ekind (S) = E_Function
+ or else Ekind (S) = E_Procedure)
+ and then Present (Protection_Object (S))
+ then
+ return Protection_Object (S);
+ end if;
+
+ S := Scope (S);
+ end loop;
+
+ -- If we do not find a Protection object in the scope chain, then
+ -- something has gone wrong, most likely the object was never created.
+
+ raise Program_Error;
+ end Find_Protection_Object;
+
----------------------
-- Force_Evaluation --
----------------------
@@ -2292,13 +2327,14 @@ package body Exp_Util is
return;
end if;
- -- Ignore insert of actions from inside default expression in the
- -- special preliminary analyze mode. Any insertions at this point
- -- have no relevance, since we are only doing the analyze to freeze
- -- the types of any static expressions. See section "Handling of
- -- Default Expressions" in the spec of package Sem for further details.
+ -- Ignore insert of actions from inside default expression (or other
+ -- similar "spec expression") in the special spec-expression analyze
+ -- mode. Any insertions at this point have no relevance, since we are
+ -- only doing the analyze to freeze the types of any static expressions.
+ -- See section "Handling of Default Expressions" in the spec of package
+ -- Sem for further details.
- if In_Default_Expression then
+ if In_Spec_Expression then
return;
end if;
@@ -3028,6 +3064,10 @@ package body Exp_Util is
Get_Name_String (Chars (E));
+ -- Most predefined primitives have internally generated names. Equality
+ -- must be treated differently; the predefined operation is recognized
+ -- as a homgeneous binary operator that returns Boolean.
+
if Name_Len > TSS_Name_Type'Last then
TSS_Name := TSS_Name_Type (Name_Buffer (Name_Len - TSS_Name'Length + 1
.. Name_Len));
@@ -3441,6 +3481,40 @@ package body Exp_Util is
and then Etype (Full_View (T)) /= T);
end Is_Untagged_Derivation;
+ ---------------------------
+ -- Is_Volatile_Reference --
+ ---------------------------
+
+ function Is_Volatile_Reference (N : Node_Id) return Boolean is
+ begin
+ if Nkind (N) in N_Has_Etype
+ and then Present (Etype (N))
+ and then Treat_As_Volatile (Etype (N))
+ then
+ return True;
+
+ elsif Is_Entity_Name (N) then
+ return Treat_As_Volatile (Entity (N));
+
+ elsif Nkind (N) = N_Slice then
+ return Is_Volatile_Reference (Prefix (N));
+
+ elsif Nkind_In (N, N_Indexed_Component, N_Selected_Component) then
+ if (Is_Entity_Name (Prefix (N))
+ and then Has_Volatile_Components (Entity (Prefix (N))))
+ or else (Present (Etype (Prefix (N)))
+ and then Has_Volatile_Components (Etype (Prefix (N))))
+ then
+ return True;
+ else
+ return Is_Volatile_Reference (Prefix (N));
+ end if;
+
+ else
+ return False;
+ end if;
+ end Is_Volatile_Reference;
+
--------------------
-- Kill_Dead_Code --
--------------------
@@ -4257,9 +4331,15 @@ package body Exp_Util is
end if;
end;
- -- If we have neither a record nor array component, it means that we
- -- have fallen off the top testing prefixes recursively, and we now
- -- have a stand alone object, where we don't have a problem.
+ -- For a slice, test the prefix, if that is possibly misaligned,
+ -- then for sure the slice is!
+
+ when N_Slice =>
+ return Possible_Bit_Aligned_Component (Prefix (N));
+
+ -- If we have none of the above, it means that we have fallen off the
+ -- top testing prefixes recursively, and we now have a stand alone
+ -- object, where we don't have a problem.
when others =>
return False;
@@ -4375,7 +4455,7 @@ package body Exp_Util is
-- hand, if we do not consider them to be side effect free, then
-- we get some awkward expansions in -gnato mode, resulting in
-- code insertions at a point where we do not have a clear model
- -- for performing the insertions. See 4908-002/comment for details.
+ -- for performing the insertions.
-- Special handling for entity names
@@ -4399,14 +4479,13 @@ package body Exp_Util is
return False;
-- Variables are considered to be a side effect if Variable_Ref
- -- is set or if we have a volatile variable and Name_Req is off.
+ -- is set or if we have a volatile reference and Name_Req is off.
-- If Name_Req is True then we can't help returning a name which
-- effectively allows multiple references in any case.
elsif Is_Variable (N) then
return not Variable_Ref
- and then (not Treat_As_Volatile (Entity (N))
- or else Name_Req);
+ and then (not Is_Volatile_Reference (N) or else Name_Req);
-- Any other entity (e.g. a subtype name) is definitely side
-- effect free.
@@ -4631,17 +4710,16 @@ package body Exp_Util is
Scope_Suppress := (others => True);
-- If it is a scalar type and we need to capture the value, just make
- -- a copy. Likewise for a function or operator call. And if we have a
- -- volatile variable and Nam_Req is not set (see comments above for
- -- Side_Effect_Free).
+ -- a copy. Likewise for a function call, an attribute reference or an
+ -- operator. And if we have a volatile reference and Name_Req is not
+ -- set (see comments above for Side_Effect_Free).
if Is_Elementary_Type (Exp_Type)
and then (Variable_Ref
or else Nkind (Exp) = N_Function_Call
+ or else Nkind (Exp) = N_Attribute_Reference
or else Nkind (Exp) in N_Op
- or else (not Name_Req
- and then Is_Entity_Name (Exp)
- and then Treat_As_Volatile (Entity (Exp))))
+ or else (not Name_Req and then Is_Volatile_Reference (Exp)))
then
Def_Id := Make_Defining_Identifier (Loc, New_Internal_Name ('R'));
Set_Etype (Def_Id, Exp_Type);
@@ -4686,9 +4764,9 @@ package body Exp_Util is
-- If this is a type conversion, leave the type conversion and remove
-- the side effects in the expression. This is important in several
- -- circumstances: for change of representations, and also when this
- -- is a view conversion to a smaller object, where gigi can end up
- -- creating its own temporary of the wrong size.
+ -- circumstances: for change of representations, and also when this is
+ -- a view conversion to a smaller object, where gigi can end up creating
+ -- its own temporary of the wrong size.
elsif Nkind (Exp) = N_Type_Conversion then
Remove_Side_Effects (Expression (Exp), Name_Req, Variable_Ref);
@@ -4732,14 +4810,12 @@ package body Exp_Util is
end if;
-- For expressions that denote objects, we can use a renaming scheme.
- -- We skip using this if we have a volatile variable and we do not
- -- have Nam_Req set true (see comments above for Side_Effect_Free).
+ -- We skip using this if we have a volatile reference and we do not
+ -- have Name_Req set true (see comments above for Side_Effect_Free).
elsif Is_Object_Reference (Exp)
and then Nkind (Exp) /= N_Function_Call
- and then (Name_Req
- or else not Is_Entity_Name (Exp)
- or else not Treat_As_Volatile (Entity (Exp)))
+ and then (Name_Req or else not Is_Volatile_Reference (Exp))
then
Def_Id := Make_Defining_Identifier (Loc, New_Internal_Name ('R'));
@@ -4778,7 +4854,7 @@ package body Exp_Util is
-- If this is a packed reference, or a selected component with a
-- non-standard representation, a reference to the temporary will
-- be replaced by a copy of the original expression (see
- -- exp_ch2.Expand_Renaming). Otherwise the temporary must be
+ -- Exp_Ch2.Expand_Renaming). Otherwise the temporary must be
-- elaborated by gigi, and is of course not to be replaced in-line
-- by the expression it renames, which would defeat the purpose of
-- removing the side-effect.
@@ -4795,6 +4871,36 @@ package body Exp_Util is
-- Otherwise we generate a reference to the value
else
+ -- Special processing for function calls that return a task. We need
+ -- to build a declaration that will enable build-in-place expansion
+ -- of the call.
+
+ -- This is relevant only in Ada 2005 mode. In Ada 95 programs we have
+ -- to accommodate functions returning limited objects by reference.
+
+ if Nkind (Exp) = N_Function_Call
+ and then Is_Task_Type (Etype (Exp))
+ and then Ada_Version >= Ada_05
+ then
+ declare
+ Obj : constant Entity_Id :=
+ Make_Defining_Identifier (Loc,
+ Chars => New_Internal_Name ('F'));
+ Decl : Node_Id;
+
+ begin
+ Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Obj,
+ Object_Definition => New_Occurrence_Of (Exp_Type, Loc),
+ Expression => Relocate_Node (Exp));
+ Insert_Action (Exp, Decl);
+ Set_Etype (Obj, Exp_Type);
+ Rewrite (Exp, New_Occurrence_Of (Obj, Loc));
+ return;
+ end;
+ end if;
+
Ref_Type := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
Ptr_Typ_Decl :=
@@ -5202,9 +5308,9 @@ package body Exp_Util is
Analyze (Asn);
- -- Kill current value indication. This is necessary because
- -- the tests of this flag are inserted out of sequence and must
- -- not pick up bogus indications of the wrong constant value.
+ -- Kill current value indication. This is necessary because the
+ -- tests of this flag are inserted out of sequence and must not
+ -- pick up bogus indications of the wrong constant value.
Set_Current_Value (Ent, Empty);
end if;
@@ -5237,6 +5343,87 @@ package body Exp_Util is
end if;
end Set_Renamed_Subprogram;
+ ----------------------------------
+ -- Silly_Boolean_Array_Not_Test --
+ ----------------------------------
+
+ -- This procedure implements an odd and silly test. We explicitly check
+ -- for the case where the 'First of the component type is equal to the
+ -- 'Last of this component type, and if this is the case, we make sure
+ -- that constraint error is raised. The reason is that the NOT is bound
+ -- to cause CE in this case, and we will not otherwise catch it.
+
+ -- Believe it or not, this was reported as a bug. Note that nearly
+ -- always, the test will evaluate statically to False, so the code will
+ -- be statically removed, and no extra overhead caused.
+
+ procedure Silly_Boolean_Array_Not_Test (N : Node_Id; T : Entity_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
+ CT : constant Entity_Id := Component_Type (T);
+
+ begin
+ Insert_Action (N,
+ Make_Raise_Constraint_Error (Loc,
+ Condition =>
+ Make_Op_Eq (Loc,
+ Left_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (CT, Loc),
+ Attribute_Name => Name_First),
+
+ Right_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (CT, Loc),
+ Attribute_Name => Name_Last)),
+ Reason => CE_Range_Check_Failed));
+ end Silly_Boolean_Array_Not_Test;
+
+ ----------------------------------
+ -- Silly_Boolean_Array_Xor_Test --
+ ----------------------------------
+
+ -- This procedure implements an odd and silly test. We explicitly check
+ -- for the XOR case where the component type is True .. True, since this
+ -- will raise constraint error. A special check is required since CE
+ -- will not be required otherwise (cf Expand_Packed_Not).
+
+ -- No such check is required for AND and OR, since for both these cases
+ -- False op False = False, and True op True = True.
+
+ procedure Silly_Boolean_Array_Xor_Test (N : Node_Id; T : Entity_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
+ CT : constant Entity_Id := Component_Type (T);
+ BT : constant Entity_Id := Base_Type (CT);
+
+ begin
+ Insert_Action (N,
+ Make_Raise_Constraint_Error (Loc,
+ Condition =>
+ Make_Op_And (Loc,
+ Left_Opnd =>
+ Make_Op_Eq (Loc,
+ Left_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (CT, Loc),
+ Attribute_Name => Name_First),
+
+ Right_Opnd =>
+ Convert_To (BT,
+ New_Occurrence_Of (Standard_True, Loc))),
+
+ Right_Opnd =>
+ Make_Op_Eq (Loc,
+ Left_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (CT, Loc),
+ Attribute_Name => Name_Last),
+
+ Right_Opnd =>
+ Convert_To (BT,
+ New_Occurrence_Of (Standard_True, Loc)))),
+ Reason => CE_Range_Check_Failed));
+ end Silly_Boolean_Array_Xor_Test;
+
--------------------------
-- Target_Has_Fixed_Ops --
--------------------------