This is the mail archive of the
gcc-prs@gcc.gnu.org
mailing list for the GCC project.
Re: ada/4851: GNAT crashs on certain argument lines
- To: nobody at gcc dot gnu dot org
- Subject: Re: ada/4851: GNAT crashs on certain argument lines
- From: Florian Weimer <fw at deneb dot enyo dot de>
- Date: 11 Nov 2001 16:36:00 -0000
- Cc: gcc-prs at gcc dot gnu dot org,
- Reply-to: Florian Weimer <fw at deneb dot enyo dot de>
The following reply was made to PR ada/4851; it has been noted by GNATS.
From: Florian Weimer <fw@deneb.enyo.de>
To: dstarner98@aasaa.ofe.org
Cc: gcc-gnats@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: Re: ada/4851: GNAT crashs on certain argument lines
Date: Sun, 11 Nov 2001 17:56:52 +0100
dstarner98@aasaa.ofe.org writes:
> gnatmake -gnatwa -gnatwu -gnatwl -gnatwc -gnatf -gnato -gnatm40 -gnatG -gnatD -fprofile-arcs -ftest-coverage -O2 -gnata -gnatiw -gnatW8 -g -fprofile-arcs -ftest-coverage -gnaty3acefiklM100nprst program.adb
> ~/Code/Ngeadal/source/bug $ ./file
> Exception name: STORAGE_ERROR
> Message: stack overflow (or erroneous memory access)
Here's the fix.
The problem is caused by the fact that a call to an instantiation of
Generic_Position can change T.Table as a side effect (if a
reallocation is necessary due to table growth). Since the prefix and
the indexed_compound in the assignment statements below are evaluated
in arbitrary order, the prefix might be the old value of T.Table,
leading to erroneous execution and the erratic behavior observed by
David Starner.
The old comment suggests that Generic_Position once was a procedure.
I wonder who changed it and why. ;-) (The bug is present in the GNAT
3.13p sources as well, but it might not show up because of code
generation differences.)
2001-11-11 Florian Weimer <fw@deneb.enyo.de>
* make.adb (Add_Switch): Make Generic_Position a procedure.
The function approach did not work well because of a side
effect (the function call could reallocate the table which was
being indexed using its result).
Index: make.adb
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ada/make.adb,v
retrieving revision 1.2
diff -c -p -3 -r1.2 make.adb
*** make.adb 2001/10/11 01:02:02 1.2
--- make.adb 2001/11/11 16:02:20
*************** package body Make is
*** 526,580 ****
is
generic
with package T is new Table.Table (<>);
! function Generic_Position return Integer;
! -- Generic procedure that adds S at the end or beginning of T depending
! -- of the value of the boolean Append_Switch.
----------------------
-- Generic_Position --
----------------------
! function Generic_Position return Integer is
begin
T.Increment_Last;
if Append_Switch then
! return Integer (T.Last);
else
for J in reverse T.Table_Index_Type'Succ (T.First) .. T.Last loop
T.Table (J) := T.Table (T.Table_Index_Type'Pred (J));
end loop;
! return Integer (T.First);
end if;
end Generic_Position;
! function Gcc_Switches_Pos is new Generic_Position (Gcc_Switches);
! function Binder_Switches_Pos is new Generic_Position (Binder_Switches);
! function Linker_Switches_Pos is new Generic_Position (Linker_Switches);
! function Saved_Gcc_Switches_Pos is new
Generic_Position (Saved_Gcc_Switches);
! function Saved_Binder_Switches_Pos is new
Generic_Position (Saved_Binder_Switches);
! function Saved_Linker_Switches_Pos is new
Generic_Position (Saved_Linker_Switches);
-- Start of processing for Add_Switch
begin
if And_Save then
case Program is
when Compiler =>
! Saved_Gcc_Switches.Table (Saved_Gcc_Switches_Pos) := S;
when Binder =>
! Saved_Binder_Switches.Table (Saved_Binder_Switches_Pos) := S;
when Linker =>
! Saved_Linker_Switches.Table (Saved_Linker_Switches_Pos) := S;
when None =>
raise Program_Error;
--- 526,586 ----
is
generic
with package T is new Table.Table (<>);
! procedure Generic_Position (New_Position : out Integer);
! -- Generic procedure that chooses a position for S in T at the
! -- beginning or the end, depending on the boolean Append_Switch.
+
----------------------
-- Generic_Position --
----------------------
! procedure Generic_Position (New_Position : out Integer) is
begin
T.Increment_Last;
if Append_Switch then
! New_Position := Integer (T.Last);
else
for J in reverse T.Table_Index_Type'Succ (T.First) .. T.Last loop
T.Table (J) := T.Table (T.Table_Index_Type'Pred (J));
end loop;
! New_Position := Integer (T.First);
end if;
end Generic_Position;
! procedure Gcc_Switches_Pos is new Generic_Position (Gcc_Switches);
! procedure Binder_Switches_Pos is new Generic_Position (Binder_Switches);
! procedure Linker_Switches_Pos is new Generic_Position (Linker_Switches);
! procedure Saved_Gcc_Switches_Pos is new
Generic_Position (Saved_Gcc_Switches);
! procedure Saved_Binder_Switches_Pos is new
Generic_Position (Saved_Binder_Switches);
! procedure Saved_Linker_Switches_Pos is new
Generic_Position (Saved_Linker_Switches);
+ New_Position : Integer;
+
-- Start of processing for Add_Switch
begin
if And_Save then
case Program is
when Compiler =>
! Saved_Gcc_Switches_Pos (New_Position);
! Saved_Gcc_Switches.Table (New_Position) := S;
when Binder =>
! Saved_Binder_Switches_Pos (New_Position);
! Saved_Binder_Switches.Table (New_Position) := S;
when Linker =>
! Saved_Linker_Switches_Pos (New_Position);
! Saved_Linker_Switches.Table (New_Position) := S;
when None =>
raise Program_Error;
*************** package body Make is
*** 583,595 ****
else
case Program is
when Compiler =>
! Gcc_Switches.Table (Gcc_Switches_Pos) := S;
when Binder =>
! Binder_Switches.Table (Binder_Switches_Pos) := S;
when Linker =>
! Linker_Switches.Table (Linker_Switches_Pos) := S;
when None =>
raise Program_Error;
--- 589,604 ----
else
case Program is
when Compiler =>
! Gcc_Switches_Pos (New_Position);
! Gcc_Switches.Table (New_Position) := S;
when Binder =>
! Binder_Switches_Pos (New_Position);
! Binder_Switches.Table (New_Position) := S;
when Linker =>
! Linker_Switches_Pos (New_Position);
! Linker_Switches.Table (New_Position) := S;
when None =>
raise Program_Error;