Signed-off-by: James Bohl <[email protected]>

gcc/algol68/ChangeLog

        * a68-low-prelude.cc (a68_lower_negate2): Annotate denotation
        as being negated.
        * a68-low-units.cc (a68_lower_denotation): Allow the full range
        of negative values if the denotation is negated.
        * a68-types.h (struct NODE_T): Add negated field.
        (NEGATED): Define.
        * a68-parser.cc (a68_new_node): Initialize NEGATED.

gcc/testsuite/ChangeLog

        * algol68/compile/error-denotation-2.a68: Check for no error on
        minimum negative value.
        * algol68/compile/error-denotation-3.a68: Likewise.
---
 gcc/algol68/a68-low-prelude.cc                       |  9 +++++++++
 gcc/algol68/a68-low-units.cc                         | 10 +++++++---
 gcc/algol68/a68-parser.cc                            |  1 +
 gcc/algol68/a68-types.h                              |  6 +++++-
 gcc/testsuite/algol68/compile/error-denotation-2.a68 |  1 +
 gcc/testsuite/algol68/compile/error-denotation-3.a68 |  1 +
 6 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/gcc/algol68/a68-low-prelude.cc b/gcc/algol68/a68-low-prelude.cc
index 8b9d973327f..7fdac27f3a2 100644
--- a/gcc/algol68/a68-low-prelude.cc
+++ b/gcc/algol68/a68-low-prelude.cc
@@ -90,6 +90,15 @@ a68_lower_confirm2 (NODE_T *p, LOW_CTX_T ctx)
 tree
 a68_lower_negate2 (NODE_T *p, LOW_CTX_T ctx)
 {
+  /* Annotate denotations as being negated.  */
+  NODE_T *s = NEXT (SUB (p));
+  if (ATTRIBUTE (s) == SECONDARY
+      && ATTRIBUTE (SUB (s)) == PRIMARY
+      && ATTRIBUTE (SUB (SUB (s))) == DENOTATION)
+    {
+      NEGATED (SUB (SUB (s))) = true;
+    }
+
   return fold_build1_loc (a68_get_node_location (p),
                          NEGATE_EXPR,
                          CTYPE (MOID (p)),
diff --git a/gcc/algol68/a68-low-units.cc b/gcc/algol68/a68-low-units.cc
index 8257d2dc96c..86eb68cc141 100644
--- a/gcc/algol68/a68-low-units.cc
+++ b/gcc/algol68/a68-low-units.cc
@@ -253,12 +253,16 @@ a68_lower_denotation (NODE_T *p, LOW_CTX_T ctx)
       type = CTYPE (moid);
       errno = 0;
 #if defined(INT64_T_IS_LONG)
-      int64_t val = strtol (NSYMBOL (s), &end, 10);
+      uint64_t val = strtoul (NSYMBOL (s), &end, 10);
 #else
-      int64_t val = strtoll (NSYMBOL (s), &end, 10);
+      uint64_t val = strtoull (NSYMBOL (s), &end, 10);
 #endif
       gcc_assert (end[0] == '\0');
-      if (errno == ERANGE || val > wi::max_value (type).to_shwi ())
+      uint64_t max_positive = uint64_t (wi::max_value (type).to_shwi ());
+      uint64_t max_negative = -uint64_t (wi::min_value (type).to_shwi ());
+      if (errno == ERANGE
+         || (NEGATED (p) && (val > max_negative))
+         || (!NEGATED (p) && (val > max_positive)))
        {
          a68_moid_format_token m (moid);
          a68_error (s, "denotation is too large for %e", &m);
diff --git a/gcc/algol68/a68-parser.cc b/gcc/algol68/a68-parser.cc
index 885b5f524d9..1fb97d11c93 100644
--- a/gcc/algol68/a68-parser.cc
+++ b/gcc/algol68/a68-parser.cc
@@ -670,6 +670,7 @@ a68_new_node (void)
   CDECL (z) = NULL_TREE;
   DYNAMIC_STACK_ALLOCS (z) = false;
   PUBLICIZED (z) = false;
+  NEGATED (z) = false;
   return z;
 }
 
diff --git a/gcc/algol68/a68-types.h b/gcc/algol68/a68-types.h
index ad6b2a92260..9dc3d006e9f 100644
--- a/gcc/algol68/a68-types.h
+++ b/gcc/algol68/a68-types.h
@@ -436,7 +436,9 @@ struct GTY(()) OPTIONS_T
    DEFINING_INDICANT nodes that appear in declarations marked with PUB.
 
    CDECL is a GCC GENERIC tree corresponding to a DECL_FIELD for FIELD
-   nodes.  */
+   nodes.
+
+   NEGATED is used to mark DENOTATION nodes as being negated.  */
 
 struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) NODE_T
 {
@@ -456,6 +458,7 @@ struct GTY((chain_next ("%h.next"), chain_prev 
("%h.previous"))) NODE_T
   tree cdecl;
   bool dynamic_stack_allocs;
   bool publicized;
+  bool negated;
 };
 
 #define NO_NODE ((NODE_T *) 0)
@@ -1036,6 +1039,7 @@ struct GTY(()) A68_T
 #define NCOMMENT_CHAR_IN_LINE(p) (COMMENT_CHAR_IN_LINE (INFO (p)))
 #define NCOMMENT_LINE(p) (COMMENT_LINE (INFO (p)))
 #define NCOMMENT_TYPE(p) (COMMENT_TYPE (INFO (p)))
+#define NEGATED(p) ((p)->negated)
 #define NPRAGMAT(p) (PRAGMAT (INFO (p)))
 #define NPRAGMAT_CHAR_IN_LINE(p) (PRAGMAT_CHAR_IN_LINE (INFO (p)))
 #define NPRAGMAT_LINE(p) (PRAGMAT_LINE (INFO (p)))
diff --git a/gcc/testsuite/algol68/compile/error-denotation-2.a68 
b/gcc/testsuite/algol68/compile/error-denotation-2.a68
index 3aa1ef97bae..d295e4e9cce 100644
--- a/gcc/testsuite/algol68/compile/error-denotation-2.a68
+++ b/gcc/testsuite/algol68/compile/error-denotation-2.a68
@@ -2,5 +2,6 @@
 { dg-require-effective-target int32 }
 begin int i0 := 2147483648; { dg-error "denotation is too large for int" }
       int i1 := 2147483647;
+      int i2 := -2147483648;
       skip
 end
diff --git a/gcc/testsuite/algol68/compile/error-denotation-3.a68 
b/gcc/testsuite/algol68/compile/error-denotation-3.a68
index ed27dc1c5be..67da411e03c 100644
--- a/gcc/testsuite/algol68/compile/error-denotation-3.a68
+++ b/gcc/testsuite/algol68/compile/error-denotation-3.a68
@@ -2,5 +2,6 @@
 { dg-require-effective-target longlong64 }
 begin long long int i0 := long long 9223372036854775808; { dg-error 
"denotation is too large for long long int" }
       long long int i1 := long long 9223372036854775807;
+      long long int i2 := -long long 9223372036854775808;
       skip
 end
-- 
2.52.0

Reply via email to