https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62193
Bug ID: 62193
Summary: There is a bug in the Ada runtime which causes some
Ada time functions to fail on the MinGW 32-bit
platform .
Product: gcc
Version: 4.8.3
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: ada
Assignee: unassigned at gcc dot gnu.org
Reporter: [email protected]
Created attachment 33364
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33364&action=edit
A patch which corrects a problem that occurs in 32-bit Windows Ada when the
compiler is built with a C runtime with a 64-bit time_t type
There is a bug in the gcc Ada runtime which causes some routines
in the Ada.Calendar runtime package (and its child packages) to produce
incorrect results on the MinGW 32-bit Windows platform. I found the bug when
using the V4.8.1 MinGW Windows 32-bit, but it is a long-standing bug that still
exists in
later releases.
This can be demonstrated with the following Ada program when it
is compiled with the MinGW 32-bit 4.8.1 compiler:
with Ada.Calendar,
Ada.Text_IO;
use Ada.Calendar,
Ada.Text_IO;
procedure Simple_BugTest
is
Test_Date: Time;
YN: Year_number;
MN: Month_Number;
DN: Day_Number;
SN: Day_Duration;
ISN: Integer;
begin
Test_Date := Time_Of(2013, 10, 3);
Split(Test_Date, YN, MN, DN, SN);
ISN := Integer(SN);
Put_Line("Time_Of(2013, 10, 3) is ");
Put("Year:" & Integer'Image(YN));
Put(", Month:" & Integer'Image(MN));
Put(", Day:" & Integer'Image(DN));
Put_Line(", Seconds:" & Integer'Image(ISN));
end Simple_BugTest;
When compiled with the MinGW 4.8.1-4 Ada compiler, which uses
the MinGW 4.0.3-1 runtime package, this produces the following
incorrect output:
Time_Of(2013, 10, 3) is
Year: 2013, Month: 9, Day: 29, Seconds: 68327
When compiled with an Ada runtime patch which corrects the
problem, the output becomes:
Time_Of(2013, 10, 3) is
Year: 2013, Month: 10, Day: 3, Seconds: 0
which is correct.
The bug which causes the problem is in the Ada runtime library
source code, found in the gcc/ada subdirectory of the compiler
source. It is caused by an incorrect assumption about time
types which is embedded in the Ada and C source code files
in the gcc/ada subdirectory.
The Ada calendar routines define the Ada version of the time_t type as
type time_t is range
-(2 (Standard'Address_Size - Integer'(1))) ..
+(2 (Standard'Address_Size - Integer'(1)) - 1);
The key item here is the Ada expression
Standard'Address_Size
The MinGW Ada compiler is a 32-bit compiler.
The result is that the Ada time_t is a 32-bit
signed integer type. A value of this type is passed to the
C procedure __gnat_localtime_tzoff which is in a C file named
sysdep.c in the Ada runtime source code directory.
In the C code, the receiving argument of this Ada time_t type
is a C time_t type, the first argument of __gnat_localtime_tzoff,
declared as:
const time_t *timer
This is where the trouble starts. When the C time_t is a 64-bit
type, the value passed into __gnat_localtime_tzoff contains the
Ada time_t value as 32 bits of a 64-bit value, and the other 32
bits are nonsense.
In short, the Ada runtime library code is assuming that Ada
Standard'Address_Size and C sizeof(time_t) are always the same
value. The V4 release of the MinGW runtime has broken that assumption.
The patch works by defining a new time type for use in the
__gnat_localtime_tzoff function: ada_time_t.
This new type is based on the existing type intptr_t found in
<stdint.h> and is defined by the patch as
typedef intptr_t ada_time_t;
The offending time declaration is in the first argument of
__gnat_localtime_tzoff:
void
__gnat_localtime_tzoff (const time_t timer,
const int is_historic, long *off)
The patch corrects that to
void
__gnat_localtime_tzoff (const ada_time_t ada_timer,
const int is_historic, long *off)
The patch defines a new local variable in __gnat_localtime_tzoff:
time_t timer;
The local variable is then initialized:
timer = (time_t) *ada_timer;
This line is where the bug is actually fixed. The 32-bit Ada time
type is properly extended to a 64-bit type, but it would just be
a trivial copy when compiled by a 64-bit compiler.
The new local variable timer then replaces all instances of *timer
in the body of the function __gnat_localtime_tzoff.
Note that a patch like this would work on any 32-bit platform which
introduced a new 64-bit time_t type in its C runtime. That is why I
did not base ada_time_t on a Windows-specific type.
The patch is in the attachment.