This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Ada] Further work on predicates


This patch completes the implementation of predicates as described in
AI05-0153-1/06. There are two more aspects to be taken care of. First
we will likely decide that 'First/'Last should not be allowed if a
predicate is present, second we want to introduce the notion of a
static predicate usable in case statements.

The following two tests are compiled with -gnata12 -gnatj60 -gnatld7
and they both execute silently showing that all tests have passed.

Compiling: test_predicates.ads

     1. with Ada.Assertions; use Ada.Assertions;
     2. package Test_Predicates is
     3.
     4.    type Even is range 0 .. Integer'Last with
     5.      Predicate => (Even mod 2) = 0;
     6.
     7.    type Color is
     8.      (Red, Orange, Yellow, Green, Blue, Indigo, Violet);
     9.    subtype RGB is Color with
    10.      Predicate => RGB = Red or RGB in Green .. Blue;
    11.    subtype Other_Color is Color with
    12.      Predicate => Other_Color not in RGB;
    13.
    14.    subtype Another_Color is Other_Color;
                   |
        >>> info: "Another_Color" inherits predicate from
            "Other_Color" at line 11

    15.    function Not_Another_One return Color;
    16.    -- Returns a value that violates
    17.    -- Another_Color's predicate
    18.
    19.    type No_Defaults is private;
    20.    subtype No_Defaults_P is No_Defaults with
    21.      Predicate => Is_Good (No_Defaults_P);
    22.
    23.    function Is_Good (X : No_Defaults) return Boolean;
    24.    function Good return No_Defaults;
    25.    function Bad return No_Defaults;
    26.    -- Is_Good(Good) is True; Is_Good(Bad) is False.
    27.
    28.    type Defaults is private;
    29.    subtype Defaults_P is Defaults with
    30.      Predicate => Is_Good (Defaults_P);
    31.
    32.    function Is_Good (X : Defaults) return Boolean;
    33.    function Good return Defaults;
    34.    function Bad return Defaults;
    35.
    36.    type String_Ref is access all String;
    37.
    38. private
    39.
    40.    type No_Defaults is
    41.       record
    42.          Comp : Integer;
    43.          Acc : String_Ref;
    44.          -- Default 'null' default doesn't count!
    45.       end record;
    46.
    47.    type Defaults is
    48.       record
    49.          Comp : Integer := 0;
    50.          Acc : String_Ref := null;
    51.       end record;
    52.
    53. end Test_Predicates;

Compiling: test_predicates.adb

     1.
     2. package body Test_Predicates is
     3.
     4.    function Not_Another_One return Color is
     5.    begin
     6.       return Result : constant Color := Red do
     7.          pragma Assert (Result in RGB);
     8.          pragma Assert
     9.            (Result not in Another_Color);
    10.       end return;
    11.    end Not_Another_One;
    12.
    13.    function Is_Good
    14.      (X : No_Defaults) return Boolean is
    15.    begin
    16.       return X.Acc /= null;
    17.    end Is_Good;
    18.
    19.    function Good return No_Defaults is
    20.    begin
    21.       return Result : constant No_Defaults
    22.         := (Comp => 0, Acc => new String'("xxx"))
    23.       do
    24.          pragma Assert (Result in No_Defaults_P);
    25.          pragma Assert (Is_Good (Result));
    26.       end return;
    27.    end Good;
    28.
    29.    function Bad return No_Defaults is
    30.    begin
    31.       return Result : constant No_Defaults
    32.         := (Comp => 0, Acc => null)
    33.       do
    34.          pragma Assert (Result not in No_Defaults_P);
    35.          pragma Assert (not Is_Good (Result));
    36.       end return;
    37.    end Bad;
    38.
    39.    function Is_Good (X : Defaults) return Boolean is
    40.    begin
    41.       return X.Acc /= null;
    42.    end Is_Good;
    43.
    44.    function Good return Defaults is
    45.    begin
    46.       return Result : constant Defaults
    47.         := (Comp => 0, Acc => new String'("xxx"))
    48.       do
    49.          pragma Assert (Is_Good (Result));
    50.          pragma Assert (Result in Defaults_P);
    51.       end return;
    52.    end Good;
    53.
    54.    function Bad return Defaults is
    55.    begin
    56.       return Result : constant Defaults
    57.         := (Comp => 0, Acc => null)
    58.       do
    59.          pragma Assert (not Is_Good (Result));
    60.          pragma Assert (Result not in Defaults_P);
    61.       end return;
    62.    end Bad;
    63.
    64. end Test_Predicates;

Compiling: test_predicates-acc.ads

     1. package Test_Predicates.Acc is
     2.
     3.    type Node (Discrim : Color) is
     4.       record
     5.          case Discrim is
     6.             when Red =>
     7.                Red_Comp : Integer;
     8.             when others =>
     9.                Others_Color_Comp : Integer;
    10.          end case;
    11.       end record;
    12.
    13.    type Ref is access all Node;
    14.    subtype RGB_Ref is Ref with
    15.      Predicate => RGB_Ref.all.Discrim in RGB;
    16.    subtype Another_Color_Ref is Ref with
    17.      Predicate =>
    18.        Another_Color_Ref.all.Discrim
    19.          in Another_Color;
    20.
    21. end Test_Predicates.Acc;

Compiling: test_predicates-main.adb

     1. with Test_Predicates.Acc;
     2. use Test_Predicates.Acc;
     3. procedure Test_Predicates.Main is
     4.    --  This test should run silently
     5.
     6.    pragma Assert (RGB'First in RGB);
     7.    pragma Assert
     8.      (Another_Color'First not in Another_Color);
     9.
    10.    pragma Assert (RGB'Last not in RGB);
    11.    pragma Assert
    12.      (Another_Color'Last in Another_Color);
    13.
    14.    X1 : RGB;
    15.    -- OK; predicate not checked
    16.
    17.    X2 : Another_Color;
    18.    -- OK; predicate not checked
    19.
    20.    X3 : No_Defaults;
    21.    -- OK; no predicate
    22.
    23.    X4 : No_Defaults_P;
    24.    -- OK; predicate not checked
    25.
    26.    X5 : Defaults;
    27.    -- OK; no predicate
    28.
    29.    X6 : RGB := Not_Another_One;
    30.    -- OK; predicate is True
    31.
    32.    X7 : No_Defaults := Bad;
    33.    -- OK; no predicate
    34.
    35.    X8 : No_Defaults_P := Good;
    36.    -- OK; predicate is True
    37.
    38.    X9 : Defaults := Bad;
    39.    -- OK; no predicate
    40.
    41.    X10 : Defaults_P := Good;
    42.    -- OK; predicate is True
    43.
    44.    Even_Var_1 : Even;
    45.    -- OK; predicate not checked
    46.
    47.    Even_Var_2 : Even := 100;
    48.    -- OK; predicate is True
    49.
    50. begin
    51.
    52.    begin
    53.       Even_Var_1 := 1;
    54.       raise Program_Error;
    55.       -- Predicate should have failed
    56.    exception
    57.       when Assertion_Error =>
    58.          null; -- OK
    59.    end;
    60.
    61.    Even_Var_1 := 0; -- OK; predicate is True
    62.
    63.    begin
    64.       declare
    65.          Even_Var_3 : Even := Even_Var_2 + 1;
    66.       begin
    67.          raise Program_Error;
    68.          -- Predicate should have failed
    69.       end;
    70.    exception
    71.       when Assertion_Error =>
    72.          null; -- OK
    73.    end;
    74.
    75.    ----------------
    76.
    77.    begin
    78.       declare
    79.          Var : Another_Color := Not_Another_One;
    80.       begin
    81.          raise Program_Error;
    82.          -- Predicate should have failed
    83.       end;
    84.    exception
    85.       when Assertion_Error =>
    86.          null; -- OK
    87.    end;
    88.
    89.    begin
    90.       declare
    91.          Var : Defaults_P := Bad;
    92.       begin
    93.          raise Program_Error;
    94.          -- Predicate should have failed
    95.       end;
    96.    exception
    97.       when Assertion_Error =>
    98.          null; -- OK
    99.    end;
   100.
   101.    begin
   102.       declare
   103.          Var : No_Defaults_P := Bad;
   104.       begin
   105.          raise Program_Error;
   106.          -- Predicate should have failed
   107.       end;
   108.    exception
   109.       when Assertion_Error =>
   110.          null; -- OK
   111.    end;
   112.
   113.    begin
   114.       declare
   115.          Var : Defaults_P;
   116.          -- Default init violates predicate
   117.       begin
   118.          raise Program_Error;
   119.          -- Predicate should have failed
   120.       end;
   121.    exception
   122.       when Assertion_Error =>
   123.          null; -- OK
   124.    end;
   125.
   126.    X1 := Not_Another_One; -- OK; predicate is True
   127.
   128.    begin
   129.       X2 := Not_Another_One;
   130.       raise Program_Error; -- Predicate should have failed
   131.    exception
   132.       when Assertion_Error =>
   133.          null; -- OK
   134.    end;
   135.
   136.    X3 := Bad; -- OK; no predicate
   137.
   138.    X4 := Good;
   139.    begin
   140.       X4 := Bad;
   141.       raise Program_Error;
   142.       -- Predicate should have failed
   143.    exception
   144.       when Assertion_Error =>
   145.          null; -- OK
   146.    end;
   147.
   148.    X5 := Bad; -- OK; no predicate
   149.
   150.    X6 := Not_Another_One;
   151.    -- OK; predicate is True
   152.
   153.    X7 := Bad; -- OK; no predicate
   154.
   155.    X8 := Good; -- OK; predicate is True
   156.    begin
   157.       X8 := Bad;
   158.       raise Program_Error;
   159.       -- Predicate should have failed
   160.    exception
   161.       when Assertion_Error =>
   162.          null; -- OK
   163.    end;
   164.
   165.    X9 := Bad; -- OK; no predicate
   166.
   167.    X10 := Good; -- OK; predicate is True
   168.    begin
   169.       X10 := Bad;
   170.       raise Program_Error;
   171.       -- Predicate should have failed
   172.    exception
   173.       when Assertion_Error =>
   174.          null; -- OK
   175.    end;
   176.
   177.    ----------------
   178.
   179.    declare
   180.       procedure P (X : Another_Color_Ref) is
   181.       begin
   182.          null;
   183.       end P;
   184.
   185.       Var : Ref := new Node(Red);
   186.    begin
   187.       P (Var); -- Violate predicate of 'in' param
   188.       raise Program_Error;
   189.    exception
   190.       when Assertion_Error =>
   191.          null; -- OK
   192.    end;
   193.
   194.    declare
   195.       procedure P (X : out Another_Color_Ref) is
   196.       begin
   197.          null;
   198.          -- Predicate of 'out' param
   199.          -- raises Constraint_Error
   200.       end P;
   201.
   202.       Var : Ref;
   203.    begin
   204.       P (Var);
   205.       raise Program_Error;
   206.    exception
   207.       when Constraint_Error =>
   208.          null; -- OK
   209.    end;
   210.
   211.    declare
   212.       procedure P (X : out Another_Color_Ref) is
   213.       begin
   214.          X := new Node(Orange);
   215.       end P;
   216.
   217.       Var : Ref;
   218.    begin
   219.       P (Var);
   220.       -- OK; don't check predicate on the way 'in'
   221.    end;
   222.
   223.    declare
   224.       procedure P (X : in out Another_Color_Ref) is
   225.       begin
   226.          X := new Node(Orange); -- Can't get here
   227.       end P;
   228.
   229.       Var : Ref;
   230.    begin
   231.       P (Var);
   232.       -- Predicate of 'in out' param
   233.       -- raises Constraint_Error
   234.       raise Program_Error;
   235.    exception
   236.       when Constraint_Error =>
   237.          null; -- OK
   238.    end;
   239.
   240. end Test_Predicates.Main;

Compiling: test_predicates_lim.ads

     1.
     2. with Ada.Assertions; use Ada.Assertions;
     3. package Test_Predicates_Lim is
     4.
     5.    type No_Defaults is limited private;
     6.    subtype No_Defaults_P is No_Defaults with
     7.      Predicate => Is_Good (No_Defaults_P);
     8.
     9.    function Is_Good (X : No_Defaults)
    10.      return Boolean;
    11.    function Good return No_Defaults;
    12.    function Bad return No_Defaults;
    13.    procedure Set_To_Bad (X : out No_Defaults);
    14.    procedure Set_To_Good (X : out No_Defaults);
    15.
    16.    type Defaults is limited private;
    17.    subtype Defaults_P is Defaults with
    18.      Predicate => Is_Good (Defaults_P);
    19.
    20.    function Is_Good (X : Defaults)
    21.      return Boolean;
    22.    function Good return Defaults;
    23.    function Bad return Defaults;
    24.    procedure Set_To_Bad (X : out Defaults);
    25.    procedure Set_To_Good (X : out Defaults);
    26.
    27.    type String_Ref is access all String;
    28.
    29. private
    30.
    31.    type No_Defaults is limited
    32.       record
    33.          Comp : Integer;
    34.          Acc : String_Ref;
    35.          -- Default 'null' default doesn't count!
    36.       end record;
    37.
    38.    type Defaults is limited
    39.       record
    40.          Comp : Integer := 0;
    41.          Acc : String_Ref := null;
    42.       end record;
    43.
    44. end Test_Predicates_Lim;

Compiling: test_predicates_lim.adb

     1. package body Test_Predicates_Lim is
     2.
     3.    function Is_Good (X : No_Defaults)
     4.      return Boolean is
     5.    begin
     6.       return X.Acc /= null;
     7.    end Is_Good;
     8.
     9.    function Good return No_Defaults is
    10.    begin
    11.       return Result : constant No_Defaults
    12.         := (Comp => 0, Acc => new String'("xxx"))
    13.       do
    14.          pragma Assert (Result in No_Defaults_P);
    15.          pragma Assert (Is_Good (Result));
    16.       end return;
    17.    end Good;
    18.
    19.    function Bad return No_Defaults is
    20.    begin
    21.       return Result : constant No_Defaults
    22.         := (Comp => 0, Acc => null)
    23.       do
    24.          pragma Assert
    25.            (Result not in No_Defaults_P);
    26.          pragma Assert (not Is_Good (Result));
    27.       end return;
    28.    end Bad;
    29.
    30.    procedure Set_To_Bad (X : out No_Defaults) is
    31.    begin
    32.       X.Acc := null;
    33.       pragma Assert (X not in No_Defaults_P);
    34.       pragma Assert (not Is_Good (X));
    35.    end Set_To_Bad;
    36.
    37.    procedure Set_To_Good (X : out No_Defaults) is
    38.    begin
    39.       X.Acc := new String'("xxx");
    40.       pragma Assert (X in No_Defaults_P);
    41.       pragma Assert (Is_Good (X));
    42.    end Set_To_Good;
    43.
    44.    function Is_Good (X : Defaults)
    45.      return Boolean is
    46.    begin
    47.       return X.Acc /= null;
    48.    end Is_Good;
    49.
    50.    function Good return Defaults is
    51.    begin
    52.       return Result : constant Defaults
    53.         := (Comp => 0,
    54.             Acc => new String'("xxx"))
    55.       do
    56.          pragma Assert (Is_Good (Result));
    57.          pragma Assert
    58.            (Result in Defaults_P);
    59.       end return;
    60.    end Good;
    61.
    62.    function Bad return Defaults is
    63.    begin
    64.       return Result : constant Defaults
    65.         := (Comp => 0, Acc => null)
    66.       do
    67.          pragma Assert
    68.            (not Is_Good (Result));
    69.          pragma Assert
    70.            (Result not in Defaults_P);
    71.       end return;
    72.    end Bad;
    73.
    74.    procedure Set_To_Bad (X : out Defaults) is
    75.    begin
    76.       X.Acc := null;
    77.       pragma Assert (X not in Defaults_P);
    78.       pragma Assert (not Is_Good (X));
    79.    end Set_To_Bad;
    80.
    81.    procedure Set_To_Good (X : out Defaults) is
    82.    begin
    83.       X.Acc := new String'("xxx");
    84.       pragma Assert (X in Defaults_P);
    85.       pragma Assert (Is_Good (X));
    86.    end Set_To_Good;
    87.
    88. end Test_Predicates_Lim;

Compiling: test_predicates_lim-main.adb

     1. pragma Warnings (Off);
     2. procedure Test_Predicates_Lim.Main is
     3.    --  This test should run silently
     4.
     5.    X3 : No_Defaults;
     6.    -- OK; no predicate
     7.
     8.    X4 : No_Defaults_P;
     9.    -- OK; predicate not checked
    10.
    11.    X5 : Defaults;
    12.    -- OK; no predicate
    13.
    14.    X7 : No_Defaults := Bad;
    15.    -- OK; no predicate
    16.
    17.    X8 : No_Defaults_P := Good;
    18.    -- OK; predicate is True
    19.
    20.    X9 : Defaults := Bad;
    21.    -- OK; no predicate
    22.
    23.    X10 : Defaults := Good;
    24.    -- OK; predicate is True
    25.
    26. begin
    27.
    28.    begin
    29.       declare
    30.          Var : Defaults_P;
    31.          -- Default init violates predicate
    32.       begin
    33.          raise Program_Error;
    34.          -- Predicate should have failed
    35.       end;
    36.    exception
    37.       when Assertion_Error =>
    38.          null; -- OK
    39.    end;
    40.
    41.    begin
    42.       declare
    43.          Var : Defaults_P := Bad;
    44.       begin
    45.          raise Program_Error;
    46.          -- Predicate should have failed
    47.       end;
    48.    exception
    49.       when Assertion_Error =>
    50.          null; -- OK
    51.    end;
    52.
    53.    begin
    54.       declare
    55.          Var : No_Defaults_P := Bad;
    56.       begin
    57.          raise Program_Error;
    58.          -- Predicate should have failed
    59.       end;
    60.    exception
    61.       when Assertion_Error =>
    62.          null; -- OK
    63.    end;
    64.
    65.    declare
    66.       procedure P (X : No_Defaults_P) is
    67.       begin
    68.          null;
    69.       end P;
    70.    begin
    71.       P (Bad);
    72.       -- Violate predicate of 'in' param
    73.    exception
    74.       when Assertion_Error =>
    75.          null; -- OK
    76.          P (Good);
    77.    end;
    78.
    79.    declare
    80.       procedure P (X : out No_Defaults_P) is
    81.       begin
    82.          Set_To_Bad (X);
    83.          -- Violate predicate of 'out' param
    84.       end P;
    85.       X : No_Defaults := Good;
    86.    begin
    87.       P (X);
    88.    exception
    89.       when Assertion_Error =>
    90.          null; -- OK
    91.    end;
    92.
    93.    declare
    94.       procedure P (X : out No_Defaults_P) is
    95.       begin
    96.          Set_To_Good (X);
    97.       end P;
    98.       X : No_Defaults := Bad;
    99.       -- OK; no predicate
   100.    begin
   101.       P (X);
   102.       -- OK; no check for 'out' on the way in
   103.    end;
   104.
   105.    declare
   106.       procedure P (X : in out No_Defaults_P) is
   107.       begin
   108.          Set_To_Bad (X);
   109.          -- Violate predicate of 'in out' param
   110.       end P;
   111.       X : No_Defaults := Good;
   112.    begin
   113.       P (X);
   114.    exception
   115.       when Assertion_Error =>
   116.          null; -- OK
   117.    end;
   118.
   119. end Test_Predicates_Lim.Main;

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

2010-10-22  Robert Dewar  <dewar@adacore.com>

	* exp_ch3.adb (Expand_N_Object_Declaration): Do required predicate
	checks.
	* sem_ch3.adb (Complete_Private_Subtype): Propagate predicates to full
	view.
	* sem_ch6.adb (Invariants_Or_Predicates_Present): New name for
	Invariants_Present.
	(Process_PPCs): Handle predicates generating post conditions
	* sem_util.adb (Is_Partially_Initialized_Type): Add
	Include_Null parameter.
	* sem_util.ads (Is_Partially_Initialized_Type): Add
	Include_Null parameter.

Attachment: difs
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]