[Ada] Constant-folding and discriminants

Message ID 20100909134443.GA19720@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Sept. 9, 2010, 1:44 p.m.
The compiler tries to optimize comparisons involving expressions that are not
compile-time known, but can be recognized as identical, for example references
to the same variable. If the expressions are references to the same discriminant
the expressions cannot be assumed to be equal, because they may denote the
discriminant of two different instances of the same discriminated type, used
for example as a component bound.

The following must compile and execute quietly:

procedure No_Fold is
   type Arr is array (integer range <>) of Integer;
   type Rec (Discr : Positive) is record
      Field : Arr (1 .. Discr);
   end record;

   R1 : Rec (3) := (3, (others => 0));
   R2 : Rec (7) := (7, (others => 0));

   procedure Compare (X, Y : Rec) is
      if X.Discr < Y.Discr
         and then not (X.Field'Last < Y.Field'Last)
         raise Program_Error;
      end if;
   end Compare;
   Compare (R1, R2);

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

2010-09-09  Ed Schonberg  <schonberg@adacore.com>

	* sem_eval.adb (Is_Same_Value): Two occurrences of the same
	discriminant cannot be assumed to be the same value because they may
	refer to bounds of a component of two different instances of a
	discriminated type.


Index: sem_eval.adb
--- sem_eval.adb	(revision 164000)
+++ sem_eval.adb	(working copy)
@@ -642,9 +642,15 @@  package body Sem_Eval is
          --  types, since we may have two NaN values and they should never
          --  compare equal.
+         --  If the entity is a discriminant, the two expressions may be
+         --  bounds of components of objects of the same discriminated
+         --  type. The values of the discriminants are not static, and
+         --  therefore the result is unknown.
          if Nkind_In (Lf, N_Identifier, N_Expanded_Name)
            and then Nkind_In (Rf, N_Identifier, N_Expanded_Name)
            and then Entity (Lf) = Entity (Rf)
+           and then Ekind (Entity (Lf)) /= E_Discriminant
            and then Present (Entity (Lf))
            and then not Is_Floating_Point_Type (Etype (L))
            and then not Is_Volatile_Reference (L)