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.
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-types.h | 6 +++++-
gcc/testsuite/algol68/compile/error-denotation-2.a68 | 1 +
gcc/testsuite/algol68/compile/error-denotation-3.a68 | 1 +
5 files changed, 23 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-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