On 10/6/19 4:57 AM, Akim Demaille wrote:

With the appended commits, the CI is green again, and I was able to push my 
other changes.

Thanks. I reproduced the GCC 4.8 problem and installed a patch that works around it without casts (see first attached patch).


         "\"".c:1102:41: error: implicit conversion loses integer precision: 
'long' to 'int' [-Werror,-Wshorten-64-to-32]
               YYPTRDIFF_T yysize = yyssp - yyss + 1;
                           ~~~~~~   ~~~~~~~~~~~~~^~~

This is a more serious problem, as it says that YYPTRDIFF_T is 'int' on a platform where ptrdiff_t is really 'long', which means Bison-generated parsers could mishandle vary large inputs. That is, the clang diagnostic is pointing out an (unlikely) bug, and is not a false alarm.

Although I installed the second attached patch which I hope works around the immediate problem, a better fix is needed here. With a C++ compiler, the definition of YYPTRDIFF_T should not be a guess at 'int' or 'long'; it should be the proper C++ type for pointer subtraction results. When you find the time I'd be interested to see the proper portable C++ magic to do that.
>From beceb2fa9382fd44816cae382dd12ffc6a210d5e Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Sun, 6 Oct 2019 11:49:56 -0700
Subject: [PATCH 1/2] Work around GCC 4.8 false alarms without casts

* data/skeletons/yacc.c (yyparse):
Initialize yyes_capacity with a signed expression.
* tests/local.at (AT_YYLEX_DEFINE(c)):
Use enum to avoid cast.
---
 TODO                  | 8 --------
 data/skeletons/yacc.c | 2 +-
 tests/local.at        | 2 +-
 3 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/TODO b/TODO
index 0a02ff03..a5935029 100644
--- a/TODO
+++ b/TODO
@@ -117,14 +117,6 @@ compiling yacc.c code:
 
     YYPTRDIFF_T yysize = (YYPTRDIFF_T) (yyesp - *yyes + 1);
 
-Or G++ 4.8
-
-    yyes_capacity = (YYPTRDIFF_T) (sizeof yyesa / sizeof *yyes);
-
-Or GCC 4.8
-
-    int input_elts = (int) (sizeof input / sizeof input[0]);
-
 * Completion
 Several features are not available in all the backends.
 
diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c
index abe20a5f..5ef4289e 100644
--- a/data/skeletons/yacc.c
+++ b/data/skeletons/yacc.c
@@ -1490,7 +1490,7 @@ b4_function_define([[yyparse]], [[int]], b4_parse_param)[
   yystacksize = YYINITDEPTH;]b4_lac_if([[
 
   yyes = yyesa;
-  yyes_capacity = (YYPTRDIFF_T) (sizeof yyesa / sizeof *yyes);
+  yyes_capacity = ]b4_percent_define_get([[parse.lac.es-capacity-initial]])[;
   if (YYMAXDEPTH < yyes_capacity)
     yyes_capacity = YYMAXDEPTH;]])[
 
diff --git a/tests/local.at b/tests/local.at
index 579b85c3..3acb2791 100644
--- a/tests/local.at
+++ b/tests/local.at
@@ -558,7 +558,7 @@ static
   static int toknum = 0;
   int res;
   ]AT_USE_LEX_ARGS[
-  int input_elts = (int) (sizeof input / sizeof input[0]);
+  enum { input_elts = sizeof input / sizeof input[0] };
   (void) input_elts;
   assert (0 <= toknum && toknum < input_elts);
   res = input[toknum++];
-- 
2.17.1

>From 6373b90fc8f9ab2bfa19a107d44cfad3404faf20 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Sun, 6 Oct 2019 11:58:10 -0700
Subject: [PATCH 2/2] Port better to C++ platforms

* data/skeletons/yacc.c (YYPTRDIFF_T, YYPTRDIFF_MAXIMUM):
Default to long, not int.
(yy_lac_stack_realloc, yy_lac, yytnamerr, yyparse):
Avoid casts to YYPTRDIFF_T that were masking the problem.
---
 TODO                  | 13 ++++---------
 data/skeletons/yacc.c | 12 ++++++------
 2 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/TODO b/TODO
index a5935029..f3f08ce1 100644
--- a/TODO
+++ b/TODO
@@ -107,15 +107,10 @@ name they have in gcc, clang, etc.  Likewise for the complain_* series of
 functions.
 
 * Modernization
-Remove some casts made for old compilers, such as Clang++ 3.3 and 3.4 when
-compiling yacc.c code:
-
-    YYPTRDIFF_T yysize = (YYPTRDIFF_T) (yyssp - yyss + 1);
-
-    YYPTRDIFF_T yysize_old =
-      *yytop == yytop_empty ? 0 : (YYPTRDIFF_T) (*yytop - *yybottom + 1);
-
-    YYPTRDIFF_T yysize = (YYPTRDIFF_T) (yyesp - *yyes + 1);
+Fix data/skeletons/yacc.c so that it defines YYPTRDIFF_T properly for modern
+and older C++ compilers.  Currently the code defaults to defining it to
+'long' for non-GCC compilers, but it should use the proper C++ magic to
+define it to the same type as the C ptrdiff_t type.
 
 * Completion
 Several features are not available in all the backends.
diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c
index 5ef4289e..10708627 100644
--- a/data/skeletons/yacc.c
+++ b/data/skeletons/yacc.c
@@ -425,9 +425,9 @@ typedef short yytype_int16;
 #  include <stdint.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYPTRDIFF_MAXIMUM PTRDIFF_MAX
 # else
-#  define YYPTRDIFF_T int
+#  define YYPTRDIFF_T long
 #  include <limits.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYPTRDIFF_MAXIMUM INT_MAX
+#  define YYPTRDIFF_MAXIMUM LONG_MAX
 # endif
 #endif
 
@@ -857,7 +857,7 @@ yy_lac_stack_realloc (YYPTRDIFF_T *yycapacity, YYPTRDIFF_T yyadd,
                       yy_state_num **yytop, yy_state_num *yytop_empty)
 {
   YYPTRDIFF_T yysize_old =
-    *yytop == yytop_empty ? 0 : (YYPTRDIFF_T) (*yytop - *yybottom + 1);
+    *yytop == yytop_empty ? 0 : *yytop - *yybottom + 1;
   YYPTRDIFF_T yysize_new = yysize_old + yyadd;
   if (*yycapacity < yysize_new)
     {
@@ -1024,7 +1024,7 @@ yy_lac (yy_state_num *yyesa, yy_state_num **yyes,
         YYDPRINTF ((stderr, " R%d", yyrule - 1));
         if (yyesp != yyes_prev)
           {
-            YYPTRDIFF_T yysize = (YYPTRDIFF_T) (yyesp - *yyes + 1);
+            YYPTRDIFF_T yysize = yyesp - *yyes + 1;
             if (yylen < yysize)
               {
                 yyesp -= yylen;
@@ -1155,7 +1155,7 @@ yytnamerr (char *yyres, const char *yystr)
     }
 
   if (yyres)
-    return (YYPTRDIFF_T) (yystpcpy (yyres, yystr) - yyres);
+    return yystpcpy (yyres, yystr) - yyres;
   else
     return yystrlen (yystr);
 }
@@ -1535,7 +1535,7 @@ yysetstate:
 #else
     {
       /* Get the current used size of the three stacks, in elements.  */
-      YYPTRDIFF_T yysize = (YYPTRDIFF_T) (yyssp - yyss + 1);
+      YYPTRDIFF_T yysize = yyssp - yyss + 1;
 
 # if defined yyoverflow
       {
-- 
2.17.1

Reply via email to