summaryrefslogtreecommitdiff
path: root/gcc/ada/exp_util.adb
diff options
context:
space:
mode:
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2007-06-06 10:28:07 +0000
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2007-06-06 10:28:07 +0000
commit378089464983e017bc55756470c487ac25fa4c55 (patch)
tree2aac9a39bc29def98b761c1e19d629191da83b42 /gcc/ada/exp_util.adb
parente0ec9373d584331140a7f3189857b94dacd76487 (diff)
downloadgcc-378089464983e017bc55756470c487ac25fa4c55.tar.gz
2007-04-20 Ed Schonberg <schonberg@adacore.com>
* exp_util.ads, exp_util.adb (Expand_Subtype_From_Expr): In Ada2005, an object of a limited type can be initialized with a call to a function that returns in place. If the limited type has unknown discriminants, and the underlying type is a constrained composite type, build an actual subtype from the function call, as is done for private types. (Side_Effect_Free): An expression that is the renaming of an object or whose prefix is the renaming of a object, is not side-effect free because it may be assigned through the renaming and its value must be captured in a temporary. (Has_Controlled_Coextensions): New routine. (Expand_Subtype_From_Expr): Do nothing if type is a limited interface, as is done for other limited types. (Non_Limited_Designated_Type): new predicate. (Make_CW_Equivalent_Type): Modified to handle class-wide interface objects. Remove all handling of with_type clauses. * par-ch10.adb: Remove all handling of with_type clauses. * lib-load.ads, lib-load.adb (Load_Main_Source): Do not get the checksum if the main source could not be parsed. (Loat_Unit): When processing a child unit, determine properly whether the parent unit is a renaming when the parent is itself a child unit. Remove handling of with_type clauses. * sinfo.ads, sinfo.adb (Is_Static_Coextension): New function. (Set_Is_Static_Coextension): New procedure. (Has_Local_Raise): New function (Set_Has_Local_Raise): New procedure (Renaming_Exception): New field (Has_Init_Expression): New flag (Delay_Finalize_Attach): Remove because flag is obsolete. (Set_Delay_Finalize_Attach): Remove because flag is obsolete. Remove all handling of with_type clauses. (Exception_Junk): Can now be set in N_Block_Statement git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125410 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/exp_util.adb')
-rw-r--r--gcc/ada/exp_util.adb292
1 files changed, 228 insertions, 64 deletions
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 5e938aa1fc8..93798b30eb2 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2006, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2007, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -32,11 +32,9 @@ with Elists; use Elists;
with Errout; use Errout;
with Exp_Aggr; use Exp_Aggr;
with Exp_Ch7; use Exp_Ch7;
-with Hostparm; use Hostparm;
with Inline; use Inline;
with Itypes; use Itypes;
with Lib; use Lib;
-with Namet; use Namet;
with Nlists; use Nlists;
with Nmake; use Nmake;
with Opt; use Opt;
@@ -653,7 +651,7 @@ package body Exp_Util is
Expr := Make_Function_Call (Loc,
Name => New_Occurrence_Of (Defining_Entity (Fun), Loc));
- if not In_Init_Proc then
+ if not In_Init_Proc and then VM_Target = No_VM then
Set_Uses_Sec_Stack (Defining_Entity (Fun));
end if;
end if;
@@ -1289,11 +1287,35 @@ package body Exp_Util is
then
null;
- -- Nothing to be done if the type of the expression is limited, because
- -- in this case the expression cannot be copied, and its use can only
- -- be by reference and there is no need for the actual subtype.
+ -- In Ada95, Nothing to be done if the type of the expression is
+ -- limited, because in this case the expression cannot be copied,
+ -- and its use can only be by reference.
- elsif Is_Limited_Type (Exp_Typ) then
+ -- In Ada2005, the context can be an object declaration whose expression
+ -- is a function that returns in place. If the nominal subtype has
+ -- unknown discriminants, the call still provides constraints on the
+ -- object, and we have to create an actual subtype from it.
+
+ -- If the type is class-wide, the expression is dynamically tagged and
+ -- we do not create an actual subtype either. Ditto for an interface.
+
+ elsif Is_Limited_Type (Exp_Typ)
+ and then
+ (Is_Class_Wide_Type (Exp_Typ)
+ or else Is_Interface (Exp_Typ)
+ or else not Has_Unknown_Discriminants (Exp_Typ)
+ or else not Is_Composite_Type (Unc_Type))
+ then
+ null;
+
+ -- For limited interfaces, nothing to be done
+
+ -- This branch may be redundant once the limited interface issue is
+ -- sorted out???
+
+ elsif Is_Interface (Exp_Typ)
+ and then Is_Limited_Interface (Exp_Typ)
+ then
null;
else
@@ -2106,6 +2128,44 @@ package body Exp_Util is
end;
end Get_Current_Value_Condition;
+ ---------------------------------
+ -- Has_Controlled_Coextensions --
+ ---------------------------------
+
+ function Has_Controlled_Coextensions (Typ : Entity_Id) return Boolean is
+ D_Typ : Entity_Id;
+ Discr : Entity_Id;
+
+ begin
+ -- Only consider record types
+
+ if Ekind (Typ) /= E_Record_Type
+ and then Ekind (Typ) /= E_Record_Subtype
+ then
+ return False;
+ end if;
+
+ if Has_Discriminants (Typ) then
+ Discr := First_Discriminant (Typ);
+ while Present (Discr) loop
+ D_Typ := Etype (Discr);
+
+ if Ekind (D_Typ) = E_Anonymous_Access_Type
+ and then
+ (Is_Controlled (Directly_Designated_Type (D_Typ))
+ or else
+ Is_Concurrent_Type (Directly_Designated_Type (D_Typ)))
+ then
+ return True;
+ end if;
+
+ Next_Discriminant (Discr);
+ end loop;
+ end if;
+
+ return False;
+ end Has_Controlled_Coextensions;
+
--------------------
-- Homonym_Number --
--------------------
@@ -2725,8 +2785,7 @@ package body Exp_Util is
N_Variant |
N_Variant_Part |
N_Validate_Unchecked_Conversion |
- N_With_Clause |
- N_With_Type_Clause
+ N_With_Clause
=>
null;
@@ -2755,13 +2814,14 @@ package body Exp_Util is
P := Parent (N);
end if;
end loop;
-
end Insert_Actions;
-- Version with check(s) suppressed
procedure Insert_Actions
- (Assoc_Node : Node_Id; Ins_Actions : List_Id; Suppress : Check_Id)
+ (Assoc_Node : Node_Id;
+ Ins_Actions : List_Id;
+ Suppress : Check_Id)
is
begin
if Suppress = All_Checks then
@@ -2810,7 +2870,8 @@ package body Exp_Util is
Aux : constant Node_Id := Aux_Decls_Node (Cunit (Main_Unit));
begin
- New_Scope (Cunit_Entity (Main_Unit));
+ Push_Scope (Cunit_Entity (Main_Unit));
+ -- ??? should this be Current_Sem_Unit instead of Main_Unit?
if No (Actions (Aux)) then
Set_Actions (Aux, New_List (N));
@@ -2831,7 +2892,8 @@ package body Exp_Util is
begin
if Is_Non_Empty_List (L) then
- New_Scope (Cunit_Entity (Main_Unit));
+ Push_Scope (Cunit_Entity (Main_Unit));
+ -- ??? should this be Current_Sem_Unit instead of Main_Unit?
if No (Actions (Aux)) then
Set_Actions (Aux, L);
@@ -3078,14 +3140,7 @@ package body Exp_Util is
function Is_Possibly_Unaligned_Slice (N : Node_Id) return Boolean is
begin
- -- ??? GCC3 will eventually handle strings with arbitrary alignments,
- -- but for now the following check must be disabled.
-
- -- if get_gcc_version >= 3 then
- -- return False;
- -- end if;
-
- -- For renaming case, go to renamed object
+ -- Go to renamed object
if Is_Entity_Name (N)
and then Is_Object (Entity (N))
@@ -3589,6 +3644,7 @@ package body Exp_Util is
Loc : constant Source_Ptr := Sloc (E);
Root_Typ : constant Entity_Id := Root_Type (T);
List_Def : constant List_Id := Empty_List;
+ Comp_List : constant List_Id := New_List;
Equiv_Type : Entity_Id;
Range_Type : Entity_Id;
Str_Type : Entity_Id;
@@ -3611,22 +3667,35 @@ package body Exp_Util is
Make_Subtype_From_Expr (E, Root_Typ)));
end if;
- -- subtype rg__xx is Storage_Offset range
- -- (Expr'size - typ'size) / Storage_Unit
+ -- Generate the range subtype declaration
Range_Type := Make_Defining_Identifier (Loc, New_Internal_Name ('G'));
- Sizexpr :=
- Make_Op_Subtract (Loc,
- Left_Opnd =>
- Make_Attribute_Reference (Loc,
- Prefix =>
- OK_Convert_To (T, Duplicate_Subexpr_No_Checks (E)),
- Attribute_Name => Name_Size),
- Right_Opnd =>
- Make_Attribute_Reference (Loc,
- Prefix => New_Reference_To (Constr_Root, Loc),
- Attribute_Name => Name_Object_Size));
+ if not Is_Interface (Root_Typ) then
+ -- subtype rg__xx is
+ -- Storage_Offset range 1 .. (Expr'size - typ'size) / Storage_Unit
+
+ Sizexpr :=
+ Make_Op_Subtract (Loc,
+ Left_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ OK_Convert_To (T, Duplicate_Subexpr_No_Checks (E)),
+ Attribute_Name => Name_Size),
+ Right_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Reference_To (Constr_Root, Loc),
+ Attribute_Name => Name_Object_Size));
+ else
+ -- subtype rg__xx is
+ -- Storage_Offset range 1 .. Expr'size / Storage_Unit
+
+ Sizexpr :=
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ OK_Convert_To (T, Duplicate_Subexpr_No_Checks (E)),
+ Attribute_Name => Name_Size);
+ end if;
Set_Paren_Count (Sizexpr, 1);
@@ -3661,7 +3730,7 @@ package body Exp_Util is
New_List (New_Reference_To (Range_Type, Loc))))));
-- type Equiv_T is record
- -- _parent : Tnn;
+ -- [ _parent : Tnn; ]
-- E : Str_Type;
-- end Equiv_T;
@@ -3682,36 +3751,41 @@ package body Exp_Util is
Set_Ekind (Equiv_Type, E_Record_Type);
Set_Parent_Subtype (Equiv_Type, Constr_Root);
+ if not Is_Interface (Root_Typ) then
+ Append_To (Comp_List,
+ Make_Component_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Name_uParent),
+ Component_Definition =>
+ Make_Component_Definition (Loc,
+ Aliased_Present => False,
+ Subtype_Indication => New_Reference_To (Constr_Root, Loc))));
+ end if;
+
+ Append_To (Comp_List,
+ Make_Component_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc,
+ Chars => New_Internal_Name ('C')),
+ Component_Definition =>
+ Make_Component_Definition (Loc,
+ Aliased_Present => False,
+ Subtype_Indication => New_Reference_To (Str_Type, Loc))));
+
Append_To (List_Def,
Make_Full_Type_Declaration (Loc,
Defining_Identifier => Equiv_Type,
-
Type_Definition =>
Make_Record_Definition (Loc,
- Component_List => Make_Component_List (Loc,
- Component_Items => New_List (
- Make_Component_Declaration (Loc,
- Defining_Identifier =>
- Make_Defining_Identifier (Loc, Name_uParent),
- Component_Definition =>
- Make_Component_Definition (Loc,
- Aliased_Present => False,
- Subtype_Indication =>
- New_Reference_To (Constr_Root, Loc))),
-
- Make_Component_Declaration (Loc,
- Defining_Identifier =>
- Make_Defining_Identifier (Loc,
- Chars => New_Internal_Name ('C')),
- Component_Definition =>
- Make_Component_Definition (Loc,
- Aliased_Present => False,
- Subtype_Indication =>
- New_Reference_To (Str_Type, Loc)))),
-
- Variant_Part => Empty))));
-
- Insert_Actions (E, List_Def);
+ Component_List =>
+ Make_Component_List (Loc,
+ Component_Items => Comp_List,
+ Variant_Part => Empty))));
+
+ -- Suppress all checks during the analysis of the expanded code
+ -- to avoid the generation of spurious warnings under ZFP run-time.
+
+ Insert_Actions (E, List_Def, Suppress => All_Checks);
return Equiv_Type;
end Make_CW_Equivalent_Type;
@@ -3839,12 +3913,12 @@ package body Exp_Util is
EQ_Typ : Entity_Id := Empty;
begin
- -- A class-wide equivalent type is not needed when Java_VM
- -- because the JVM back end handles the class-wide object
+ -- A class-wide equivalent type is not needed when VM_Target
+ -- because the VM back-ends handle the class-wide object
-- initialization itself (and doesn't need or want the
-- additional intermediate type to handle the assignment).
- if Expander_Active and then not Java_VM then
+ if Expander_Active and then VM_Target = No_VM then
EQ_Typ := Make_CW_Equivalent_Type (Unc_Typ, E);
end if;
@@ -3952,6 +4026,22 @@ package body Exp_Util is
return (Res);
end New_Class_Wide_Subtype;
+ --------------------------------
+ -- Non_Limited_Designated_Type --
+ ---------------------------------
+
+ function Non_Limited_Designated_Type (T : Entity_Id) return Entity_Id is
+ Desig : constant Entity_Id := Designated_Type (T);
+ begin
+ if Ekind (Desig) = E_Incomplete_Type
+ and then Present (Non_Limited_View (Desig))
+ then
+ return Non_Limited_View (Desig);
+ else
+ return Desig;
+ end if;
+ end Non_Limited_Designated_Type;
+
-----------------------------------
-- OK_To_Do_Constant_Replacement --
-----------------------------------
@@ -4019,6 +4109,69 @@ package body Exp_Util is
end if;
end OK_To_Do_Constant_Replacement;
+ ------------------------------------
+ -- Possible_Bit_Aligned_Component --
+ ------------------------------------
+
+ function Possible_Bit_Aligned_Component (N : Node_Id) return Boolean is
+ begin
+ case Nkind (N) is
+
+ -- Case of indexed component
+
+ when N_Indexed_Component =>
+ declare
+ P : constant Node_Id := Prefix (N);
+ Ptyp : constant Entity_Id := Etype (P);
+
+ begin
+ -- If we know the component size and it is less than 64, then
+ -- we are definitely OK. The back end always does assignment
+ -- of misaligned small objects correctly.
+
+ if Known_Static_Component_Size (Ptyp)
+ and then Component_Size (Ptyp) <= 64
+ then
+ return False;
+
+ -- Otherwise, we need to test the prefix, to see if we are
+ -- indexing from a possibly unaligned component.
+
+ else
+ return Possible_Bit_Aligned_Component (P);
+ end if;
+ end;
+
+ -- Case of selected component
+
+ when N_Selected_Component =>
+ declare
+ P : constant Node_Id := Prefix (N);
+ Comp : constant Entity_Id := Entity (Selector_Name (N));
+
+ begin
+ -- If there is no component clause, then we are in the clear
+ -- since the back end will never misalign a large component
+ -- unless it is forced to do so. In the clear means we need
+ -- only the recursive test on the prefix.
+
+ if Component_May_Be_Bit_Aligned (Comp) then
+ return True;
+ else
+ return Possible_Bit_Aligned_Component (P);
+ 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.
+
+ when others =>
+ return False;
+
+ end case;
+ end Possible_Bit_Aligned_Component;
+
-------------------------
-- Remove_Side_Effects --
-------------------------
@@ -4171,6 +4324,17 @@ package body Exp_Util is
elsif Compile_Time_Known_Value (N) then
return True;
+
+ -- A variable renaming is not side-effet free, because the
+ -- renaming will function like a macro in the front-end in
+ -- some cases, and an assignment can modify the the component
+ -- designated by N, so we need to create a temporary for it.
+
+ elsif Is_Entity_Name (Original_Node (N))
+ and then Is_Renaming_Of_Object (Entity (Original_Node (N)))
+ and then Ekind (Entity (Original_Node (N))) /= E_Constant
+ then
+ return False;
end if;
-- For other than entity names and compile time known values,