https://gcc.gnu.org/g:adb8cde058e70bc3f9d000b91734f01f74e2dea0
commit r16-7763-gadb8cde058e70bc3f9d000b91734f01f74e2dea0 Author: James Bohl <[email protected]> Date: Fri Feb 27 07:32:16 2026 -0500 a68: Allow full range of negative values in integral denotations 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. Diff: --- 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 8b9d973327f4..7fdac27f3a23 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 8257d2dc96c7..86eb68cc141c 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 885b5f524d94..1fb97d11c93f 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 ad6b2a922609..9dc3d006e9fe 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 3aa1ef97baed..d295e4e9cce9 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 ed27dc1c5bea..67da411e03c1 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
