From accaa343dbb9ac38414543a9984d596ce5bd1b67 Mon Sep 17 00:00:00 2001
From: Tristan Gingold <tgingold@free.fr>
Date: Sat, 18 Apr 2020 09:25:58 +0200
Subject: vhdl-evaluation: remove some cascaded errors.

Add an argument to eval_is_in_bound for the return value of overflow literal.
---
 src/vhdl/vhdl-evaluation.adb | 36 +++++++++++++-----------------------
 src/vhdl/vhdl-evaluation.ads |  7 ++++++-
 src/vhdl/vhdl-sem_assocs.adb |  2 +-
 src/vhdl/vhdl-sem_expr.adb   | 13 +++++++++++--
 4 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/src/vhdl/vhdl-evaluation.adb b/src/vhdl/vhdl-evaluation.adb
index 80dfd774d..9ffe40b42 100644
--- a/src/vhdl/vhdl-evaluation.adb
+++ b/src/vhdl/vhdl-evaluation.adb
@@ -2207,7 +2207,7 @@ package body Vhdl.Evaluation is
       Res := Build_Constant (Val, Conv);
       if Get_Constraint_State (Conv_Type) = Fully_Constrained then
          Set_Type (Res, Conv_Type);
-         if not Eval_Is_In_Bound (Val, Conv_Type) then
+         if not Eval_Is_In_Bound (Val, Conv_Type, True) then
             Warning_Msg_Sem (Warnid_Runtime_Error, +Conv,
                              "non matching length in type conversion");
             return Build_Overflow (Conv);
@@ -2277,13 +2277,11 @@ package body Vhdl.Evaluation is
                Error_Kind ("eval_type_conversion(3)", Conv_Type);
          end case;
       end if;
-      if not Eval_Is_In_Bound (Res, Get_Type (Conv)) then
-         if Get_Kind (Res) /= Iir_Kind_Overflow_Literal then
-            Warning_Msg_Sem (Warnid_Runtime_Error, +Conv,
-                             "result of conversion out of bounds");
-            Free_Eval_Static_Expr (Res, Conv);
-            Res := Build_Overflow (Conv);
-         end if;
+      if not Eval_Is_In_Bound (Res, Get_Type (Conv), True) then
+         Warning_Msg_Sem (Warnid_Runtime_Error, +Conv,
+                          "result of conversion out of bounds");
+         Free_Eval_Static_Expr (Res, Conv);
+         Res := Build_Overflow (Conv);
       end if;
       return Res;
    end Eval_Type_Conversion;
@@ -2551,9 +2549,7 @@ package body Vhdl.Evaluation is
             Set_Nth_Element (Indexes_List, I, Index);
 
             --  Return overflow if out of range.
-            if Get_Kind (Index) = Iir_Kind_Overflow_Literal
-              or else not Eval_Is_In_Bound (Index, Prefix_Index)
-            then
+            if not Eval_Is_In_Bound (Index, Prefix_Index) then
                return Build_Overflow (Expr, Get_Type (Expr));
             end if;
          end loop;
@@ -2853,9 +2849,7 @@ package body Vhdl.Evaluation is
                Set_Parameter (Expr, Param);
 
                --  Special case for overflow.
-               if Get_Kind (Param) = Iir_Kind_Overflow_Literal
-                 or else not Eval_Is_In_Bound (Param,
-                                               Get_Type (Get_Prefix (Expr)))
+               if not Eval_Is_In_Bound (Param, Get_Type (Get_Prefix (Expr)))
                then
                   return Build_Overflow (Expr);
                end if;
@@ -3354,7 +3348,8 @@ package body Vhdl.Evaluation is
    end Eval_Fp_In_Range;
 
    --  Return FALSE if literal EXPR is not in SUB_TYPE bounds.
-   function Eval_Is_In_Bound (Expr : Iir; Sub_Type : Iir) return Boolean
+   function Eval_Is_In_Bound
+     (Expr : Iir; Sub_Type : Iir; Overflow : Boolean := False) return Boolean
    is
       Type_Range : Iir;
       Val : Iir;
@@ -3374,8 +3369,7 @@ package body Vhdl.Evaluation is
             --  Ignore errors.
             return True;
          when Iir_Kind_Overflow_Literal =>
-            --  Never within bounds
-            return False;
+            return Overflow;
          when others =>
             null;
       end case;
@@ -3503,12 +3497,8 @@ package body Vhdl.Evaluation is
 
    procedure Eval_Check_Bound (Expr : Iir; Sub_Type : Iir) is
    begin
-      if Get_Kind (Expr) = Iir_Kind_Overflow_Literal then
-         --  Nothing to check, and a message was already generated.
-         return;
-      end if;
-
-      if not Eval_Is_In_Bound (Expr, Sub_Type) then
+      --  Note: use True not to repeat a message in case of overflow.
+      if not Eval_Is_In_Bound (Expr, Sub_Type, True) then
          Warning_Msg_Sem (Warnid_Runtime_Error, +Expr,
                           "static expression violates bounds");
       end if;
diff --git a/src/vhdl/vhdl-evaluation.ads b/src/vhdl/vhdl-evaluation.ads
index bf63abb49..3b68e003d 100644
--- a/src/vhdl/vhdl-evaluation.ads
+++ b/src/vhdl/vhdl-evaluation.ads
@@ -77,7 +77,12 @@ package Vhdl.Evaluation is
    function Eval_Physical_Literal (Expr : Iir) return Iir;
 
    --  Return TRUE if literal EXPR is in SUB_TYPE bounds.
-   function Eval_Is_In_Bound (Expr : Iir; Sub_Type : Iir) return Boolean;
+   --  OVERFLOW is the value returned for overflow_literal.  The default is
+   --   False because an overflow is never within the bounds (by definition).
+   --   But if you use this function to report an error, you prefer to
+   --   get True as you don't want to report a second error.
+   function Eval_Is_In_Bound
+     (Expr : Iir; Sub_Type : Iir; Overflow : Boolean := False) return Boolean;
 
    --  Emit an error if EXPR violates SUB_TYPE bounds.
    procedure Eval_Check_Bound (Expr : Iir; Sub_Type : Iir);
diff --git a/src/vhdl/vhdl-sem_assocs.adb b/src/vhdl/vhdl-sem_assocs.adb
index 79ce1c151..d68c4812e 100644
--- a/src/vhdl/vhdl-sem_assocs.adb
+++ b/src/vhdl/vhdl-sem_assocs.adb
@@ -2161,7 +2161,7 @@ package body Vhdl.Sem_Assocs is
          Expr := Eval_Expr_Check_If_Static (Expr, Res_Type);
          Set_Actual (Assoc, Expr);
          if In_Conv = Null_Iir and then Out_Conv = Null_Iir then
-            if not Eval_Is_In_Bound (Expr, Formal_Type) then
+            if not Eval_Is_In_Bound (Expr, Formal_Type, True) then
                Error_Msg_Sem
                  (+Assoc, "actual constraints don't match formal ones");
             end if;
diff --git a/src/vhdl/vhdl-sem_expr.adb b/src/vhdl/vhdl-sem_expr.adb
index c05dcb618..3f34ccf10 100644
--- a/src/vhdl/vhdl-sem_expr.adb
+++ b/src/vhdl/vhdl-sem_expr.adb
@@ -396,7 +396,8 @@ package body Vhdl.Sem_Expr is
            | Iir_Kind_Aggregate
            | Iir_Kind_Allocator_By_Expression
            | Iir_Kind_Allocator_By_Subtype
-           | Iir_Kind_Qualified_Expression =>
+           | Iir_Kind_Qualified_Expression
+           | Iir_Kind_Overflow_Literal =>
             return Expr;
          when Iir_Kinds_Dyadic_Operator
            | Iir_Kinds_Monadic_Operator =>
@@ -4195,6 +4196,7 @@ package body Vhdl.Sem_Expr is
          return Null_Iir;
       end if;
       Check_Read (Res);
+      Res := Eval_Expr_If_Static (Res);
       Set_Expression (Expr, Res);
 
       --  LRM93 7.4.1 Locally static primaries
@@ -4223,7 +4225,14 @@ package body Vhdl.Sem_Expr is
       end case;
 
       --  Emit a warning if the value is known not to be within the bounds.
-      Eval_Check_Bound (Res, N_Type);
+      if Get_Expr_Staticness (Res) = Locally
+        and then not Eval_Is_In_Bound (Res, N_Type)
+      then
+         Warning_Msg_Sem
+           (Warnid_Runtime_Error, +Expr,
+            "static expression out of prefix type bounds");
+         return Build_Overflow (Expr, N_Type);
+      end if;
 
       return Expr;
    end Sem_Qualified_Expression;
-- 
cgit v1.2.3