[Ada] Crash on case expression in build-in-place function
authorHristian Kirtchev <kirtchev@adacore.com>
Tue, 17 Jul 2018 08:03:44 +0000 (08:03 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Tue, 17 Jul 2018 08:03:44 +0000 (08:03 +0000)
This patch modifies the recursive tree replication routine New_Copy_Tree to
create new entities and remap old entities to the new ones for constructs in
N_Expression_With_Actions nodes when requested by a caller. This in turn allows
the build-in-place mechanism to avoid sharing entities between the 4 variants
of returns it generates.

2018-07-17  Hristian Kirtchev  <kirtchev@adacore.com>

gcc/ada/

* exp_ch6.adb (Build_Heap_Or_Pool_Allocator): Ensure that scoping
constructs and entities within receive new entities when replicating a
tree.
(Expand_N_Extended_Return_Statement): Ensure that scoping constructs
and entities within receive new entities when replicating a tree.
* sem_util.adb (New_Copy_Tree): Add new formal Scopes_In_EWA_OK.
(Visit_Entity): Visit entities within scoping constructs inside
expression with actions nodes when requested by the caller. Add blocks,
labels, and procedures to the list of entities which need replication.
* sem_util.ads (New_Copy_Tree): Add new formal Scopes_In_EWA_OK. Update
the comment on usage.

gcc/testsuite/

* gnat.dg/bip_case_expr.adb, gnat.dg/bip_case_expr_pkg.ads: New testcase.

From-SVN: r262766

gcc/ada/ChangeLog
gcc/ada/exp_ch6.adb
gcc/ada/sem_util.adb
gcc/ada/sem_util.ads
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/bip_case_expr.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/bip_case_expr_pkg.ads [new file with mode: 0644]

index 4e7eba7da0f97e9e1e2c5c3bd5c96be3ab28472f..d6cf6e78a88be19bd4027fcae285d6d2a0b8076e 100644 (file)
@@ -1,3 +1,17 @@
+2018-07-17  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * exp_ch6.adb (Build_Heap_Or_Pool_Allocator): Ensure that scoping
+       constructs and entities within receive new entities when replicating a
+       tree.
+       (Expand_N_Extended_Return_Statement): Ensure that scoping constructs
+       and entities within receive new entities when replicating a tree.
+       * sem_util.adb (New_Copy_Tree): Add new formal Scopes_In_EWA_OK.
+       (Visit_Entity): Visit entities within scoping constructs inside
+       expression with actions nodes when requested by the caller. Add blocks,
+       labels, and procedures to the list of entities which need replication.
+       * sem_util.ads (New_Copy_Tree): Add new formal Scopes_In_EWA_OK. Update
+       the comment on usage.
+
 2018-07-17  Arnaud Charlet  <charlet@adacore.com>
 
        * doc/gnat_ugn/about_this_guide.rst,
index 9ddf0fa038199cb39fdba3ed4d9a12afc70498f4..ef6406d203eebfe74f10fb0d41f04a6e1842d808 100644 (file)
@@ -4562,7 +4562,10 @@ package body Exp_Ch6 is
                Fin_Mas_Id : constant Entity_Id :=
                               Build_In_Place_Formal
                                 (Func_Id, BIP_Finalization_Master);
-               Orig_Expr  : constant Node_Id := New_Copy_Tree (Alloc_Expr);
+               Orig_Expr  : constant Node_Id :=
+                              New_Copy_Tree
+                                (Source           => Alloc_Expr,
+                                 Scopes_In_EWA_OK => True);
                Stmts      : constant List_Id := New_List;
                Desig_Typ  : Entity_Id;
                Local_Id   : Entity_Id;
@@ -5022,7 +5025,10 @@ package body Exp_Ch6 is
                   Init_Assignment :=
                     Make_Assignment_Statement (Loc,
                       Name       => New_Occurrence_Of (Ret_Obj_Id, Loc),
-                      Expression => New_Copy_Tree (Ret_Obj_Expr));
+                      Expression =>
+                        New_Copy_Tree
+                          (Source           => Ret_Obj_Expr,
+                           Scopes_In_EWA_OK => True));
 
                   Set_Etype (Name (Init_Assignment), Etype (Ret_Obj_Id));
                   Set_Assignment_OK (Name (Init_Assignment));
@@ -5153,7 +5159,10 @@ package body Exp_Ch6 is
                                 Subtype_Mark =>
                                   New_Occurrence_Of
                                     (Etype (Ret_Obj_Expr), Loc),
-                                Expression   => New_Copy_Tree (Ret_Obj_Expr)));
+                                Expression   =>
+                                  New_Copy_Tree
+                                    (Source           => Ret_Obj_Expr,
+                                     Scopes_In_EWA_OK => True)));
 
                      else
                         --  If the function returns a class-wide type we cannot
@@ -5193,7 +5202,11 @@ package body Exp_Ch6 is
                      --  except we set Storage_Pool and Procedure_To_Call so
                      --  it will use the user-defined storage pool.
 
-                     Pool_Allocator := New_Copy_Tree (Heap_Allocator);
+                     Pool_Allocator :=
+                       New_Copy_Tree
+                         (Source           => Heap_Allocator,
+                          Scopes_In_EWA_OK => True);
+
                      pragma Assert (Alloc_For_BIP_Return (Pool_Allocator));
 
                      --  Do not generate the renaming of the build-in-place
@@ -5235,7 +5248,11 @@ package body Exp_Ch6 is
                      --  allocation.
 
                      else
-                        SS_Allocator := New_Copy_Tree (Heap_Allocator);
+                        SS_Allocator :=
+                          New_Copy_Tree
+                            (Source           => Heap_Allocator,
+                             Scopes_In_EWA_OK => True);
+
                         pragma Assert (Alloc_For_BIP_Return (SS_Allocator));
 
                         --  The heap and pool allocators are marked as
index 1c3610c3251eab37893f9261f90e0bcb25ee7bd8..c8c914a093b4c0e1ada872c4454a365cc8eeab87 100644 (file)
@@ -19505,10 +19505,11 @@ package body Sem_Util is
    -------------------
 
    function New_Copy_Tree
-     (Source    : Node_Id;
-      Map       : Elist_Id   := No_Elist;
-      New_Sloc  : Source_Ptr := No_Location;
-      New_Scope : Entity_Id  := Empty) return Node_Id
+     (Source           : Node_Id;
+      Map              : Elist_Id   := No_Elist;
+      New_Sloc         : Source_Ptr := No_Location;
+      New_Scope        : Entity_Id  := Empty;
+      Scopes_In_EWA_OK : Boolean    := False) return Node_Id
    is
       --  This routine performs low-level tree manipulations and needs access
       --  to the internals of the tree.
@@ -20430,34 +20431,44 @@ package body Sem_Util is
          pragma Assert (Nkind (Id) in N_Entity);
          pragma Assert (not Is_Itype (Id));
 
-         --  Nothing to do if the entity is not defined in the Actions list of
-         --  an N_Expression_With_Actions node.
+         --  Nothing to do when the entity is not defined in the Actions list
+         --  of an N_Expression_With_Actions node.
 
          if EWA_Level = 0 then
             return;
 
-         --  Nothing to do if the entity is defined within a scoping construct
-         --  of an N_Expression_With_Actions node.
+         --  Nothing to do when the entity is defined in a scoping construct
+         --  within an N_Expression_With_Actions node, unless the caller has
+         --  requested their replication.
 
-         elsif EWA_Inner_Scope_Level > 0 then
+         --  ??? should this restriction be eliminated?
+
+         elsif EWA_Inner_Scope_Level > 0 and then not Scopes_In_EWA_OK then
             return;
 
-         --  Nothing to do if the entity is not an object or a type. Relaxing
+         --  Nothing to do when the entity does not denote a construct that
+         --  may appear within an N_Expression_With_Actions node. Relaxing
          --  this restriction leads to a performance penalty.
 
-         elsif not Ekind_In (Id, E_Constant, E_Variable)
+         --  ??? this list is flaky, and may hide dormant bugs
+
+         elsif not Ekind_In (Id, E_Block,
+                                 E_Constant,
+                                 E_Label,
+                                 E_Procedure,
+                                 E_Variable)
            and then not Is_Type (Id)
          then
             return;
 
-         --  Nothing to do if the entity was already visited
+         --  Nothing to do when the entity was already visited
 
          elsif NCT_Tables_In_Use
            and then Present (NCT_New_Entities.Get (Id))
          then
             return;
 
-         --  Nothing to do if the declaration node of the entity is not within
+         --  Nothing to do when the declaration node of the entity is not in
          --  the subtree being replicated.
 
          elsif not In_Subtree
index 9bff3ba92cf34c4eae2e81dd551f4a993b6d5765..34d618e6400b8b740eea507126bcc662fa59a3a5 100644 (file)
@@ -872,7 +872,7 @@ package Sem_Util is
       Placement : out State_Space_Kind;
       Pack_Id   : out Entity_Id);
    --  Determine the state space placement of an item. Item_Id denotes the
-   --  entity of an abstract state, object or package instantiation. Placement
+   --  entity of an abstract state, object, or package instantiation. Placement
    --  captures the precise placement of the item in the enclosing state space.
    --  If the state space is that of a package, Pack_Id denotes its entity,
    --  otherwise Pack_Id is Empty.
@@ -2240,10 +2240,11 @@ package Sem_Util is
    --  nodes (entities) either directly or indirectly using this function.
 
    function New_Copy_Tree
-     (Source    : Node_Id;
-      Map       : Elist_Id   := No_Elist;
-      New_Sloc  : Source_Ptr := No_Location;
-      New_Scope : Entity_Id  := Empty) return Node_Id;
+     (Source           : Node_Id;
+      Map              : Elist_Id   := No_Elist;
+      New_Sloc         : Source_Ptr := No_Location;
+      New_Scope        : Entity_Id  := Empty;
+      Scopes_In_EWA_OK : Boolean    := False) return Node_Id;
    --  Perform a deep copy of the subtree rooted at Source. Entities, itypes,
    --  and nodes are handled separately as follows:
    --
@@ -2313,6 +2314,10 @@ package Sem_Util is
    --
    --  Parameter New_Scope may be used to specify a new scope for all copied
    --  entities and itypes.
+   --
+   --  Parameter Scopes_In_EWA_OK may be used to force the replication of both
+   --  scoping entities and non-scoping entities found within expression with
+   --  actions nodes.
 
    function New_External_Entity
      (Kind         : Entity_Kind;
index a6cd3c80d1ac435c7c91d20fd4b680b867e2790c..c801b103c82b94b8c0fa4e382885f7d507cf9dda 100644 (file)
@@ -1,3 +1,7 @@
+2018-07-17  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * gnat.dg/bip_case_expr.adb, gnat.dg/bip_case_expr_pkg.ads: New testcase.
+
 2018-07-16  Carl Love  <cel@us.ibm.com>
 
        PR target/86414
diff --git a/gcc/testsuite/gnat.dg/bip_case_expr.adb b/gcc/testsuite/gnat.dg/bip_case_expr.adb
new file mode 100644 (file)
index 0000000..6e8a687
--- /dev/null
@@ -0,0 +1,15 @@
+--  { dg-do compile }
+
+with BIP_Case_Expr_Pkg; use BIP_Case_Expr_Pkg;
+
+procedure BIP_Case_Expr is
+   function Make_Any_Lim_Ctrl (Flag : Boolean) return Lim_Ctrl is
+   begin
+      return (case Flag is
+                 when True  => Make_Lim_Ctrl,
+                 when False => Make_Lim_Ctrl);
+   end;
+
+   Res : Lim_Ctrl := Make_Any_Lim_Ctrl (True);
+
+begin null; end BIP_Case_Expr;
diff --git a/gcc/testsuite/gnat.dg/bip_case_expr_pkg.ads b/gcc/testsuite/gnat.dg/bip_case_expr_pkg.ads
new file mode 100644 (file)
index 0000000..3fb0009
--- /dev/null
@@ -0,0 +1,7 @@
+with Ada.Finalization; use Ada.Finalization;
+
+package BIP_Case_Expr_Pkg is
+   type Lim_Ctrl is new Limited_Controlled with null record;
+
+   function Make_Lim_Ctrl return Lim_Ctrl;
+end BIP_Case_Expr_Pkg;