aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/sem_ch5.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_ch5.adb')
-rw-r--r--gcc/ada/sem_ch5.adb119
1 files changed, 108 insertions, 11 deletions
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index e3aa50b..54d0a86 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_ch5.adb
@@ -101,13 +101,7 @@ package body Sem_Ch5 is
procedure Analyze_Assignment (N : Node_Id) is
Lhs : constant Node_Id := Name (N);
- Rhs : constant Node_Id := Expression (N);
-
- Decl : Node_Id;
- T1 : Entity_Id;
- T2 : Entity_Id;
-
- Save_Full_Analysis : Boolean := False; -- initialize to prevent warning
+ Rhs : Node_Id := Expression (N);
procedure Diagnose_Non_Variable_Lhs (N : Node_Id);
-- N is the node for the left hand side of an assignment, and it is not
@@ -126,6 +120,93 @@ package body Sem_Ch5 is
-- nominal subtype. This procedure is used to deal with cases where the
-- nominal subtype must be replaced by the actual subtype.
+ procedure Transform_BIP_Assignment (Typ : Entity_Id);
+ function Should_Transform_BIP_Assignment
+ (Typ : Entity_Id) return Boolean;
+ -- If the right-hand side of an assignment statement is a build-in-place
+ -- call we cannot build in place, so we insert a temp initialized with
+ -- the call, and transform the assignment statement to copy the temp.
+ -- Transform_BIP_Assignment does the tranformation, and
+ -- Should_Transform_BIP_Assignment determines whether we should.
+ -- The same goes for qualified expressions and conversions whose
+ -- operand is such a call.
+ --
+ -- This is only for nonlimited types; assignment statements are illegal
+ -- for limited types, but are generated internally for aggregates and
+ -- init procs. These limited-type are not really assignment statements
+ -- -- conceptually, they are initializations, so should not be
+ -- transformed.
+ --
+ -- Similarly, for nonlimited types, aggregates and init procs generate
+ -- assignment statements that are really initializations. These are
+ -- marked No_Ctrl_Actions.
+
+ function Should_Transform_BIP_Assignment
+ (Typ : Entity_Id) return Boolean
+ is
+ Result : Boolean;
+ begin
+ if Expander_Active
+ and then not Is_Limited_View (Typ)
+ and then Is_Build_In_Place_Result_Type (Typ)
+ and then not No_Ctrl_Actions (N)
+ then
+ -- This function is called early, before name resolution is
+ -- complete, so we have to deal with things that might turn into
+ -- function calls later. N_Function_Call and N_Op nodes are the
+ -- obvious case. An N_Identifier or N_Expanded_Name is a
+ -- parameterless function call if it denotes a function.
+ -- Finally, an attribute reference can be a function call.
+
+ case Nkind (Unqual_Conv (Rhs)) is
+ when N_Function_Call | N_Op =>
+ Result := True;
+ when N_Identifier | N_Expanded_Name =>
+ case Ekind (Entity (Unqual_Conv (Rhs))) is
+ when E_Function | E_Operator =>
+ Result := True;
+ when others =>
+ Result := False;
+ end case;
+ when N_Attribute_Reference =>
+ Result := Attribute_Name (Unqual_Conv (Rhs)) = Name_Input;
+ -- T'Input will turn into a call whose result type is T
+ when others =>
+ Result := False;
+ end case;
+ else
+ Result := False;
+ end if;
+ return Result;
+ end Should_Transform_BIP_Assignment;
+
+ procedure Transform_BIP_Assignment (Typ : Entity_Id) is
+ -- Tranform "X : [constant] T := F (...);" into:
+ --
+ -- Temp : constant T := F (...);
+ -- X := Temp;
+
+ Loc : constant Source_Ptr := Sloc (N);
+ Def_Id : constant Entity_Id := Make_Temporary (Loc, 'Y', Rhs);
+ Obj_Decl : constant Node_Id :=
+ Make_Object_Declaration
+ (Loc,
+ Defining_Identifier => Def_Id,
+ Constant_Present => True,
+ Object_Definition => New_Occurrence_Of (Typ, Loc),
+ Expression => Rhs,
+ Has_Init_Expression => True);
+ begin
+ Set_Etype (Def_Id, Typ);
+ Set_Expression (N, New_Occurrence_Of (Def_Id, Loc));
+
+ -- At this point, Rhs is no longer equal to Expression (N), so:
+
+ Rhs := Expression (N);
+
+ Insert_Action (N, Obj_Decl);
+ end Transform_BIP_Assignment;
+
-------------------------------
-- Diagnose_Non_Variable_Lhs --
-------------------------------
@@ -232,6 +313,7 @@ package body Sem_Ch5 is
(Opnd : Node_Id;
Opnd_Type : in out Entity_Id)
is
+ Decl : Node_Id;
begin
Require_Entity (Opnd);
@@ -284,6 +366,11 @@ package body Sem_Ch5 is
-- Local variables
+ T1 : Entity_Id;
+ T2 : Entity_Id;
+
+ Save_Full_Analysis : Boolean;
+
Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
-- Save the Ghost mode to restore on exit
@@ -360,8 +447,9 @@ package body Sem_Ch5 is
null;
elsif Has_Compatible_Type (Rhs, It.Typ) then
- if T1 /= Any_Type then
-
+ if T1 = Any_Type then
+ T1 := It.Typ;
+ else
-- An explicit dereference is overloaded if the prefix
-- is. Try to remove the ambiguity on the prefix, the
-- error will be posted there if the ambiguity is real.
@@ -412,8 +500,6 @@ package body Sem_Ch5 is
("ambiguous left-hand side in assignment", Lhs);
exit;
end if;
- else
- T1 := It.Typ;
end if;
end if;
@@ -429,6 +515,15 @@ package body Sem_Ch5 is
end if;
end if;
+ -- Deal with build-in-place calls for nonlimited types.
+ -- We don't do this later, because resolving the rhs
+ -- tranforms it incorrectly for build-in-place.
+
+ if Should_Transform_BIP_Assignment (Typ => T1) then
+ Transform_BIP_Assignment (Typ => T1);
+ end if;
+ pragma Assert (not Should_Transform_BIP_Assignment (Typ => T1));
+
-- The resulting assignment type is T1, so now we will resolve the left
-- hand side of the assignment using this determined type.
@@ -971,6 +1066,8 @@ package body Sem_Ch5 is
Expander_Mode_Restore;
Full_Analysis := Save_Full_Analysis;
end if;
+
+ pragma Assert (not Should_Transform_BIP_Assignment (Typ => T1));
end Analyze_Assignment;
-----------------------------