In Ada 2012, static matching of subtypes requires that the static predicates
that apply to the subtypes come from the same declaration.

Compiling predmatch.ads in Ada 2012 mode must yield:

   predmatch.ads:5:21: object subtype must statically match designated subtype
   predmatch.ads:12:22: object subtype must statically match designated subtype
   predmatch.ads:15:22: object subtype must statically match designated subtype

---
package Predmatch is
   type Int_Ref is access all Integer;
   subtype Even is Integer with Dynamic_predicate => Even mod 2 = 0;
   X1 : aliased Even;
   Ptr : Int_Ref := X1'access;  --  Illegal in Ada 2012

   subtype Little_Even is Integer
      with
        Static_Predicate  => Little_Even in 2 | 4 | 8 | 16;
   X2 : aliased Little_Even;

   Ptr2 : Int_Ref := X2'Access; -- illegal in Ada 2012

   type Pos_Ref is access all Positive;
   Ptr3 : Pos_Ref := X1'access;   --  Illegal in Ada 2005

   subtype Mult2 is Even;
   type Mult_Ref is access all Mult2;
   Ptr4 : Mult_Ref := X1'Access;  --  OK, same predicate
   
end Predmatch;

Tested on x86_64-pc-linux-gnu, committed on trunk

2012-05-15  Ed Schonberg  <schonb...@adacore.com>

        * sem_eval.adb (Subtypes_Statically_Match): In Ada 2012, static
        matching requires matching of static subtype predicates as well.

Index: sem_eval.adb
===================================================================
--- sem_eval.adb        (revision 187504)
+++ sem_eval.adb        (working copy)
@@ -4664,6 +4664,41 @@
    --  values match (RM 4.9.1(1)).
 
    function Subtypes_Statically_Match (T1, T2 : Entity_Id) return Boolean is
+
+      function Predicates_Match return Boolean;
+      --  In Ada 2012, subtypes statically match if their static predicates
+      --  match as well.
+
+      function Predicates_Match return Boolean is
+         Pred1 : Node_Id;
+         Pred2 : Node_Id;
+
+      begin
+         if Ada_Version < Ada_2012 then
+            return True;
+
+         elsif Has_Predicates (T1) /= Has_Predicates (T2) then
+            return False;
+
+         else
+            Pred1 := Get_Rep_Item_For_Entity (T1, Name_Static_Predicate);
+            Pred2 := Get_Rep_Item_For_Entity (T2, Name_Static_Predicate);
+
+            --  Subtypes statically match if the predicate comes from the
+            --  same declaration, which can only happen if one is a subtype
+            --  of the other and has no explicit predicate.
+
+            --  Suppress warnings on order of actuals, which is otherwise
+            --  triggered by one of the two calls below.
+
+            pragma Warnings (Off);
+            return Pred1 = Pred2
+              or else (No (Pred1) and then Is_Subtype_Of (T1, T2))
+              or else (No (Pred2) and then Is_Subtype_Of (T2, T1));
+            pragma Warnings (On);
+         end if;
+      end Predicates_Match;
+
    begin
       --  A type always statically matches itself
 
@@ -4736,7 +4771,7 @@
             --  If the bounds are the same tree node, then match
 
             if LB1 = LB2 and then HB1 = HB2 then
-               return True;
+               return Predicates_Match;
 
             --  Otherwise bounds must be static and identical value
 

Reply via email to