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.