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] Cleanup for static expressions raising constraint error


A static expression that raises constraint error when evaluated
cannot be used in contexts requiring static evaluation. There
were many problems here, both in terms of not rejecting bad uses
of such static expressions, and in flagging expressions as being
illegal, when such constructs as 1/0 appeared in statically
unevaluated expressions. The following test now compiles with
the given errors (the last error was not issued before). This
is compiled using -gnatld7 -gnatj60:

     1. procedure T_with_case is
     2.    subtype I1 is Integer range 1 .. 5;
     3.    XI1 : constant I1 := 10;
                                |
        >>> warning: value not in range of type "I1"
            defined at line 2, "Constraint_Error" will be
            raised at run time

     4.    XI3 : constant := XI1; -- GNAT rejects this
                             |
        >>> non-static expression used in number declaration
        >>> expression raises exception, cannot be static
            (RM 4.9(34))

     5.    I : Integer := 123;
     6.
     7. begin
     8.    case I is
     9.       when XI1 => null;   -- GNAT allows this
                   |
        >>> choice given in case statement is not static
        >>> expression raises exception, cannot be static
            (RM 4.9(34))

    10.       when others => null;
    11.    end case;
    12. end T_with_case;

The following test case tests various cases of properly ignoring
errors in statically unevaluated expressions (it had many problems
and a crash) before:

    71. package BTestSU is
    72.    c1 : constant :=                         -- OK (A).
    73.           Boolean'Pos (True or else 1=1/0);
    74.    c2 : constant :=                         -- OK (B).
    75.           (if True then 1 else 1 / 0);
    76.    c3 : constant :=                         -- OK (D).
    77.           (case True is
    78.            when 0=1 => 1/0, when 2=2 => 1);
    79.    c4 : constant :=                         -- OK (B).
    80.           Boolean'Pos (if True then True
    81.                        else 1 in 0 .. 1/0);
    82.    c5 : constant :=                         -- OK (D).
    83.           (case Integer'(4) is
    84.              when Integer => 1,
    85.              when others  => 1/0);
    86.    c6 : constant :=                         -- ERROR (D)
    87.           (case False is
                   |
        >>> non-static expression used in number declaration
        >>> expression raises exception, cannot be static (RM 4.9(34))

    88.              when 0=1 => 1/0,
                                  |
        >>> division by zero
        >>> static expression fails Constraint_Check

    89.              when 2=2 => 1);
    90.    c7 : constant :=                         -- OK (E)
    91.           Boolean'Pos (1 in 1 | 2/0);
    92.    c8 : constant :=                         -- OK (C)
    93.           (if True then 1
    94.            elsif 1/0=0 then 2 else 3);
    95.    c9 : constant :=                         -- OK (E)
    96.           Boolean'Pos
    97.             (1.0 in 1.0 | 1.0 / 0.0);
    98.    c10 : constant :=                        -- ERROR (E)
    99.            Boolean'Pos
   100.              (2.0 in 1.0 | 1.0 / 0.0);
                                       |
        >>> division by zero
        >>> static expression fails Constraint_Check

   101.
   102.    subtype S1 is String (1 .. 2);          -- OK
   103.    subtype S2 is String (1 .. 3);          -- OK
   104.    subtype S3 is String (1 .. 3/0);        -- ERROR
                                       |
        >>> division by zero
        >>> static expression fails Constraint_Check

   105.
   106.    Scon : constant String := "ABC";        -- OK
   107.
   108.    c11 : constant :=                       -- OK (E)
   109.            Boolean'Pos
   110.              (Scon in S1 | S2 | S3);
   111.    c12 : constant :=                       -- ERROR (E)
   112.            Boolean'Pos
                   |
        >>> non-static expression used in number declaration

   113.              (Scon in S3 | S2 | S1);
                              |
        >>> "S3" is not a static subtype (RM 4.9(26))

   114.    c13 : constant :=                       -- OK (E)
   115.            Boolean'Pos
   116.              (Scon in "ABC" | S3);
   117.    c14 : constant :=                       -- ERROR (E)
   118.            Boolean'Pos
                   |
        >>> non-static expression used in number declaration

   119.              (Scon in "AB1" | "AB2" | S3);
                                              |
        >>> "S3" is not a static subtype (RM 4.9(26))

   120.    c15 : constant :=                       -- OK (B)
   121.            (if True then 1
   122.             else Boolean'Pos (1/0 = 0));
   123.    c16 : constant :=                       -- ERROR (B)
   124.            (if False then 1
   125.             else Boolean'Pos (1/0 = 0));
                                       |
        >>> division by zero
        >>> static expression fails Constraint_Check

   126.    c17 : constant :=                       -- ERROR (F)
   127.            (if True then 1
                    |
        >>> non-static expression used in number declaration

   128.             else (case 1 is
   129.                     when 1/0 => 2,
                                  |
        >>> division by zero
        >>> static expression fails Constraint_Check

   130.                     when others => 3));
   131. end BtestSU;

Note: the missing 70 lines at the start are a standard ACATS style
Btest header.

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

2014-07-29  Robert Dewar  <dewar@adacore.com>

	* sem_aggr.adb (Resolve_Array_Aggregate): Change Is_Static_Range
	to Is_OK_Static_Range.
	* sem_attr.adb (Eval_Attribute): Make sure we properly flag
	static attributes (Eval_Attribute, case Size): Handle size of
	zero properly (Eval_Attribute, case Value_Size): Handle size of
	zero properly.
	* sem_ch13.adb: Minor reformatting.
	* sem_ch3.adb (Process_Range_Expr_In_Decl): Change
	Is_Static_Range to Is_OK_Static_Range.
	* sem_eval.adb (Eval_Case_Expression): Total rewrite, was
	wrong in several ways (Is_Static_Range): Moved here from spec
	(Is_Static_Subtype): Moved here from spec Change some incorrect
	Is_Static_Subtype calls to Is_OK_Static_Subtype.
	* sem_eval.ads: Add comments to section on
	Is_Static_Expression/Raises_Constraint_Error (Is_OK_Static_Range):
	Add clarifying comments (Is_Static_Range): Moved to body
	(Is_Statically_Unevaluated): New function.
	* sem_util.ads, sem_util.adb (Is_Preelaborable_Expression): Change
	Is_Static_Range to Is_OK_Static_Range.
	* sinfo.ads: Additional commments for Is_Static_Expression noting
	that clients should almost always use Is_OK_Static_Expression
	instead. Many other changes throughout front end units to obey
	this rule.
	* tbuild.ads, tbuild.adb (New_Occurrence_Of): Set Is_Static_Expression
	for enumeration literal.
	* exp_ch5.adb, sem_intr.adb, sem_ch5.adb, exp_attr.adb, exp_ch9.adb,
	lib-writ.adb, sem_ch9.adb, einfo.ads, checks.adb, checks.ads,
	sem_prag.adb, sem_ch12.adb, freeze.adb, sem_res.adb, exp_ch4.adb,
	exp_ch6.adb, sem_ch4.adb, sem_ch6.adb, exp_aggr.adb, sem_cat.adb:
	Replace all occurrences of Is_Static_Expression by
	Is_OK_Static_Expression.

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]