This patch removes a spurious discriminant check on an generated assignment
statement in an iterator loop, when the cursor type is a type with unknown
discriminants, when the full view has discriminants with defaults.
Executing:
gnatmake -f -q -g date_iteration_test.adb
date_iteration_test
Must yield:
1
2
3
4
5
6
7
8
9
10
2015-12-31 05:00:00
2016-01-01 05:00:00
2016-01-02 05:00:00
2016-01-03 05:00:00
2016-01-04 05:00:00
2016-01-05 05:00:00
2016-01-06 05:00:00
2016-01-07 05:00:00
2016-01-08 05:00:00
2016-01-09 05:00:00
2016-01-10 05:00:00
---
with Date_Iteration;
with Ada.Calendar.Formatting;
with Ada.Text_IO; use Ada.Text_IO;
procedure Date_Iteration_Test is
use type Ada.Calendar.Time;
Day : constant Duration := 86_400.0;
Number : Natural := 0;
begin
for D in Date_Iteration.Generator
(Start_Time => Ada.Calendar.Clock,
End_Time => Ada.Calendar.Clock + Day * 10)
loop
Number := Number + 1;
Put_Line (Number'Img);
end loop;
New_Line;
for D of Date_Iteration.Generator
(Start_Time => Ada.Calendar.Time_Of (2015, 12, 31),
End_Time => Ada.Calendar.Time_Of (2015, 12, 31) + Day * 10)
loop
Put_Line (Ada.Calendar.Formatting.Image (D));
end loop;
end Date_Iteration_Test;
---
with Ada.Calendar;
with Ada.Iterator_Interfaces;
package Date_Iteration is
type Cursor (<>) is private;
function Has_Element (C : Cursor) return Boolean;
function Date (C : Cursor) return Ada.Calendar.Time;
package Iterator_Interfaces
is new Ada.Iterator_Interfaces (Cursor, Has_Element);
type Date_Set is new Iterator_Interfaces.Forward_Iterator with private
with
Constant_Indexing => Element,
Default_Iterator => Iterate,
Iterator_Element => Ada.Calendar.Time;
function Element (Set : Date_Set; C : Cursor) return Ada.Calendar.Time;
function Iterate (Set : Date_Set)
return Iterator_Interfaces.Forward_Iterator'Class;
function Generator (Start_Time : Ada.Calendar.Time;
End_Time : Ada.Calendar.Time;
Interval : Duration := 86_400.0)
return Date_Set;
private
type Cursor (Valid : Boolean := True) is record
case Valid is
when True =>
Date : Ada.Calendar.Time;
when False =>
null;
end case;
end record;
function Has_Element (C : Cursor) return Boolean is (C.Valid);
function Date (C : Cursor) return Ada.Calendar.Time is (C.Date);
type Date_Set is new Iterator_Interfaces.Forward_Iterator with record
Start_Time : Ada.Calendar.Time;
End_Time : Ada.Calendar.Time;
Interval : Duration;
end record;
overriding
function First (Object : Date_Set) return Cursor;
overriding
function Next (Object : Date_Set; Position : Cursor) return Cursor;
function Element (Set : Date_Set; C : Cursor) return Ada.Calendar.Time
is (C.Date);
function Iterate (Set : Date_Set)
return Iterator_Interfaces.Forward_Iterator'Class
is (Set);
end Date_Iteration;
---
package body Date_Iteration is
function Generator (Start_Time : Ada.Calendar.Time;
End_Time : Ada.Calendar.Time;
Interval : Duration := 86_400.0)
return Date_Set is
begin
return D : Date_Set do
D := (Start_Time => Start_Time,
End_Time => End_Time,
Interval => Interval);
end return;
end Generator;
function First (Object : Date_Set) return Cursor is
use type Ada.Calendar.Time;
begin
if Object.End_Time >= Object.Start_Time then
return (Valid => True, Date => Object.Start_Time);
else
return (Valid => False);
end if;
end First;
function Next (Object : Date_Set; Position : Cursor)
return Cursor is
use type Ada.Calendar.Time;
Next : Ada.Calendar.Time := Position.Date + Object.Interval;
begin
if Next > Object.End_Time then
return (Valid => False);
else
return (Valid => True, Date => Next);
end if;
end Next;
end Date_Iteration;
Tested on x86_64-pc-linux-gnu, committed on trunk
2016-04-20 Ed Schonberg <[email protected]>
* exp_ch5.adb (Expand_N_Assignment_Statement): Do no generate
a discriminant check for a type whose partial view has unknown
discriminants when the full view has discriminants with defaults.
Index: exp_ch5.adb
===================================================================
--- exp_ch5.adb (revision 235265)
+++ exp_ch5.adb (working copy)
@@ -1946,10 +1946,12 @@
-- have a full view with discriminants, but those are nameable only
-- in the underlying type, so convert the Rhs to it before potential
-- checking. Convert Lhs as well, otherwise the actual subtype might
- -- not be constructible.
+ -- not be constructible. If the discriminants have defaults the type
+ -- is unconstrained and there is nothing to check.
elsif Has_Unknown_Discriminants (Base_Type (Etype (Lhs)))
and then Has_Discriminants (Typ)
+ and then not Has_Defaulted_Discriminants (Typ)
then
Rewrite (Rhs, OK_Convert_To (Base_Type (Typ), Rhs));
Rewrite (Lhs, OK_Convert_To (Base_Type (Typ), Lhs));