I am thinking, since integral denotations are always positive (-100 is
the application of the monadic standard - operator to 100) the new error
makes it impossible to write something like  -2147483648, forcing the
user to write something like  -2147483647-1 instead.

This is not very user friendly.

A possible solution would be to annotate INT_DENOTATION AST nodes that
are operands of a - operator with a flag, and not emit the error if

1) the flag is set,
2) the result of negation would be in-range for the mode of the formula,
3) the tree INTEGER_CST can actually hold the resulting value

This way, the vast majority of these -N denotations would be valid.

The annotation would be done by a68_lower_denotation before lowering the
operand, or alternatively in some of the parser passes.  Since this
really is the result of the two's complement used by tree integers, I
think the first would be preferable.

WDYT?

> Hello James.
>
> I just installed the patch on your behalf.
> Thank you!
>
>> Signed-off-by: James Bohl <[email protected]>
>>
>> gcc/algol68/ChangeLog
>>
>>         * a68-low-units.cc (a68_lower_denotation): Add error on
>>         integral denotation overflow.
>>
>> gcc/testsuite/ChangeLog
>>
>>         * algol68/compile/error-denotation-1.a68: New test.
>>         * algol68/compile/error-denotation-2.a68: Likewise.
>>         * algol68/compile/error-denotation-3.a68: Likewise.
>>         * algol68/execute/plusab-1.a68: Fixed denotation overflow.
>> ---
>>  gcc/algol68/a68-low-units.cc                         | 12 ++++++++++++
>>  gcc/testsuite/algol68/compile/error-denotation-1.a68 |  4 ++++
>>  gcc/testsuite/algol68/compile/error-denotation-2.a68 |  6 ++++++
>>  gcc/testsuite/algol68/compile/error-denotation-3.a68 |  6 ++++++
>>  gcc/testsuite/algol68/execute/plusab-1.a68           | 10 +++++-----
>>  5 files changed, 33 insertions(+), 5 deletions(-)
>>  create mode 100644 gcc/testsuite/algol68/compile/error-denotation-1.a68
>>  create mode 100644 gcc/testsuite/algol68/compile/error-denotation-2.a68
>>  create mode 100644 gcc/testsuite/algol68/compile/error-denotation-3.a68
>>
>> diff --git a/gcc/algol68/a68-low-units.cc b/gcc/algol68/a68-low-units.cc
>> index ba0ab5e2382..8257d2dc96c 100644
>> --- a/gcc/algol68/a68-low-units.cc
>> +++ b/gcc/algol68/a68-low-units.cc
>> @@ -41,6 +41,7 @@
>>  #include "convert.h"
>>  
>>  #include "a68.h"
>> +#include "a68-pretty-print.h"
>>  
>>  /* Note that enclosed clauses, which are units, are handled in
>>     a68-low-clauses.  */
>> @@ -250,8 +251,19 @@ a68_lower_denotation (NODE_T *p, LOW_CTX_T ctx)
>>      s = SUB (p);
>>  
>>        type = CTYPE (moid);
>> +      errno = 0;
>> +#if defined(INT64_T_IS_LONG)
>>        int64_t val = strtol (NSYMBOL (s), &end, 10);
>> +#else
>> +      int64_t val = strtoll (NSYMBOL (s), &end, 10);
>> +#endif
>>        gcc_assert (end[0] == '\0');
>> +      if (errno == ERANGE || val > wi::max_value (type).to_shwi ())
>> +    {
>> +      a68_moid_format_token m (moid);
>> +      a68_error (s, "denotation is too large for %e", &m);
>> +    }
>> +
>>        return build_int_cst (type, val);
>>      }
>>    if (moid == M_BITS
>> diff --git a/gcc/testsuite/algol68/compile/error-denotation-1.a68 
>> b/gcc/testsuite/algol68/compile/error-denotation-1.a68
>> new file mode 100644
>> index 00000000000..f911cc380b8
>> --- /dev/null
>> +++ b/gcc/testsuite/algol68/compile/error-denotation-1.a68
>> @@ -0,0 +1,4 @@
>> +{ dg-options {-fstropping=supper} }
>> +begin int i0 := 123456789012345678901234567890; { dg-error "denotation is 
>> too large for int" }
>> +      skip
>> +end
>> diff --git a/gcc/testsuite/algol68/compile/error-denotation-2.a68 
>> b/gcc/testsuite/algol68/compile/error-denotation-2.a68
>> new file mode 100644
>> index 00000000000..3aa1ef97bae
>> --- /dev/null
>> +++ b/gcc/testsuite/algol68/compile/error-denotation-2.a68
>> @@ -0,0 +1,6 @@
>> +{ dg-options {-fstropping=supper} }
>> +{ dg-require-effective-target int32 }
>> +begin int i0 := 2147483648; { dg-error "denotation is too large for int" }
>> +      int i1 := 2147483647;
>> +      skip
>> +end
>> diff --git a/gcc/testsuite/algol68/compile/error-denotation-3.a68 
>> b/gcc/testsuite/algol68/compile/error-denotation-3.a68
>> new file mode 100644
>> index 00000000000..ed27dc1c5be
>> --- /dev/null
>> +++ b/gcc/testsuite/algol68/compile/error-denotation-3.a68
>> @@ -0,0 +1,6 @@
>> +{ dg-options {-fstropping=supper} }
>> +{ 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;
>> +      skip
>> +end
>> diff --git a/gcc/testsuite/algol68/execute/plusab-1.a68 
>> b/gcc/testsuite/algol68/execute/plusab-1.a68
>> index 8de4e97b046..48865f8a1fe 100644
>> --- a/gcc/testsuite/algol68/execute/plusab-1.a68
>> +++ b/gcc/testsuite/algol68/execute/plusab-1.a68
>> @@ -12,11 +12,11 @@ BEGIN BEGIN INT i := 10;
>>              i PLUSAB SHORT 100;
>>              ASSERT (i = SHORT 1200)
>>        END;
>> -      BEGIN SHORT SHORT INT i := SHORT SHORT 10000;
>> -            i +:= SHORT SHORT 1000;
>> -            ASSERT (i = SHORT SHORT 11000);
>> -            i PLUSAB SHORT SHORT 1000;
>> -            ASSERT (i = SHORT SHORT 12000)
>> +      BEGIN SHORT SHORT INT i := SHORT SHORT 100;
>> +            i +:= SHORT SHORT 10;
>> +            ASSERT (i = SHORT SHORT 110);
>> +            i PLUSAB SHORT SHORT 10;
>> +            ASSERT (i = SHORT SHORT 120)
>>        END;
>>  
>>        BEGIN LONG INT i := LONG 1000;

Reply via email to