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