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: jdgress...@amli-denton.com

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.

Reply via email to