poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC][PATCH] pkl, testsuite: Improve detection of overflow in integer li


From: Mohammad-Reza Nabipoor
Subject: [RFC][PATCH] pkl, testsuite: Improve detection of overflow in integer literals
Date: Mon, 8 Aug 2022 03:20:26 +0430

With this commit the following integer literals are invalid:

  8N, 128B, 32768H, 2147483648, 9223372036854775808L

But to keep -8N, -128B, -32768H, -2147483648, -9223372036854775808L
valid literals, we have to consider minus sign as part of the integer
literal.  As a consequence, `1-2' is no longer a valid expression.
Instead, one has to write `1- 2'.

2022-08-08  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>

        * libpoke/pkl-lex.l (pkl_lex_get_base): Add new param `negative_p'.
        (integer_literal_overflow_p): New function for overflow check.
        (Alien token rule): Use `integer_literal_overflow_p'.
        (Offset literal rule): Adapt `pkl_lex_get_base' invocation.
        (Integer literal rule): Add optional sign recognition at the
        beginning and update integer literal overflow detection logic.
        * testsuite/poke.pkl/array-integ-33.pk: Adapt to new semantics.
        * testsuite/poke.pkl/arrays-diag-3.pk: Likewise.
        * testsuite/poke.pkl/cdiv-integers-overflow-1.pk: Likewise.
        * testsuite/poke.pkl/cdiv-integers-overflow-diag-2.pk: Likewise.
        * testsuite/poke.pkl/div-integers-overflow-1.pk: Likewise.
        * testsuite/poke.pkl/div-integers-overflow-diag-2.pk: Likewise.
        * testsuite/poke.pkl/getenv-1.pk: Likewise.
        * testsuite/poke.pkl/mod-integers-overflow-1.pk: Likewise.
        * testsuite/poke.pkl/mod-integers-overflow-diag-2.pk: Likewise.
        * testsuite/poke.pkl/neg-int-overflow-1.pk: Likewise.
        * testsuite/poke.pkl/neg-int-overflow-diag-1.pk: Likewise.
        * testsuite/poke.pkl/promo-array-arg-4.pk: Likewise.
        * testsuite/poke.pkl/promo-array-arg-5.pk: Likewise.
        * testsuite/poke.pkl/promo-array-return-5.pk: Likewise.
        * testsuite/poke.pkl/sub-integers-overflow-1.pk: Likewise.
---

Hello Jose.

With this patch, nobody can write nonsenses like 666B, but OTOH we
have to force people (including you :D) to put spaces around the binary
minus operator.

Is this a good trade-off?


Regards,
Mohammad-Reza


 ChangeLog                                     |  24 ++++
 libpoke/pkl-lex.l                             | 120 +++++++++---------
 testsuite/poke.pkl/array-integ-33.pk          |   4 +-
 testsuite/poke.pkl/arrays-diag-3.pk           |   2 +-
 .../poke.pkl/cdiv-integers-overflow-1.pk      |   2 +-
 .../poke.pkl/cdiv-integers-overflow-diag-2.pk |   2 +-
 testsuite/poke.pkl/div-integers-overflow-1.pk |   2 +-
 .../poke.pkl/div-integers-overflow-diag-2.pk  |   2 +-
 testsuite/poke.pkl/getenv-1.pk                |   2 +-
 testsuite/poke.pkl/mod-integers-overflow-1.pk |   2 +-
 .../poke.pkl/mod-integers-overflow-diag-2.pk  |   2 +-
 testsuite/poke.pkl/neg-int-overflow-1.pk      |   2 +-
 testsuite/poke.pkl/neg-int-overflow-diag-1.pk |   2 +-
 testsuite/poke.pkl/promo-array-arg-4.pk       |   4 +-
 testsuite/poke.pkl/promo-array-arg-5.pk       |   4 +-
 testsuite/poke.pkl/promo-array-return-5.pk    |   4 +-
 testsuite/poke.pkl/sub-integers-overflow-1.pk |   2 +-
 17 files changed, 103 insertions(+), 79 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index ef9187f5..85a97378 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2022-08-08  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
+
+       * libpoke/pkl-lex.l (pkl_lex_get_base): Add new param `negative_p'.
+       (integer_literal_overflow_p): New function for overflow check.
+       (Alien token rule): Use `integer_literal_overflow_p'.
+       (Offset literal rule): Adapt `pkl_lex_get_base' invocation.
+       (Integer literal rule): Add optional sign recognition at the
+       beginning and update integer literal overflow detection logic.
+       * testsuite/poke.pkl/array-integ-33.pk: Adapt to new semantics.
+       * testsuite/poke.pkl/arrays-diag-3.pk: Likewise.
+       * testsuite/poke.pkl/cdiv-integers-overflow-1.pk: Likewise.
+       * testsuite/poke.pkl/cdiv-integers-overflow-diag-2.pk: Likewise.
+       * testsuite/poke.pkl/div-integers-overflow-1.pk: Likewise.
+       * testsuite/poke.pkl/div-integers-overflow-diag-2.pk: Likewise.
+       * testsuite/poke.pkl/getenv-1.pk: Likewise.
+       * testsuite/poke.pkl/mod-integers-overflow-1.pk: Likewise.
+       * testsuite/poke.pkl/mod-integers-overflow-diag-2.pk: Likewise.
+       * testsuite/poke.pkl/neg-int-overflow-1.pk: Likewise.
+       * testsuite/poke.pkl/neg-int-overflow-diag-1.pk: Likewise.
+       * testsuite/poke.pkl/promo-array-arg-4.pk: Likewise.
+       * testsuite/poke.pkl/promo-array-arg-5.pk: Likewise.
+       * testsuite/poke.pkl/promo-array-return-5.pk: Likewise.
+       * testsuite/poke.pkl/sub-integers-overflow-1.pk: Likewise.
+
 2022-07-25  Jose E. Marchesi  <jemarch@gnu.org>
 
        * configure.ac: Bump version to 2.4.
diff --git a/libpoke/pkl-lex.l b/libpoke/pkl-lex.l
index 78f1ce1d..583b21be 100644
--- a/libpoke/pkl-lex.l
+++ b/libpoke/pkl-lex.l
@@ -101,14 +101,16 @@
 
 /* Note that the following function assumes that STR is a pointer of a
    string that satisfies the regexp
-   ({HEXCST}|{BINCST}|{OCTCST}|{DECCST}) */
+   "-"?({HEXCST}|{BINCST}|{OCTCST}|{DECCST}) */
 
 int
-pkl_lex_get_base  (const char *str, int *offset)
+pkl_lex_get_base  (const char *str, int *offset, int *negative_p)
 {
  int base = 10;
  *offset = 0;
 
+ if ((*negative_p = str[0] == '-'))
+   str++;
  if (str[0] == '0')
   {
     if (str[1] == 'x' || str[1] == 'X')
@@ -128,7 +130,51 @@ pkl_lex_get_base  (const char *str, int *offset)
     }
   }
 
- return base;
+  *offset += *negative_p;
+  return base;
+}
+
+static int
+integer_literal_overflow_p (uint64_t value, int signed_p, int negative_p,
+                            int *width)
+{
+  /* If the width is not already known (e.g., based on the suffix),
+     the type of the integer constant is the smallest signed or unsigned
+     integer capable of holding it, starting with 32 bits, in steps of
+     power of two and up to 64 bits.  But note these are positive values!  */
+
+  if (*width == 0)
+    {
+      if (value > 0x0000000080000000 && value <= 0x00000000ffffffff)
+        *width = signed_p ? 64 : 32;
+      else if (value & 0xffffffff00000000)
+        *width = 64;
+      else
+        *width = 32;
+    }
+
+  if (*width != 64)
+    {
+      uint64_t mask = 1;
+
+      mask <<= *width;
+      mask -= 1;
+      if (value & ~mask)
+        return 1;
+    }
+
+  /* Handle overflow in signed integers.  */
+  if (signed_p)
+    {
+      uint64_t limit = (uint64_t)1 << (*width - 1);
+
+      if (negative_p && value > limit)
+        return 1;
+      if (!negative_p && value >= limit)
+        return 1;
+    }
+
+  return 0;
 }
 
 %}
@@ -438,23 +484,8 @@ S ::
             int width = token->value.integer.width;
             pkl_ast_node type;
 
-            /* As with regular integer tokens, the type of the integer
-               constant is the smallest signed or unsigned integer
-               capable of holding it, starting with 32 bits, in steps
-               of power of two and up to 64 bits. */
-
-            if (width == 0)
-              {
-                if (value > 0x0000000080000000 && value <= 0x00000000ffffffff)
-                  width = signed_p ? 64 : 32;
-                else if (value & 0xffffffff00000000)
-                  width = 64;
-                else
-                  width = 32;
-              }
-
-            /* Handle overflow in signed integers. */
-            if (signed_p && value >= 0x8000000000000000)
+            if (integer_literal_overflow_p (value, signed_p,
+                                            /*negative_p (dummy)*/ 1, &width))
               return INTEGER_OVERFLOW;
 
             type = pkl_ast_make_integral_type (yyextra->ast, width, signed_p);
@@ -472,23 +503,8 @@ S ::
             int width = token->value.offset.width;
             pkl_ast_node unit, magnitude, magnitude_type, offset_type, 
unit_type;
 
-            /* As with regular integer tokens, the type of the integer
-               constant is the smallest signed or unsigned integer
-               capable of holding it, starting with 32 bits, in steps
-               of power of two and up to 64 bits. */
-
-            if (width == 0)
-              {
-                if (value > 0x0000000080000000 && value <= 0x00000000ffffffff)
-                  width = signed_p ? 64 : 32;
-                else if (value & 0xffffffff00000000)
-                  width = 64;
-                else
-                  width = 32;
-              }
-
-            /* Handle overflow in signed integers. */
-            if (signed_p && value >= 0x8000000000000000)
+            if (integer_literal_overflow_p (value, signed_p,
+                                            /*negative_p (dummy)*/ 1, &width))
               return INTEGER_OVERFLOW;
 
             /* Build the offset magnitude.  */
@@ -530,12 +546,12 @@ S ::
 
 #({HEXCST}|{BINCST}|{OCTCST}|{DECCST}) {
   char *end;
-  int base, offset;
+  int base, offset, negative_p;
   uint64_t value;
   pkl_ast_node type
      = pkl_ast_make_integral_type (yyextra->ast, 64, 0);
 
-  base = pkl_lex_get_base (yytext + 1, &offset);
+  base = pkl_lex_get_base (yytext + 1, &offset, &negative_p);
   value = strtoll (yytext + 1 + offset, &end, base);
   yylval->ast = pkl_ast_make_integer (yyextra->ast, value);
   PKL_AST_TYPE (yylval->ast) = ASTREF (type);
@@ -577,9 +593,9 @@ S ::
      return IDENTIFIER;
 }
 
-({HEXCST}|{BINCST}|{OCTCST}|{DECCST}){IS}? {
+"-"?({HEXCST}|{BINCST}|{OCTCST}|{DECCST}){IS}? {
   uint64_t value;
-  int base, offset, signed_p, width;
+  int base, offset, signed_p, width, negative_p;
   char *p, *end;
   pkl_ast_node type;
 
@@ -593,7 +609,7 @@ S ::
        *tmp = *(tmp + 1);
   }
 
-  base = pkl_lex_get_base (yytext, &offset);
+  base = pkl_lex_get_base (yytext, &offset, &negative_p);
 
   /* strtoull can fail here only in case of overflow.  */
   errno = 0;
@@ -619,28 +635,12 @@ S ::
       || ((*end != '\0') && ((*(end + 1) == 'n' || *(end + 1) == 'N'))))
     width = 4;
 
-  /* If not specified with the 'l' or 'L' suffix, the type of the
-     integer constant is the smallest signed or unsigned integer
-     capable of holding it, starting with 32 bits, in steps of power
-     of two and up to 64 bits.  But note these are positive values! */
-
-  if (width == 0)
-  {
-    if (value > 0x0000000080000000 && value <= 0x00000000ffffffff)
-      width = signed_p ? 64 : 32;
-    else if (value & 0xffffffff00000000)
-      width = 64;
-    else
-      width = 32;
-  }
-
-  /* Handle overflow in signed integers. */
-  if (signed_p && value >= 0x8000000000000000)
+  if (integer_literal_overflow_p (value, signed_p, negative_p, &width))
     return INTEGER_OVERFLOW;
 
   type = pkl_ast_make_integral_type (yyextra->ast, width, signed_p);
 
-  yylval->ast = pkl_ast_make_integer (yyextra->ast, value);
+  yylval->ast = pkl_ast_make_integer (yyextra->ast, negative_p ? -value : 
value);
   PKL_AST_TYPE (yylval->ast) = ASTREF (type);
 
   return INTEGER;
diff --git a/testsuite/poke.pkl/array-integ-33.pk 
b/testsuite/poke.pkl/array-integ-33.pk
index 3db905ea..6481063c 100644
--- a/testsuite/poke.pkl/array-integ-33.pk
+++ b/testsuite/poke.pkl/array-integ-33.pk
@@ -1,9 +1,9 @@
 /* { dg-do run } */
 
-var a = [[[[[[[[0xdeadH,0xbeefH]]]]]]]];
+var a = [[[[[[[[0xdeadUH,0xbeefUH]]]]]]]];
 
 /* { dg-command {.set obase 16} } */
 /* { dg-command {a as int<32>} } */
 /* { dg-output {0xdeadbeef\n} } */
-/* { dg-command {[[[[[[[[0xdeadH,0xbeefH]]]]]]]] as int<32>} } */
+/* { dg-command {[[[[[[[[0xdeadUH,0xbeefUH]]]]]]]] as int<32>} } */
 /* { dg-output {0xdeadbeef} } */
diff --git a/testsuite/poke.pkl/arrays-diag-3.pk 
b/testsuite/poke.pkl/arrays-diag-3.pk
index 8e16b95b..90d5adc1 100644
--- a/testsuite/poke.pkl/arrays-diag-3.pk
+++ b/testsuite/poke.pkl/arrays-diag-3.pk
@@ -1,3 +1,3 @@
 /* { dg-do compile } */
 
-var a = [0,1,.[1-2]=10]; /* { dg-error "negative" } */
+var a = [0,1,.[1 - 2]=10]; /* { dg-error "negative" } */
diff --git a/testsuite/poke.pkl/cdiv-integers-overflow-1.pk 
b/testsuite/poke.pkl/cdiv-integers-overflow-1.pk
index 327db6b0..44b1b8bc 100644
--- a/testsuite/poke.pkl/cdiv-integers-overflow-1.pk
+++ b/testsuite/poke.pkl/cdiv-integers-overflow-1.pk
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 
-var x = 0x8000_0000;
+var x = -0x8000_0000;
 
 /* { dg-command {  try x /^ -1; catch if E_overflow { print "caught\n"; } } } 
*/
 /* { dg-output "caught" } */
diff --git a/testsuite/poke.pkl/cdiv-integers-overflow-diag-2.pk 
b/testsuite/poke.pkl/cdiv-integers-overflow-diag-2.pk
index d2e2472e..d4060568 100644
--- a/testsuite/poke.pkl/cdiv-integers-overflow-diag-2.pk
+++ b/testsuite/poke.pkl/cdiv-integers-overflow-diag-2.pk
@@ -1,4 +1,4 @@
 /* { dg-do compile } */
 
 var res
-  = 0x8000_0000 /^ -1; /* { dg-error "overflow" } */
+  = -0x8000_0000 /^ -1; /* { dg-error "overflow" } */
diff --git a/testsuite/poke.pkl/div-integers-overflow-1.pk 
b/testsuite/poke.pkl/div-integers-overflow-1.pk
index 23fc279c..ba051e6a 100644
--- a/testsuite/poke.pkl/div-integers-overflow-1.pk
+++ b/testsuite/poke.pkl/div-integers-overflow-1.pk
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 
-var x = 0x8000_0000;
+var x = -0x8000_0000;
 
 /* { dg-command {  try x / -1; catch if E_overflow { print "caught\n"; } } } */
 /* { dg-output "caught" } */
diff --git a/testsuite/poke.pkl/div-integers-overflow-diag-2.pk 
b/testsuite/poke.pkl/div-integers-overflow-diag-2.pk
index e530daa8..50397b95 100644
--- a/testsuite/poke.pkl/div-integers-overflow-diag-2.pk
+++ b/testsuite/poke.pkl/div-integers-overflow-diag-2.pk
@@ -1,4 +1,4 @@
 /* { dg-do compile } */
 
 var res
-  = 0x8000_0000 / -1; /* { dg-error "overflow" } */
+  = -0x8000_0000 / -1; /* { dg-error "overflow" } */
diff --git a/testsuite/poke.pkl/getenv-1.pk b/testsuite/poke.pkl/getenv-1.pk
index 4c81f209..13d3de72 100644
--- a/testsuite/poke.pkl/getenv-1.pk
+++ b/testsuite/poke.pkl/getenv-1.pk
@@ -6,5 +6,5 @@
 var picklesdir = getenv ("POKEPICKLESDIR");
 var length = picklesdir'length;
 
-/* { dg-command { picklesdir[length-8:length] } } */
+/* { dg-command { picklesdir[length - 8:length] } } */
 /* { dg-output {"/pickles"} } */
diff --git a/testsuite/poke.pkl/mod-integers-overflow-1.pk 
b/testsuite/poke.pkl/mod-integers-overflow-1.pk
index 9452b5d6..bcdf53b5 100644
--- a/testsuite/poke.pkl/mod-integers-overflow-1.pk
+++ b/testsuite/poke.pkl/mod-integers-overflow-1.pk
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 
-var x = 0x8000_0000;
+var x = -0x8000_0000;
 
 /* { dg-command {  try x % -1; catch if E_overflow { print "caught\n"; } } } */
 /* { dg-output "caught" } */
diff --git a/testsuite/poke.pkl/mod-integers-overflow-diag-2.pk 
b/testsuite/poke.pkl/mod-integers-overflow-diag-2.pk
index 15277be3..0ebd9c91 100644
--- a/testsuite/poke.pkl/mod-integers-overflow-diag-2.pk
+++ b/testsuite/poke.pkl/mod-integers-overflow-diag-2.pk
@@ -1,4 +1,4 @@
 /* { dg-do compile } */
 
 var res
-  = 0x8000_0000 % -1; /* { dg-error "overflow" } */
+  = -0x8000_0000 % -1; /* { dg-error "overflow" } */
diff --git a/testsuite/poke.pkl/neg-int-overflow-1.pk 
b/testsuite/poke.pkl/neg-int-overflow-1.pk
index 52fad876..8d769b61 100644
--- a/testsuite/poke.pkl/neg-int-overflow-1.pk
+++ b/testsuite/poke.pkl/neg-int-overflow-1.pk
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 
-var x = 0x8000_0000;
+var x = -0x8000_0000;
 
 /* { dg-command {  try -x; catch if E_overflow { print "caught\n"; } } } */
 /* { dg-output "caught" } */
diff --git a/testsuite/poke.pkl/neg-int-overflow-diag-1.pk 
b/testsuite/poke.pkl/neg-int-overflow-diag-1.pk
index 8e152221..76074eab 100644
--- a/testsuite/poke.pkl/neg-int-overflow-diag-1.pk
+++ b/testsuite/poke.pkl/neg-int-overflow-diag-1.pk
@@ -1,4 +1,4 @@
 /* { dg-do compile } */
 
 var res
-  = -0x8000_0000; /* { dg-error "overflow" } */
+  = 0 - -0x8000_0000; /* { dg-error "overflow" } */
diff --git a/testsuite/poke.pkl/promo-array-arg-4.pk 
b/testsuite/poke.pkl/promo-array-arg-4.pk
index 23b8eeda..94dc2b85 100644
--- a/testsuite/poke.pkl/promo-array-arg-4.pk
+++ b/testsuite/poke.pkl/promo-array-arg-4.pk
@@ -1,8 +1,8 @@
 /* { dg-do run } */
 
 var x = 3;
-fun foo = (int[x-1] a) int: { return a[1]; }
-fun bar = (int[x-1][x-1] a) int: { return a[1][1]; }
+fun foo = (int[x - 1] a) int: { return a[1]; }
+fun bar = (int[x - 1][x - 1] a) int: { return a[1][1]; }
 
 /* { dg-command { foo ([1,2]) } } */
 /* { dg-output "2" } */
diff --git a/testsuite/poke.pkl/promo-array-arg-5.pk 
b/testsuite/poke.pkl/promo-array-arg-5.pk
index a4864328..1f29de4f 100644
--- a/testsuite/poke.pkl/promo-array-arg-5.pk
+++ b/testsuite/poke.pkl/promo-array-arg-5.pk
@@ -1,8 +1,8 @@
 /* { dg-do run } */
 
 var x = 3;
-fun foo = (int[x-1] a) int: { return a[1]; }
-fun bar = (int[x-1][x-1] a) int: { return a[1][1]; }
+fun foo = (int[x - 1] a) int: { return a[1]; }
+fun bar = (int[x - 1][x - 1] a) int: { return a[1][1]; }
 
 /* { dg-command { foo ([1,2] as int[]) } } */
 /* { dg-output "2" } */
diff --git a/testsuite/poke.pkl/promo-array-return-5.pk 
b/testsuite/poke.pkl/promo-array-return-5.pk
index 354fad4f..021497a7 100644
--- a/testsuite/poke.pkl/promo-array-return-5.pk
+++ b/testsuite/poke.pkl/promo-array-return-5.pk
@@ -1,8 +1,8 @@
 /* { dg-do run } */
 
 var x = 3;
-fun foo = int[x-1]: { return [1,2]; }
-fun bar = int[x-1][x-1]: { return [[1,2],[3,4]]; }
+fun foo = int[x - 1]: { return [1,2]; }
+fun bar = int[x - 1][x - 1]: { return [[1,2],[3,4]]; }
 
 /* { dg-command {foo[1]} } */
 /* { dg-output "2" } */
diff --git a/testsuite/poke.pkl/sub-integers-overflow-1.pk 
b/testsuite/poke.pkl/sub-integers-overflow-1.pk
index 3929cf0f..88be7988 100644
--- a/testsuite/poke.pkl/sub-integers-overflow-1.pk
+++ b/testsuite/poke.pkl/sub-integers-overflow-1.pk
@@ -1,6 +1,6 @@
 /* { dg-do run } */
 
-var x = 0x8000_0000 as int<32>;
+var x = 0x8000_0000U as int<32>;
 
 /* { dg-command {  try x - 1; catch if E_overflow { print "caught\n"; } } } */
 /* { dg-output "caught" } */
-- 
2.37.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]