Static_Predicate should not be applied on non-scalar types. The example below
is now rejected by GNAT:

     $ gcc -c -gnat12 t.ads

     1. package T is
     2.    type R is tagged record
                |
        >>> static predicate not allowed for non-scalar type "R"

     3.       A, B : Integer;
     4.    end record with Static_Predicate => R.A = 0 and R.B = 0;
     5. end T;

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

2013-04-23  Yannick Moy  <m...@adacore.com>

        * einfo.ads: Minor typo fix.
        * sem_ch13.adb (Build_Predicate_Functions): Reject cases where
        Static_Predicate is applied to a non-scalar or non-static type.
        * sem_prag.adb: Minor typo fix.

Index: einfo.ads
===================================================================
--- einfo.ads   (revision 198194)
+++ einfo.ads   (working copy)
@@ -2544,7 +2544,7 @@
 --       entirely synthesized, by looking at the bounds, and the immediate
 --       subtype parent. However, this method does not work for some Itypes
 --       that have no parent set (and the only way to find the immediate
---       subtype parent is to go through the tree). For now, this flay is set
+--       subtype parent is to go through the tree). For now, this flag is set
 --       conservatively, i.e. if it is set then for sure the subtype is non-
 --       static, but if it is not set, then the type may or may not be static.
 --       Thus the test for a static subtype is that this flag is clear AND that
Index: sem_prag.adb
===================================================================
--- sem_prag.adb        (revision 198195)
+++ sem_prag.adb        (working copy)
@@ -8121,8 +8121,8 @@
             --  Set Check_On to indicate check status
 
             --  If this comes from an aspect, we have already taken care of
-            --  the policy active when the aspect was analyzed, and Is_Ignore
-            --  is set appriately already.
+            --  the policy active when the aspect was analyzed, and Is_Ignored
+            --  is set appropriately already.
 
             if From_Aspect_Specification (N) then
                Check_On := not Is_Ignored (N);
Index: sem_ch13.adb
===================================================================
--- sem_ch13.adb        (revision 198184)
+++ sem_ch13.adb        (working copy)
@@ -980,7 +980,7 @@
             --  Perform analysis of the External_Name or Link_Name aspects
 
             procedure Analyze_Aspect_Implicit_Dereference;
-            --  Perform  analysis of the Implicit_Dereference aspects
+            --  Perform analysis of the Implicit_Dereference aspects
 
             procedure Make_Aitem_Pragma
               (Pragma_Argument_Associations : List_Id;
@@ -1082,8 +1082,8 @@
                      Pragma_Argument_Associations,
                    Pragma_Identifier =>
                      Make_Identifier (Sloc (Id), Pragma_Name),
-                     Class_Present     => Class_Present (Aspect),
-                     Split_PPC         => Split_PPC (Aspect));
+                   Class_Present     => Class_Present (Aspect),
+                   Split_PPC         => Split_PPC (Aspect));
 
                --  Set additional semantic fields
 
@@ -5707,7 +5707,7 @@
    -- Build_Predicate_Functions --
    -------------------------------
 
-   --  The procedures that are constructed here has the form:
+   --  The procedures that are constructed here have the form:
 
    --    function typPredicate (Ixxx : typ) return Boolean is
    --    begin
@@ -5725,8 +5725,8 @@
    --  use this function even if checks are off, e.g. for membership tests.
 
    --  If the expression has at least one Raise_Expression, then we also build
-   --  the typPredicateM version of the function, in which any occurence of a
-   --  Raise_Expressioon is converted to "return False".
+   --  the typPredicateM version of the function, in which any occurrence of a
+   --  Raise_Expression is converted to "return False".
 
    procedure Build_Predicate_Functions (Typ : Entity_Id; N : Node_Id) is
       Loc : constant Source_Ptr := Sloc (Typ);
@@ -6216,23 +6216,49 @@
 
          --  Deal with static predicate case
 
-         if Ekind_In (Typ, E_Enumeration_Subtype,
-                           E_Modular_Integer_Subtype,
-                           E_Signed_Integer_Subtype)
+         --  ??? We don't currently deal with real types
+         --  ??? Why requiring that Typ is static?
+
+         if Ekind (Typ) in Discrete_Kind
            and then Is_Static_Subtype (Typ)
            and then not Dynamic_Predicate_Present
          then
-            Build_Static_Predicate (Typ, Expr, Object_Name);
+            --  Only build the predicate for subtypes
 
-            if Present (Static_Predicate_Present)
-              and No (Static_Predicate (Typ))
+            if Ekind_In (Typ, E_Enumeration_Subtype,
+                              E_Modular_Integer_Subtype,
+                              E_Signed_Integer_Subtype)
             then
-               Error_Msg_F
-                 ("expression does not have required form for "
-                  & "static predicate",
-                  Next (First (Pragma_Argument_Associations
-                                (Static_Predicate_Present))));
+               Build_Static_Predicate (Typ, Expr, Object_Name);
+
+               if Present (Static_Predicate_Present)
+                 and No (Static_Predicate (Typ))
+               then
+                  Error_Msg_F
+                    ("expression does not have required form for "
+                     & "static predicate",
+                     Next (First (Pragma_Argument_Associations
+                                   (Static_Predicate_Present))));
+               end if;
             end if;
+
+         --  If a Static_Predicate applies on other types, that's an error:
+         --  either the type is scalar but non-static, or it's not even a
+         --  scalar type. We do not issue an error on generated types, as these
+         --  would be duplicates of the same error on a source type.
+
+         elsif Present (Static_Predicate_Present)
+           and then Comes_From_Source (Typ)
+         then
+            if Is_Scalar_Type (Typ) then
+               Error_Msg_FE
+                 ("static predicate not allowed for non-static type&",
+                  Typ, Typ);
+            else
+               Error_Msg_FE
+                 ("static predicate not allowed for non-scalar type&",
+                  Typ, Typ);
+            end if;
          end if;
       end if;
    end Build_Predicate_Functions;

Reply via email to