From: Eric Botcazou <ebotcazou@adacore.com>
The problem is that we analyze references to an object before the actual
subtype of the object is established, thus creating a type mismatch that
is flagged by the code generator.
gcc/ada/ChangeLog:
* exp_ch7.ads (Store_After_Actions_In_Scope_Without_Analysis): New
procedure declaration.
* exp_ch7.adb (Store_New_Actions_In_Scope): New procedure.
(Store_Actions_In_Scope): Call Store_New_Actions_In_Scope when the
target list is empty.
(Store_After_Actions_In_Scope_Without_Analysis): New procedure body.
* exp_aggr.adb (Expand_Container_Aggregate): For a declaration that
is wrapped in a transient scope, also defer the analysis of the new
code until after the declaration is analyzed.
Tested on x86_64-pc-linux-gnu, committed on master.
---
gcc/ada/exp_aggr.adb | 9 +++----
gcc/ada/exp_ch7.adb | 56 +++++++++++++++++++++++++++++++++++++-------
gcc/ada/exp_ch7.ads | 7 ++++--
3 files changed, 57 insertions(+), 15 deletions(-)
@@ -7345,12 +7345,13 @@ package body Exp_Aggr is
-- If a transient scope has been created around the declaration, we
-- need to attach the code to it so that the finalization actions of
- -- the declaration will be inserted after it. Otherwise, we directly
- -- insert it after the declaration and it will be analyzed only once
- -- the declaration is processed.
+ -- the declaration will be inserted after it; otherwise, we directly
+ -- insert it after the declaration. In both cases, the code will be
+ -- analyzed after the declaration is processed, i.e. once the actual
+ -- subtype of the object is established.
if Scope_Is_Transient and then Par = Node_To_Be_Wrapped then
- Insert_Actions_After (Par, Aggr_Code);
+ Store_After_Actions_In_Scope_Without_Analysis (Aggr_Code);
else
Insert_List_After (Par, Aggr_Code);
end if;
@@ -514,7 +514,13 @@ package body Exp_Ch7 is
-- cleanup actions are performed at the end of the block.
procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id);
- -- Shared processing for Store_xxx_Actions_In_Scope
+ -- Shared processing for the Store_xxx_Actions_In_Scope routines: attach
+ -- the list L of actions to the list of actions stored in the top of the
+ -- scope stack specified by AK.
+
+ procedure Store_New_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id);
+ -- Same as above for the case where the list of actions stored in the top
+ -- of the scope stack specified by AK is empty.
-------------------------------------------
-- Unnesting procedures for CCG and LLVM --
@@ -8907,14 +8913,7 @@ package body Exp_Ch7 is
begin
if Is_Empty_List (Actions) then
- Actions := L;
-
- if Is_List_Member (SE.Node_To_Be_Wrapped) then
- Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
- else
- Set_Parent (L, SE.Node_To_Be_Wrapped);
- end if;
-
+ Store_New_Actions_In_Scope (AK, L);
Analyze_List (L);
elsif AK = Before then
@@ -8934,6 +8933,22 @@ package body Exp_Ch7 is
Store_Actions_In_Scope (After, L);
end Store_After_Actions_In_Scope;
+ ---------------------------------------------------
+ -- Store_After_Actions_In_Scope_Without_Analysis --
+ ---------------------------------------------------
+
+ procedure Store_After_Actions_In_Scope_Without_Analysis (L : List_Id) is
+ SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
+ Actions : List_Id renames SE.Actions_To_Be_Wrapped (After);
+
+ begin
+ if Is_Empty_List (Actions) then
+ Store_New_Actions_In_Scope (After, L);
+ else
+ Insert_List_Before (First (Actions), L);
+ end if;
+ end Store_After_Actions_In_Scope_Without_Analysis;
+
-----------------------------------
-- Store_Before_Actions_In_Scope --
-----------------------------------
@@ -8952,6 +8967,29 @@ package body Exp_Ch7 is
Store_Actions_In_Scope (Cleanup, L);
end Store_Cleanup_Actions_In_Scope;
+ --------------------------------
+ -- Store_New_Actions_In_Scope --
+ --------------------------------
+
+ procedure Store_New_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id)
+ is
+ SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
+ Actions : List_Id renames SE.Actions_To_Be_Wrapped (AK);
+
+ begin
+ pragma Assert (Is_Empty_List (Actions));
+
+ Actions := L;
+
+ -- Set the Parent link to provide the context for the actions
+
+ if Is_List_Member (SE.Node_To_Be_Wrapped) then
+ Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
+ else
+ Set_Parent (L, SE.Node_To_Be_Wrapped);
+ end if;
+ end Store_New_Actions_In_Scope;
+
------------------
-- Unnest_Block --
------------------
@@ -311,7 +311,7 @@ package Exp_Ch7 is
-- Return the node to be wrapped if the current scope is transient
procedure Store_Before_Actions_In_Scope (L : List_Id);
- -- Append the list L of actions to the end of the before-actions store in
+ -- Append the list L of actions to the end of the before-actions stored in
-- the top of the scope stack (also analyzes these actions).
procedure Store_After_Actions_In_Scope (L : List_Id);
@@ -324,9 +324,12 @@ package Exp_Ch7 is
-- last call executed first). Within the list L for a single call, the
-- actions are executed in the order in which they appear in this list.
+ procedure Store_After_Actions_In_Scope_Without_Analysis (L : List_Id);
+ -- Same as above, but without analyzing the actions
+
procedure Store_Cleanup_Actions_In_Scope (L : List_Id);
-- Prepend the list L of actions to the beginning of the cleanup-actions
- -- store in the top of the scope stack.
+ -- stored in the top of the scope stack.
procedure Wrap_Transient_Declaration (N : Node_Id);
-- N is an object declaration. Expand the finalization calls after the