aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJavier Miranda <miranda@adacore.com>2018-07-17 08:07:00 +0000
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>2018-07-17 08:07:00 +0000
commit01bd58f51858c375e5814e3937aa2c57fbbc9bdc (patch)
tree741aaee4e5d6357b48cea2a1c04482a60ed4a523
parent3567ca3f6be029d5a68722b675df74c2c6945854 (diff)
downloadgcc-01bd58f51858c375e5814e3937aa2c57fbbc9bdc.zip
gcc-01bd58f51858c375e5814e3937aa2c57fbbc9bdc.tar.gz
gcc-01bd58f51858c375e5814e3937aa2c57fbbc9bdc.tar.bz2
[Ada] Secondary stack leak in statements block located in a loop
When a loop iterator has a block declaration containing statements that invoke functions whose result is returned on the secondary stack (such as a string-returning function), the compiler fails to generate code to release the allocated memory when the loop terminates. After this patch the following test works fine. with Ada.Text_IO; use Ada.Text_IO; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; pragma Warnings (Off); with System.Secondary_Stack; pragma Warnings (On); procedure Small is procedure Info is new System.Secondary_Stack.Ss_Info (Put_Line); US : Unbounded_String; begin Info; for J in 1 .. 100_000 loop Leaky_Block : declare begin if (J mod 20000) = 0 then Info; end if; Ada.Text_IO.Put_Line (To_String (US)); -- Test if (J mod 20000) = 0 then Info; end if; end Leaky_Block; end loop; Info; end; Command: gnatmake small.adb; small | grep "Current allocated space :" | uniq Output: Current allocated space : 0 bytes 2018-07-17 Javier Miranda <miranda@adacore.com> gcc/ada/ * exp_ch7.adb (Make_Transient_Block): When determining whether an enclosing scope already handles the secondary stack, take into account transient blocks nested in a block that do not manage the secondary stack and are located within a loop. From-SVN: r262779
-rw-r--r--gcc/ada/ChangeLog7
-rw-r--r--gcc/ada/exp_ch7.adb34
2 files changed, 41 insertions, 0 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 4f747f2..af38e50 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,10 @@
+2018-07-17 Javier Miranda <miranda@adacore.com>
+
+ * exp_ch7.adb (Make_Transient_Block): When determining whether an
+ enclosing scope already handles the secondary stack, take into account
+ transient blocks nested in a block that do not manage the secondary
+ stack and are located within a loop.
+
2018-07-17 Ed Schonberg <schonberg@adacore.com>
* sem_util.adb (Enclosing_Subprogram): Protected entries and task
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index 2f3092d9..781456f 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -8695,9 +8695,33 @@ package body Exp_Ch7 is
Action : Node_Id;
Par : Node_Id) return Node_Id
is
+ function Within_Loop_Statement (N : Node_Id) return Boolean;
+ -- Return True when N appears within a loop and no block is containing N
+
function Manages_Sec_Stack (Id : Entity_Id) return Boolean;
-- Determine whether scoping entity Id manages the secondary stack
+ ---------------------------
+ -- Within_Loop_Statement --
+ ---------------------------
+
+ function Within_Loop_Statement (N : Node_Id) return Boolean is
+ Par : Node_Id := Parent (N);
+
+ begin
+ while not (Nkind_In (Par,
+ N_Loop_Statement,
+ N_Handled_Sequence_Of_Statements,
+ N_Package_Specification)
+ or else Nkind (Par) in N_Proper_Body)
+ loop
+ pragma Assert (Present (Par));
+ Par := Parent (Par);
+ end loop;
+
+ return Nkind (Par) = N_Loop_Statement;
+ end Within_Loop_Statement;
+
-----------------------
-- Manages_Sec_Stack --
-----------------------
@@ -8780,6 +8804,16 @@ package body Exp_Ch7 is
elsif Ekind (Scop) = E_Loop then
exit;
+ -- Ditto when the block appears without a block that does not
+ -- manage the secondary stack and is located within a loop.
+
+ elsif Ekind (Scop) = E_Block
+ and then not Manages_Sec_Stack (Scop)
+ and then Present (Block_Node (Scop))
+ and then Within_Loop_Statement (Block_Node (Scop))
+ then
+ exit;
+
-- The transient block does not need to manage the secondary stack
-- when there is an enclosing construct which already does that.
-- This optimization saves on SS_Mark and SS_Release calls but may