OSDN Git Service

2010-04-06 Matthias Klose <doko@ubuntu.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / sem_eval.adb
index 19abf4b..c9054f3 100644 (file)
@@ -424,6 +424,10 @@ package body Sem_Eval is
       --  have a 'Last/'First reference in which case the value returned is the
       --  appropriate type bound.
 
+      function Is_Known_Valid_Operand (Opnd : Node_Id) return Boolean;
+      --  Even if the context does not assume that values are valid, some
+      --  simple cases can be recognized.
+
       function Is_Same_Value (L, R : Node_Id) return Boolean;
       --  Returns True iff L and R represent expressions that definitely
       --  have identical (but not necessarily compile time known) values
@@ -522,7 +526,7 @@ package body Sem_Eval is
                else         -- Attribute_Name (N) = Name_Last
                   return Make_Integer_Literal (Sloc (N),
                     Intval => Intval (String_Literal_Low_Bound (Xtyp))
-                       + String_Literal_Length (Xtyp));
+                                + String_Literal_Length (Xtyp));
                end if;
             end if;
 
@@ -551,6 +555,22 @@ package body Sem_Eval is
          return N;
       end Compare_Fixup;
 
+      ----------------------------
+      -- Is_Known_Valid_Operand --
+      ----------------------------
+
+      function Is_Known_Valid_Operand (Opnd : Node_Id) return Boolean is
+      begin
+         return (Is_Entity_Name (Opnd)
+                  and then
+                    (Is_Known_Valid (Entity (Opnd))
+                      or else Ekind (Entity (Opnd)) = E_In_Parameter
+                      or else
+                        (Ekind (Entity (Opnd)) in Object_Kind
+                           and then Present (Current_Value (Entity (Opnd))))))
+           or else Is_OK_Static_Expression (Opnd);
+      end Is_Known_Valid_Operand;
+
       -------------------
       -- Is_Same_Value --
       -------------------
@@ -560,12 +580,11 @@ package body Sem_Eval is
          Rf : constant Node_Id := Compare_Fixup (R);
 
          function Is_Same_Subscript (L, R : List_Id) return Boolean;
-         --  L, R are the Expressions values from two attribute nodes
-         --  for First or Last attributes. Either may be set to No_List
-         --  if no expressions are present (indicating subscript 1).
-         --  The result is True if both expressions represent the same
-         --  subscript (note that one case is where one subscript is
-         --  missing and the other is explicitly set to 1).
+         --  L, R are the Expressions values from two attribute nodes for First
+         --  or Last attributes. Either may be set to No_List if no expressions
+         --  are present (indicating subscript 1). The result is True if both
+         --  expressions represent the same subscript (note one case is where
+         --  one subscript is missing and the other is explicitly set to 1).
 
          -----------------------
          -- Is_Same_Subscript --
@@ -706,7 +725,7 @@ package body Sem_Eval is
          return Unknown;
 
       --  For access types, the only time we know the result at compile time
-      --  (apart from identical operands, which we handled already, is if we
+      --  (apart from identical operands, which we handled already) is if we
       --  know one operand is null and the other is not, or both operands are
       --  known null.
 
@@ -720,9 +739,7 @@ package body Sem_Eval is
                return Unknown;
             end if;
 
-         elsif Known_Non_Null (L)
-           and then Known_Null (R)
-         then
+         elsif Known_Non_Null (L) and then Known_Null (R) then
             return NE;
 
          else
@@ -792,7 +809,7 @@ package body Sem_Eval is
 
          --  For remaining scalar cases we know exactly (note that this does
          --  include the fixed-point case, where we know the run time integer
-         --  values now)
+         --  values now).
 
          else
             declare
@@ -887,13 +904,31 @@ package body Sem_Eval is
                  and then RLo = RHi
                  and then LLo = RLo
                then
-                  return EQ;
+
+                  --  If the range includes a single literal and we can assume
+                  --  validity then the result is known even if an operand is
+                  --  not static.
+
+                  if Assume_Valid then
+                     return EQ;
+                  else
+                     return Unknown;
+                  end if;
 
                elsif LHi = RLo then
                   return LE;
 
                elsif RHi = LLo then
                   return GE;
+
+               elsif not Is_Known_Valid_Operand (L)
+                 and then not Assume_Valid
+               then
+                  if Is_Same_Value (L, R) then
+                     return EQ;
+                  else
+                     return Unknown;
+                  end if;
                end if;
             end if;
          end;
@@ -1876,11 +1911,11 @@ package body Sem_Eval is
                Atyp := Designated_Type (Atyp);
             end if;
 
-            --  If we have an array type (we should have but perhaps there
-            --  are error cases where this is not the case), then see if we
-            --  can do a constant evaluation of the array reference.
+            --  If we have an array type (we should have but perhaps there are
+            --  error cases where this is not the case), then see if we can do
+            --  a constant evaluation of the array reference.
 
-            if Is_Array_Type (Atyp) then
+            if Is_Array_Type (Atyp) and then Atyp /= Any_Composite then
                if Ekind (Atyp) = E_String_Literal_Subtype then
                   Lbd := String_Literal_Low_Bound (Atyp);
                else
@@ -1948,21 +1983,21 @@ package body Sem_Eval is
    --  Numeric literals are static (RM 4.9(1)), and have already been marked
    --  as static by the analyzer. The reason we did it that early is to allow
    --  the possibility of turning off the Is_Static_Expression flag after
-   --  analysis, but before resolution, when integer literals are generated
-   --  in the expander that do not correspond to static expressions.
+   --  analysis, but before resolution, when integer literals are generated in
+   --  the expander that do not correspond to static expressions.
 
    procedure Eval_Integer_Literal (N : Node_Id) is
       T : constant Entity_Id := Etype (N);
 
       function In_Any_Integer_Context return Boolean;
-      --  If the literal is resolved with a specific type in a context
-      --  where the expected type is Any_Integer, there are no range checks
-      --  on the literal. By the time the literal is evaluated, it carries
-      --  the type imposed by the enclosing expression, and we must recover
-      --  the context to determine that Any_Integer is meant.
+      --  If the literal is resolved with a specific type in a context where
+      --  the expected type is Any_Integer, there are no range checks on the
+      --  literal. By the time the literal is evaluated, it carries the type
+      --  imposed by the enclosing expression, and we must recover the context
+      --  to determine that Any_Integer is meant.
 
       ----------------------------
-      -- To_Any_Integer_Context --
+      -- In_Any_Integer_Context --
       ----------------------------
 
       function In_Any_Integer_Context return Boolean is
@@ -1971,8 +2006,8 @@ package body Sem_Eval is
 
       begin
          --  Any_Integer also appears in digits specifications for real types,
-         --  but those have bounds smaller that those of any integer base
-         --  type, so we can safely ignore these cases.
+         --  but those have bounds smaller that those of any integer base type,
+         --  so we can safely ignore these cases.
 
          return    K = N_Number_Declaration
            or else K = N_Attribute_Reference
@@ -1986,9 +2021,9 @@ package body Sem_Eval is
    begin
 
       --  If the literal appears in a non-expression context, then it is
-      --  certainly appearing in a non-static context, so check it. This
-      --  is actually a redundant check, since Check_Non_Static_Context
-      --  would check it, but it seems worth while avoiding the call.
+      --  certainly appearing in a non-static context, so check it. This is
+      --  actually a redundant check, since Check_Non_Static_Context would
+      --  check it, but it seems worth while avoiding the call.
 
       if Nkind (Parent (N)) not in N_Subexpr
         and then not In_Any_Integer_Context
@@ -2091,9 +2126,9 @@ package body Sem_Eval is
    -- Eval_Membership_Op --
    ------------------------
 
-   --  A membership test is potentially static if the expression is static,
-   --  and the range is a potentially static range, or is a subtype mark
-   --  denoting a static subtype (RM 4.9(12)).
+   --  A membership test is potentially static if the expression is static, and
+   --  the range is a potentially static range, or is a subtype mark denoting a
+   --  static subtype (RM 4.9(12)).
 
    procedure Eval_Membership_Op (N : Node_Id) is
       Left   : constant Node_Id := Left_Opnd (N);
@@ -2106,8 +2141,8 @@ package body Sem_Eval is
       Fold   : Boolean;
 
    begin
-      --  Ignore if error in either operand, except to make sure that
-      --  Any_Type is properly propagated to avoid junk cascaded errors.
+      --  Ignore if error in either operand, except to make sure that Any_Type
+      --  is properly propagated to avoid junk cascaded errors.
 
       if Etype (Left) = Any_Type
         or else Etype (Right) = Any_Type
@@ -2134,8 +2169,7 @@ package body Sem_Eval is
             return;
          end if;
 
-         --  For string membership tests we will check the length
-         --  further below.
+         --  For string membership tests we will check the length further on
 
          if not Is_String_Type (Def_Id) then
             Lo := Type_Low_Bound (Def_Id);
@@ -2191,8 +2225,8 @@ package body Sem_Eval is
             end;
          end if;
 
-      --  Fold the membership test. We know we have a static range and Lo
-      --  and Hi are set to the expressions for the end points of this range.
+      --  Fold the membership test. We know we have a static range and Lo and
+      --  Hi are set to the expressions for the end points of this range.
 
       elsif Is_Real_Type (Etype (Right)) then
          declare
@@ -2359,10 +2393,10 @@ package body Sem_Eval is
          Typ  : constant Entity_Id := Etype (N);
 
       begin
-         --  Negation is equivalent to subtracting from the modulus minus
-         --  one. For a binary modulus this is equivalent to the ones-
-         --  component of the original value. For non-binary modulus this
-         --  is an arbitrary but consistent definition.
+         --  Negation is equivalent to subtracting from the modulus minus one.
+         --  For a binary modulus this is equivalent to the ones-complement of
+         --  the original value. For non-binary modulus this is an arbitrary
+         --  but consistent definition.
 
          if Is_Modular_Integer_Type (Typ) then
             Fold_Uint (N, Modulus (Typ) - 1 - Rint, Stat);
@@ -2392,7 +2426,7 @@ package body Sem_Eval is
       Hex  : Boolean;
 
    begin
-      --  Can only fold if target is string or scalar and subtype is static
+      --  Can only fold if target is string or scalar and subtype is static.
       --  Also, do not fold if our parent is an allocator (this is because
       --  the qualified expression is really part of the syntactic structure
       --  of an allocator, and we do not want to end up with something that
@@ -2404,8 +2438,8 @@ package body Sem_Eval is
       then
          Check_Non_Static_Context (Operand);
 
-         --  If operand is known to raise constraint_error, set the
-         --  flag on the expression so it does not get optimized away.
+         --  If operand is known to raise constraint_error, set the flag on the
+         --  expression so it does not get optimized away.
 
          if Nkind (Operand) = N_Raise_Constraint_Error then
             Set_Raises_Constraint_Error (N);
@@ -2482,9 +2516,9 @@ package body Sem_Eval is
       PK : constant Node_Kind := Nkind (Parent (N));
 
    begin
-      --  If the literal appears in a non-expression context
-      --  and not as part of a number declaration, then it is
-      --  appearing in a non-static context, so check it.
+      --  If the literal appears in a non-expression context and not as part of
+      --  a number declaration, then it is appearing in a non-static context,
+      --  so check it.
 
       if PK not in N_Subexpr and then PK /= N_Number_Declaration then
          Check_Non_Static_Context (N);
@@ -2531,8 +2565,8 @@ package body Sem_Eval is
 
          Length_Mismatch : declare
             procedure Get_Static_Length (Op : Node_Id; Len : out Uint);
-            --  If Op is an expression for a constrained array with a known
-            --  at compile time length, then Len is set to this (non-negative
+            --  If Op is an expression for a constrained array with a known at
+            --  compile time length, then Len is set to this (non-negative
             --  length). Otherwise Len is set to minus 1.
 
             -----------------------
@@ -2907,7 +2941,8 @@ package body Sem_Eval is
       Left_Int := Expr_Value (Left);
 
       if (Kind = N_And_Then and then Is_False (Left_Int))
-        or else (Kind = N_Or_Else and Is_True (Left_Int))
+            or else
+         (Kind = N_Or_Else  and then Is_True (Left_Int))
       then
          Fold_Uint (N, Left_Int, Rstat);
          return;
@@ -3740,6 +3775,16 @@ package body Sem_Eval is
       elsif not Is_Scalar_Type (T1) or else not Is_Scalar_Type (T1) then
          return False;
 
+      --  If T1 has infinities but T2 doesn't have infinities, then T1 is
+      --  definitely not compatible with T2.
+
+      elsif Is_Floating_Point_Type (T1)
+        and then Has_Infinities (T1)
+        and then Is_Floating_Point_Type (T2)
+        and then not Has_Infinities (T2)
+      then
+         return False;
+
       else
          L1 := Type_Low_Bound  (T1);
          H1 := Type_High_Bound (T1);
@@ -4947,7 +4992,7 @@ package body Sem_Eval is
                   "(RM 4.9(5))!", N, E);
             end if;
 
-         when N_Binary_Op | N_And_Then | N_Or_Else | N_Membership_Test =>
+         when N_Binary_Op | N_Short_Circuit | N_Membership_Test =>
             if Nkind (N) in N_Op_Shift then
                Error_Msg_N
                 ("shift functions are never static (RM 4.9(6,18))!", N);
@@ -4973,7 +5018,7 @@ package body Sem_Eval is
 
             if Attribute_Name (N) = Name_Size then
                Error_Msg_N
-                 ("size attribute is only static for scalar type " &
+                 ("size attribute is only static for static scalar type " &
                   "(RM 4.9(7,8))", N);
 
             --  Flag array cases