summaryrefslogtreecommitdiff
path: root/gcc/ada/exp_ch4.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/exp_ch4.adb')
-rw-r--r--gcc/ada/exp_ch4.adb153
1 files changed, 133 insertions, 20 deletions
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 22179e0b588..f8f2caa79b3 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -580,8 +580,7 @@ package body Exp_Ch4 is
-- Allocate the object with no expression
Node := Relocate_Node (N);
- Set_Expression (Node,
- New_Reference_To (Root_Type (Etype (Exp)), Loc));
+ Set_Expression (Node, New_Reference_To (Etype (Exp), Loc));
-- Avoid its expansion to avoid generating a call to the default
-- C++ constructor
@@ -615,7 +614,7 @@ package body Exp_Ch4 is
Id_Ref =>
Make_Explicit_Dereference (Loc,
Prefix => New_Reference_To (Temp, Loc)),
- Typ => Root_Type (Etype (Exp)),
+ Typ => Etype (Exp),
Constructor_Ref => Exp));
end;
@@ -3988,8 +3987,7 @@ package body Exp_Ch4 is
else pragma Assert (Expr_Value_E (Right) = Standard_False);
Remove_Side_Effects (Left);
- Rewrite
- (N, New_Occurrence_Of (Standard_False, Loc));
+ Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
end if;
end if;
@@ -4029,8 +4027,23 @@ package body Exp_Ch4 is
-- and replace the conditional expression by a reference to Cnn
+ -- ??? Note: this expansion is wrong for limited types, since it does
+ -- a copy of a limited value. The proper fix would be to do the
+ -- following expansion:
+
+ -- Cnn : access typ;
+ -- if cond then
+ -- <<then actions>>
+ -- Cnn := then-expr'Unrestricted_Access;
+ -- else
+ -- <<else actions>>
+ -- Cnn := else-expr'Unrestricted_Access;
+ -- end if;
+
+ -- and replace the conditional expresion by a reference to Cnn.all ???
+
if Present (Then_Actions (N)) or else Present (Else_Actions (N)) then
- Cnn := Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
+ Cnn := Make_Temporary (Loc, New_Internal_Name ('C'), N);
New_If :=
Make_Implicit_If_Statement (N,
@@ -4079,10 +4092,6 @@ package body Exp_Ch4 is
Insert_Action (N, New_If);
Analyze_And_Resolve (N, Typ);
-
- -- Link temporary to original expression, for Codepeer
-
- Set_Related_Expression (Cnn, Original_Node (N));
end if;
end Expand_N_Conditional_Expression;
@@ -4108,6 +4117,67 @@ package body Exp_Ch4 is
Rop : constant Node_Id := Right_Opnd (N);
Static : constant Boolean := Is_OK_Static_Expression (N);
+ procedure Expand_Set_Membership;
+ -- For each disjunct we create a simple equality or membership test.
+ -- The whole membership is rewritten as a short-circuit disjunction.
+
+ ---------------------------
+ -- Expand_Set_Membership --
+ ---------------------------
+
+ procedure Expand_Set_Membership is
+ Alt : Node_Id;
+ Res : Node_Id;
+
+ function Make_Cond (Alt : Node_Id) return Node_Id;
+ -- If the alternative is a subtype mark, create a simple membership
+ -- test. Otherwise create an equality test for it.
+
+ ---------------
+ -- Make_Cond --
+ ---------------
+
+ function Make_Cond (Alt : Node_Id) return Node_Id is
+ Cond : Node_Id;
+ L : constant Node_Id := New_Copy (Lop);
+ R : constant Node_Id := Relocate_Node (Alt);
+
+ begin
+ if Is_Entity_Name (Alt)
+ and then Is_Type (Entity (Alt))
+ then
+ Cond :=
+ Make_In (Sloc (Alt),
+ Left_Opnd => L,
+ Right_Opnd => R);
+ else
+ Cond := Make_Op_Eq (Sloc (Alt),
+ Left_Opnd => L,
+ Right_Opnd => R);
+ end if;
+
+ return Cond;
+ end Make_Cond;
+
+ -- Start of proessing for Expand_N_In
+
+ begin
+ Alt := Last (Alternatives (N));
+ Res := Make_Cond (Alt);
+
+ Prev (Alt);
+ while Present (Alt) loop
+ Res :=
+ Make_Or_Else (Sloc (Alt),
+ Left_Opnd => Make_Cond (Alt),
+ Right_Opnd => Res);
+ Prev (Alt);
+ end loop;
+
+ Rewrite (N, Res);
+ Analyze_And_Resolve (N, Standard_Boolean);
+ end Expand_Set_Membership;
+
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.
@@ -4133,6 +4203,13 @@ package body Exp_Ch4 is
-- Start of processing for Expand_N_In
begin
+
+ if Present (Alternatives (N)) then
+ Remove_Side_Effects (Lop);
+ Expand_Set_Membership;
+ return;
+ end if;
+
-- 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.
@@ -4720,6 +4797,10 @@ package body Exp_Ch4 is
Left_Opnd => Left_Opnd (N),
Right_Opnd => Right_Opnd (N))));
+ -- If this is a set membership, preserve list of alternatives
+
+ Set_Alternatives (Right_Opnd (N), Alternatives (Original_Node (N)));
+
-- We want this to appear as coming from source if original does (see
-- transformations in Expand_N_In).
@@ -7519,6 +7600,11 @@ package body Exp_Ch4 is
-- assignment to temporary. If there is no change of representation,
-- then the conversion node is unchanged.
+ procedure Raise_Accessibility_Error;
+ -- Called when we know that an accessibility check will fail. Rewrites
+ -- node N to an appropriate raise statement and outputs warning msgs.
+ -- The Etype of the raise node is set to Target_Type.
+
procedure Real_Range_Check;
-- Handles generation of range check for real target value
@@ -7648,6 +7734,22 @@ package body Exp_Ch4 is
end if;
end Handle_Changed_Representation;
+ -------------------------------
+ -- Raise_Accessibility_Error --
+ -------------------------------
+
+ procedure Raise_Accessibility_Error is
+ begin
+ Rewrite (N,
+ Make_Raise_Program_Error (Sloc (N),
+ Reason => PE_Accessibility_Check_Failed));
+ Set_Etype (N, Target_Type);
+
+ Error_Msg_N ("?accessibility check failure", N);
+ Error_Msg_NE
+ ("\?& will be raised at run time", N, Standard_Program_Error);
+ end Raise_Accessibility_Error;
+
----------------------
-- Real_Range_Check --
----------------------
@@ -7810,9 +7912,14 @@ package body Exp_Ch4 is
begin
-- Nothing at all to do if conversion is to the identical type so remove
- -- the conversion completely, it is useless.
+ -- the conversion completely, it is useless, except that it may carry
+ -- an Assignment_OK attribute, which must be propagated to the operand.
if Operand_Type = Target_Type then
+ if Assignment_OK (N) then
+ Set_Assignment_OK (Operand);
+ end if;
+
Rewrite (N, Relocate_Node (Operand));
return;
end if;
@@ -7884,10 +7991,7 @@ package body Exp_Ch4 is
and then Type_Access_Level (Operand_Type) >
Type_Access_Level (Target_Type)
then
- Rewrite (N,
- Make_Raise_Program_Error (Sloc (N),
- Reason => PE_Accessibility_Check_Failed));
- Set_Etype (N, Target_Type);
+ Raise_Accessibility_Error;
-- When the operand is a selected access discriminant the check needs
-- to be made against the level of the object denoted by the prefix
@@ -7901,11 +8005,7 @@ package body Exp_Ch4 is
and then Object_Access_Level (Operand) >
Type_Access_Level (Target_Type)
then
- Rewrite (N,
- Make_Raise_Program_Error (Sloc (N),
- Reason => PE_Accessibility_Check_Failed));
- Set_Etype (N, Target_Type);
-
+ Raise_Accessibility_Error;
return;
end if;
end if;
@@ -8407,6 +8507,19 @@ package body Exp_Ch4 is
Operand_Type : constant Entity_Id := Etype (Operand);
begin
+ -- Nothing at all to do if conversion is to the identical type so remove
+ -- the conversion completely, it is useless, except that it may carry
+ -- an Assignment_OK indication which must be proprgated to the operand.
+
+ if Operand_Type = Target_Type then
+ if Assignment_OK (N) then
+ Set_Assignment_OK (Operand);
+ end if;
+
+ Rewrite (N, Relocate_Node (Operand));
+ return;
+ end if;
+
-- If we have a conversion of a compile time known value to a target
-- type and the value is in range of the target type, then we can simply
-- replace the construct by an integer literal of the correct type. We