From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19141 invoked by alias); 11 Nov 2001 16:36:00 -0000 Mailing-List: contact gcc-prs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-prs-owner@gcc.gnu.org Received: (qmail 19127 invoked by uid 71); 11 Nov 2001 16:36:00 -0000 Date: Thu, 01 Nov 2001 03:37:00 -0000 Message-ID: <20011111163600.19126.qmail@sourceware.cygnus.com> To: nobody@gcc.gnu.org Cc: gcc-prs@gcc.gnu.org, From: Florian Weimer Subject: Re: ada/4851: GNAT crashs on certain argument lines Reply-To: Florian Weimer X-SW-Source: 2001-11/txt/msg00000.txt.bz2 List-Id: The following reply was made to PR ada/4851; it has been noted by GNATS. From: Florian Weimer 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 * 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;