diff options
author | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-15 09:57:47 +0000 |
---|---|---|
committer | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-15 09:57:47 +0000 |
commit | 46f942b1635d1d2b5828d204c914e86d58d52082 (patch) | |
tree | 71361ae103915a536a466c140fbb0b0baa9c0e6d | |
parent | 555c63a669bf0ad0343938c048251c4cb11d7b80 (diff) | |
download | gcc-46f942b1635d1d2b5828d204c914e86d58d52082.tar.gz |
2009-04-15 Ed Schonberg <schonberg@adacore.com>
* sem_ch4.adb: improve error message on exponentiation.
2009-04-15 Hristian Kirtchev <kirtchev@adacore.com>
* a-calend.adb: Move constant Epoch_Offset from package
Conversion_Operations to top level.
(Delay_Operations.To_Duration): Define a constant which represents
"end of time" and use it as a guard against very distant delay dates.
Protect the code against overflow when performing the origin shift to
Unix time.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@146095 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ada/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/ada/a-calend.adb | 35 | ||||
-rw-r--r-- | gcc/ada/sem_ch4.adb | 14 |
3 files changed, 52 insertions, 10 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 0d4a01e24eb..b56f38f0a52 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,16 @@ +2009-04-15 Ed Schonberg <schonberg@adacore.com> + + * sem_ch4.adb: improve error message on exponentiation. + +2009-04-15 Hristian Kirtchev <kirtchev@adacore.com> + + * a-calend.adb: Move constant Epoch_Offset from package + Conversion_Operations to top level. + (Delay_Operations.To_Duration): Define a constant which represents + "end of time" and use it as a guard against very distant delay dates. + Protect the code against overflow when performing the origin shift to + Unix time. + 2009-04-15 Robert Dewar <dewar@adacore.com> * sem_prag.adb: Minor reformatting. diff --git a/gcc/ada/a-calend.adb b/gcc/ada/a-calend.adb index 67942a8ecd2..a2759b53a89 100644 --- a/gcc/ada/a-calend.adb +++ b/gcc/ada/a-calend.adb @@ -177,6 +177,10 @@ package body Ada.Calendar is Unix_Min : constant Time_Rep := Ada_Low + Time_Rep (17 * 366 + 52 * 365) * Nanos_In_Day; + Epoch_Offset : constant Time_Rep := (136 * 365 + 44 * 366) * Nanos_In_Day; + -- The difference between 2150-1-1 UTC and 1970-1-1 UTC expressed in + -- nanoseconds. Note that year 2100 is non-leap. + Cumulative_Days_Before_Month : constant array (Month_Number) of Natural := (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334); @@ -765,11 +769,6 @@ package body Ada.Calendar is package body Conversion_Operations is - Epoch_Offset : constant Time_Rep := - (136 * 365 + 44 * 366) * Nanos_In_Day; - -- The difference between 2150-1-1 UTC and 1970-1-1 UTC expressed in - -- nanoseconds. Note that year 2100 is non-leap. - ----------------- -- To_Ada_Time -- ----------------- @@ -972,6 +971,15 @@ package body Ada.Calendar is ----------------- function To_Duration (Date : Time) return Duration is + pragma Unsuppress (Overflow_Check); + + Safe_Ada_High : constant Time_Rep := Ada_High - Epoch_Offset; + -- This value represents a "safe" end of time. In order to perform a + -- proper conversion to Unix duration, we will have to shift origins + -- at one point. For very distant dates, this means an overflow check + -- failure. To prevent this, the function returns the "safe" end of + -- time (roughly 2219) which is still distant enough. + Elapsed_Leaps : Natural; Next_Leap_N : Time_Rep; Res_N : Time_Rep; @@ -979,8 +987,8 @@ package body Ada.Calendar is begin Res_N := Time_Rep (Date); - -- If the target supports leap seconds, remove any leap seconds - -- elapsed up to the input date. + -- Step 1: If the target supports leap seconds, remove any leap + -- seconds elapsed up to the input date. if Leap_Support then Cumulative_Leap_Seconds @@ -1000,10 +1008,17 @@ package body Ada.Calendar is Res_N := Res_N - Time_Rep (Elapsed_Leaps) * Nano; - -- Perform a shift in origins, note that enforcing type Time on - -- both operands will invoke Ada.Calendar."-". + -- Step 2: Perform a shift in origins to obtain a Unix equivalent of + -- the input. Guard against very large delay values such as the end + -- of time since the computation will overflow. + + if Res_N > Safe_Ada_High then + Res_N := Safe_Ada_High; + else + Res_N := Res_N + Epoch_Offset; + end if; - return Time (Res_N) - Time (Unix_Min); + return Time_Rep_To_Duration (Res_N); end To_Duration; end Delay_Operations; diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index e8199b5efeb..e9a20c5a70d 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -5213,6 +5213,20 @@ package body Sem_Ch4 is Error_Msg_N ("access parameter is not allowed to be null", L); Error_Msg_N ("\(call would raise Constraint_Error)", L); return; + + -- Another special case for exponentiation, where the right + -- operand must be Natural, independently of the base. + + elsif Nkind (N) = N_Op_Expon + and then Is_Numeric_Type (Etype (L)) + and then not Is_Overloaded (R) + and then + First_Subtype (Base_Type (Etype (R))) /= Standard_Integer + and then Base_Type (Etype (R)) /= Universal_Integer + then + Error_Msg_NE + ("exponent must be of type Natural, found}", R, Etype (R)); + return; end if; -- If we fall through then just give general message. Note that in |