[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: bison-2.6.4-generated parser triggers pragma warnings in GCC 4.6.3
From: |
Akim Demaille |
Subject: |
Re: bison-2.6.4-generated parser triggers pragma warnings in GCC 4.6.3 |
Date: |
Tue, 6 Nov 2012 13:43:23 +0100 |
Le 29 oct. 2012 à 17:34, Paul Eggert a écrit :
> On 10/29/2012 01:03 AM, Akim Demaille wrote:
>> So you are suggesting something different now, right?
>
> Yes.
>
>> Something like "%define initialize_yyllval_and_yylloc" if I
>> understand correctly (and translate into something dealt with
>> by Bison rather than CPP).
>
> I hadn't been thinking of it as anything requiring a directive
> at the Bison level. I was thinking only of a macro that one
> defines at the C level, to disable the warnings. I suppose
> that it could be mapped into a Bison directive too, though, if
> that's convenient.
>
> You can see an example of what I'm talking about by looking at
> the coreutils source and seeing the C code that uses
> "#ifdef lint" or "defined lint".
This is a nightmare. Trying to please GCC in all the situation
is painful work. It took me an embarrassingly large amount of
time to propose the attached patches which address yylloc only.
yylval is, I guess, yet another session of extraordinarily interesting
work.
commit 7d846072c727c9314040cb209431c98ff0d299c6
Author: Akim Demaille <address@hidden>
Date: Mon Nov 5 15:19:45 2012 +0100
yacc.c: simplify initialization
* data/yacc.c: Fuse the initializations of yyssp, yyss and the like.
Remove an obsolete comment: we do initialize these initial stack
members (in some cases).
diff --git a/data/yacc.c b/data/yacc.c
index 5d68bd4..77f86ec 100644
--- a/data/yacc.c
+++ b/data/yacc.c
@@ -1558,9 +1558,9 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
goto yyread_pushed_token;
}]])[
- yyss = yyssa;
- yyvs = yyvsa;]b4_locations_if([[
- yyls = yylsa;]])[
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;]b4_locations_if([[
+ yylsp = yyls = yylsa;]])[
yystacksize = YYINITDEPTH;]b4_lac_if([[
yyes = yyesa;
@@ -1574,14 +1574,6 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
yyerrstatus = 0;
yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
- yyssp = yyss;
- yyvsp = yyvs;]b4_locations_if([[
- yylsp = yyls;]])[
]m4_ifdef([b4_initial_action],[
b4_dollar_pushdef([m4_define([b4_dollar_dollar_used])yylval], [],
[m4_define([b4_at_dollar_used])yylloc])dnl
commit 3237f570964d5f6cccad349f946dd301448e206e
Author: Akim Demaille <address@hidden>
Date: Mon Nov 5 16:58:24 2012 +0100
yacc.c, glr.c: a better YY_LOCATION_PRINT
* data/c.m4 (b4_yy_location_print_define): New.
Now issues "short" locations, e.g., "1.1" instead of "1.1-1.1".
Was initially a function, but then we face "static but unused"
warnings.
Simpler as a macro.
* tests/local.at, data/glr.c, data/yacc.c: Use it instead of duplicating.
* tests/actions.at: Adjust expectations.
diff --git a/data/c.m4 b/data/c.m4
index 136b46e..a1013cc 100644
--- a/data/c.m4
+++ b/data/c.m4
@@ -644,8 +644,37 @@ m4_define([b4_yylloc_default_define],
#endif
]])
+# b4_yy_location_print_define
+# ---------------------------
+# Define YY_LOCATION_PRINT.
+m4_define([b4_yy_location_print_define],
+[b4_locations_if([[
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if defined ]b4_api_PREFIX[LTYPE_IS_TRIVIAL && ]b4_api_PREFIX[LTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ do { \
+ fprintf (File, "%d.%d", (Loc).first_line, (Loc).first_column); \
+ if ((Loc).first_line < (Loc).last_line) \
+ fprintf (File, "-%d.%d", (Loc).last_line, (Loc).last_column - 1); \
+ else if ((Loc).first_column < (Loc).last_column - 1) \
+ fprintf (File, "-%d", (Loc).last_column - 1); \
+ } while (0)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif]],
+[[/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif]])
+])
+
# b4_yyloc_default_define
-# ------------------------
+# -----------------------
# Define yyloc_default, which can be used to initialize location
# variables.
m4_define([b4_yyloc_default_define],
diff --git a/data/glr.c b/data/glr.c
index 89a76e3..a2992e0 100644
--- a/data/glr.c
+++ b/data/glr.c
@@ -475,28 +475,10 @@ static const ]b4_int_type_for([b4_stos])[ yystos[] =
#define YYTERROR 1
]b4_locations_if([[
-#ifndef YYLLOC_DEFAULT
]b4_yylloc_default_define[
# define YYRHSLOC(Rhs, K) ((Rhs)[K].yystate.yyloc)
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
- This macro was not mandated originally: define only if we know
- we won't break user code: when these are the locations we know. */
-
-# define YY_LOCATION_PRINT(File, Loc) \
- fprintf (File, "%d.%d-%d.%d", \
- (Loc).first_line, (Loc).first_column, \
- (Loc).last_line, (Loc).last_column)
-#endif
-]],[
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) ((void) 0)
-#endif
-])[
-
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
+]])[
+]b4_yy_location_print_define[
/* YYLEX -- calling `yylex' with the right arguments. */
#define YYLEX ]b4_c_function_call([yylex], [int], b4_lex_param)[
diff --git a/data/yacc.c b/data/yacc.c
index 77f86ec..e82264f 100644
--- a/data/yacc.c
+++ b/data/yacc.c
@@ -766,33 +766,15 @@ do
\
} \
while (YYID (0))
-
+/* Error token number */
#define YYTERROR 1
#define YYERRCODE 256
]b4_locations_if([[
]b4_yylloc_default_define[
#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
- This macro was not mandated originally: define only if we know
- we won't break user code: when these are the locations we know. */
-
-#ifndef YY_LOCATION_PRINT
-# if defined ]b4_api_PREFIX[LTYPE_IS_TRIVIAL && ]b4_api_PREFIX[LTYPE_IS_TRIVIAL
-# define YY_LOCATION_PRINT(File, Loc) \
- fprintf (File, "%d.%d-%d.%d", \
- (Loc).first_line, (Loc).first_column, \
- (Loc).last_line, (Loc).last_column)
-# else
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif]],
-[[/* This macro is provided for backward compatibility. */
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif]])[
-
+]])[
+]b4_yy_location_print_define[
/* YYLEX -- calling `yylex' with the right arguments. */
#ifdef YYLEX_PARAM
diff --git a/tests/actions.at b/tests/actions.at
index 2314c1c..fc70f48 100644
--- a/tests/actions.at
+++ b/tests/actions.at
@@ -651,29 +651,29 @@ AT_PARSER_CHECK([./input], 1,
]],
[[Starting parse
Entering state 0
-Reading a token: Next token is token 'a' (1.1-1.1: <> printer for 'a' @ 1)
-Shifting token 'a' (1.1-1.1: <> printer for 'a' @ 1)
+Reading a token: Next token is token 'a' (1.1: <> printer for 'a' @ 1)
+Shifting token 'a' (1.1: <> printer for 'a' @ 1)
Entering state 1
-Reading a token: Next token is token 'b' (1.2-1.2: 'b'/'c' printer for 'b' @ 2)
-Shifting token 'b' (1.2-1.2: 'b'/'c' printer for 'b' @ 2)
+Reading a token: Next token is token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
+Shifting token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
Entering state 3
-Reading a token: Next token is token 'c' (1.3-1.3: 'b'/'c' printer for 'c' @ 3)
-Shifting token 'c' (1.3-1.3: 'b'/'c' printer for 'c' @ 3)
+Reading a token: Next token is token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
+Shifting token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
Entering state 5
-Reading a token: Next token is token 'd' (1.4-1.4: <> printer for 'd' @ 4)
-Shifting token 'd' (1.4-1.4: <> printer for 'd' @ 4)
+Reading a token: Next token is token 'd' (1.4: <> printer for 'd' @ 4)
+Shifting token 'd' (1.4: <> printer for 'd' @ 4)
Entering state 6
Reading a token: Now at end of input.
1.5: syntax error, unexpected $end, expecting 'e'
-Error: popping token 'd' (1.4-1.4: <> printer for 'd' @ 4)
+Error: popping token 'd' (1.4: <> printer for 'd' @ 4)
Stack now 0 1 3 5
-Error: popping token 'c' (1.3-1.3: 'b'/'c' printer for 'c' @ 3)
+Error: popping token 'c' (1.3: 'b'/'c' printer for 'c' @ 3)
Stack now 0 1 3
-Error: popping token 'b' (1.2-1.2: 'b'/'c' printer for 'b' @ 2)
+Error: popping token 'b' (1.2: 'b'/'c' printer for 'b' @ 2)
Stack now 0 1
-Error: popping token 'a' (1.1-1.1: <> printer for 'a' @ 1)
+Error: popping token 'a' (1.1: <> printer for 'a' @ 1)
Stack now 0
-Cleanup: discarding lookahead token $end (1.5-1.5: )
+Cleanup: discarding lookahead token $end (1.5: )
Stack now 0
]])
@@ -895,15 +895,15 @@ AT_PARSER_CHECK([./input$1], 0,
[[Starting parse
Entering state 0
Reducing stack by rule 1 (line 46):
--> $$ = nterm start (1.1-1.1: <]]kind[[> for 'S' @ 1)
+-> $$ = nterm start (1.1: <]]kind[[> for 'S' @ 1)
Stack now 0
Entering state 1
Reading a token: Now at end of input.
-Shifting token END (1.1-1.1: <]]kind[[> for 'E' @ 1)
+Shifting token END (1.1: <]]kind[[> for 'E' @ 1)
Entering state 2
Stack now 0 1 2
-Cleanup: popping token END (1.1-1.1: <]]kind[[> for 'E' @ 1)
-Cleanup: popping nterm start (1.1-1.1: <]]kind[[> for 'S' @ 1)
+Cleanup: popping token END (1.1: <]]kind[[> for 'E' @ 1)
+Cleanup: popping nterm start (1.1: <]]kind[[> for 'S' @ 1)
]])
m4_popdef([kind])
diff --git a/tests/local.at b/tests/local.at
index 2af7971..73680c7 100644
--- a/tests/local.at
+++ b/tests/local.at
@@ -386,14 +386,7 @@ static
[[^,]+[^A-Za-z_0-9]\([A-Za-z_][A-Za-z_0-9]*\), *], [
YYUSE(\1);])dnl
AT_YYERROR_SEES_LOC_IF([[
- fprintf (stderr, "%d.%d",
- ]AT_LOC_FIRST_LINE[, ]AT_LOC_FIRST_COLUMN[);
- if (]AT_LOC_FIRST_LINE[ < ]AT_LOC_LAST_LINE[)
- fprintf (stderr, "-%d.%d",
- ]AT_LOC_LAST_LINE[, ]AT_LOC_LAST_COLUMN[ - 1);
- else if (]AT_LOC_FIRST_COLUMN[ < ]AT_LOC_LAST_COLUMN[ - 1)
- fprintf (stderr, "-%d",
- ]AT_LOC_LAST_COLUMN[ - 1);
+ YY_LOCATION_PRINT (stderr, ]AT_LOC[);
fprintf (stderr, ": ");]])[
fprintf (stderr, "%s\n", msg);
}]],
commit 4b881f6d8e00a4ba1ae30c8558800cb963ffa904
Author: Akim Demaille <address@hidden>
Date: Tue Nov 6 11:04:24 2012 +0100
glr.cc, yacc.c: initialize yylloc properly
There are several issues to address here. One is that yylloc should
be initialized when possible. Another is that the push parser needs
to update yypushed_loc when the user modified it. And if the parser
starts by a reduction of an empty, it uses the first location on the
stack, which, therefore, must also be initialized to this initial
location.
This is getting complex, especially since because initializing a
global (impure interface) is different from initializing a local
variable. To simplify, the local yylloc is not initialized during its
definition.
* data/c.m4 (b4_yyloc_default_define): Replace by...
(b4_yyloc_default): this.
Adjust dependencies.
* data/glr.cc: Initialize yylloc.
* data/yacc.c (b4_declare_scanner_communication_variables):
Initialize yylloc during its definition.
Don't define yyloc_default.
(yypush_parse): The location formal is not const, as we might
initialize it.
(yyparse): Define yyloc_default.
Use it before running the user initial action.
Possibly update the first location on the stack, and the pushed
location after the user initial action.
* tests/actions.at (Initial locations): Check that the initial
location is correct.
diff --git a/NEWS b/NEWS
index 37b8e2c..3d21470 100644
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,9 @@ GNU Bison NEWS
Nul characters are correctly displayed in error messages.
+ When possible, yylloc is correctly initialized before calling yylex. It
+ is no longer necessary to initialize it in the %initial-action.
+
* Noteworthy changes in release 2.6.4 (2012-10-23) [stable]
Bison 2.6.3's --version was incorrect. This release fixes this issue.
diff --git a/data/c.m4 b/data/c.m4
index a1013cc..8bd96b8 100644
--- a/data/c.m4
+++ b/data/c.m4
@@ -673,12 +673,11 @@ m4_define([b4_yy_location_print_define],
#endif]])
])
-# b4_yyloc_default_define
-# -----------------------
-# Define yyloc_default, which can be used to initialize location
-# variables.
-m4_define([b4_yyloc_default_define],
-[[static YYLTYPE yyloc_default
+# b4_yyloc_default
+# ----------------
+# Expand to a possible default value for yylloc.
+m4_define([b4_yyloc_default],
+[[
# if defined ]b4_api_PREFIX[LTYPE_IS_TRIVIAL && ]b4_api_PREFIX[LTYPE_IS_TRIVIAL
= { ]m4_join([, ],
m4_defn([b4_location_initial_line]),
@@ -686,5 +685,4 @@ m4_define([b4_yyloc_default_define],
m4_defn([b4_location_initial_line]),
m4_defn([b4_location_initial_column]))[ }
# endif
- ;]dnl
-])
+]])
diff --git a/data/glr.c b/data/glr.c
index a2992e0..3baacf4 100644
--- a/data/glr.c
+++ b/data/glr.c
@@ -226,8 +226,8 @@ b4_percent_code_get([[top]])[
right-hand sides. Unlike the standard yacc.c template, here we set
the default value of $$ to a zeroed-out value. Since the default
value is undefined, this behavior is technically correct. */
-static YYSTYPE yyval_default;]b4_locations_if([
-b4_yyloc_default_define])[
+static YYSTYPE yyval_default;]b4_locations_if([[
+static YYLTYPE yyloc_default]b4_yyloc_defaultl;])[
/* Copy the second part of user declarations. */
]b4_user_post_prologue
diff --git a/data/glr.cc b/data/glr.cc
index 826bc80..104bf78 100644
--- a/data/glr.cc
+++ b/data/glr.cc
@@ -87,12 +87,17 @@ m4_define([b4_yy_symbol_print_generate],
]b4_parse_param_use[]dnl
[ yyparser.yy_symbol_print_ (yytype, yyvaluep]b4_locations_if([,
yylocationp])[);
}
-]])
+]])[
+# Hijack the initial action to initialize the locations.
+]b4_locations_if([b4_percent_define_ifdef([[location_type]], [],
+[m4_define([b4_initial_action],
+[yylloc.initialize ();]m4_ifdef([b4_initial_action], [
+m4_defn([b4_initial_action])]))])])[
# Hijack the post prologue to insert early definition of YYLLOC_DEFAULT
# and declaration of yyerror.
-m4_append([b4_post_prologue],
+]m4_append([b4_post_prologue],
[b4_syncline(address@hidden@], address@hidden@])[
]b4_yylloc_default_define[
#define YYRHSLOC(Rhs, K) ((Rhs)[K].yystate.yyloc)
diff --git a/data/yacc.c b/data/yacc.c
index e82264f..6284de4 100644
--- a/data/yacc.c
+++ b/data/yacc.c
@@ -181,8 +181,7 @@ int yychar;
#else
/* Default value used for initialization, for pacifying older GCCs
or non-GCC compilers. */
-static YYSTYPE yyval_default;]b4_locations_if([
-b4_yyloc_default_define])[
+static YYSTYPE yyval_default;
# define YY_INITIAL_VALUE(Value) = Value
#endif]])[
#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
@@ -197,7 +196,8 @@ b4_yyloc_default_define])[
YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);]b4_locations_if([[
/* Location data for the lookahead symbol. */
-YYLTYPE yylloc YY_INITIAL_VALUE(yyloc_default);]])b4_pure_if([], [[
+YYLTYPE yylloc]b4_yyloc_default[;
+]])b4_pure_if([], [[
/* Number of syntax errors so far. */
int yynerrs;]])])
@@ -265,7 +265,7 @@ typedef struct ]b4_prefix[pstate ]b4_prefix[pstate;
[[b4_prefix[pstate *ps]], [[ps]]]b4_pure_if([,
[[[int pushed_char]], [[pushed_char]]],
[[b4_api_PREFIX[STYPE const *pushed_val]], [[pushed_val]]]b4_locations_if([,
- [[b4_api_PREFIX[LTYPE const *pushed_loc]],
[[pushed_loc]]]])])m4_ifset([b4_parse_param], [,
+ [[b4_api_PREFIX[LTYPE *pushed_loc]],
[[pushed_loc]]]])])m4_ifset([b4_parse_param], [,
b4_parse_param]))
b4_pull_if([b4_c_function_decl([b4_prefix[pull_parse]], [[int]],
[[b4_prefix[pstate *ps]], [[ps]]]m4_ifset([b4_parse_param], [,
@@ -1489,7 +1489,7 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
[[[yypstate *yyps]], [[yyps]]]b4_pure_if([,
[[[int yypushed_char]], [[yypushed_char]]],
[[[YYSTYPE const *yypushed_val]], [[yypushed_val]]]b4_locations_if([,
- [[[YYLTYPE const *yypushed_loc]],
[[yypushed_loc]]]])])m4_ifset([b4_parse_param], [,
+ [[[YYLTYPE *yypushed_loc]], [[yypushed_loc]]]])])m4_ifset([b4_parse_param],
[,
b4_parse_param]))], [[
@@ -1556,16 +1556,16 @@ b4_c_function_def([[yyparse]], [[int]], b4_parse_param)[
yyerrstatus = 0;
yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
-]m4_ifdef([b4_initial_action],[
+]m4_ifdef([b4_initial_action], [
b4_dollar_pushdef([m4_define([b4_dollar_dollar_used])yylval], [],
[m4_define([b4_at_dollar_used])yylloc])dnl
/* User initialization code. */
b4_user_initial_action
b4_dollar_popdef[]dnl
m4_ifdef([b4_dollar_dollar_used],[[ yyvsp[0] = yylval;
-]])dnl
-m4_ifdef([b4_at_dollar_used], [[ yylsp[0] = yylloc;
]])])dnl
+b4_locations_if([[ yylsp[0] = ]b4_push_if([b4_pure_if([*])yypushed_loc =
])[yylloc;
+]])dnl
[ goto yysetstate;
/*------------------------------------------------------------.
diff --git a/tests/actions.at b/tests/actions.at
index fc70f48..0e02239 100644
--- a/tests/actions.at
+++ b/tests/actions.at
@@ -69,6 +69,76 @@ AT_PARSER_CHECK([./input], 0,
AT_CLEANUP
+## ------------------ ##
+## Initial location. ##
+## ------------------ ##
+
+# AT_TEST(SKELETON-NAME, DIRECTIVES)
+# ----------------------------------
+# Check the the initial location is correct.
+m4_pushdef([AT_TEST],
+[AT_SETUP([Initial location: $1 $2])
+
+AT_BISON_OPTION_PUSHDEFS([%locations %skeleton "$1" $2 %parse-param { int x }])
+AT_DATA_GRAMMAR([[input.y]],
+[[%defines /* FIXME: Required by lalr1.cc in Bison 2.6. */
+%locations
+%debug
+%skeleton "$1"
+$2
+%parse-param { int x } // Useless, but used to force yyerror purity.
+%code
+{
+# include <stdio.h>
+# include <stdlib.h> // getenv
+]AT_YYERROR_DECLARE[
+]AT_YYLEX_DECLARE[
+}
+%%
+exp: { ]AT_SKEL_CC_IF([[std::cerr << @$ << std::endl]],
+ [[YY_LOCATION_PRINT(stderr, @$); fputc ('\n',
stderr)]])[; }
+%%
+]AT_YYERROR_DEFINE[
+
+]AT_YYLEX_PROTOTYPE[
+{]AT_PURE_IF([
+ YYUSE(lvalp);
+ YYUSE(llocp);], [AT_SKEL_CC_IF([
+ YYUSE(lvalp);
+ YYUSE(llocp);])])[
+ return 'x';
+}
+
+int
+main (void)
+{]AT_SKEL_CC_IF([[
+ yy::parser p (0);
+ p.set_debug_level (!!getenv("YYDEBUG"));
+ return p.parse ();]], [[
+ yydebug = !!getenv("YYDEBUG");
+ return !!yyparse (0);]])[
+}
+]])
+
+AT_FULL_COMPILE([input])
+AT_PARSER_CHECK([./input], 1, [],
+[[1.1
+1.1: syntax error
+]])
+AT_BISON_OPTION_POPDEFS
+AT_CLEANUP
+])
+
+## FIXME: test Java, and iterate over skeletons.
+AT_TEST([yacc.c])
+AT_TEST([yacc.c], [%define api.pure])
+AT_TEST([yacc.c], [%define api.push-pull both])
+AT_TEST([yacc.c], [%define api.push-pull both %define api.pure])
+AT_TEST([glr.c])
+AT_TEST([lalr1.cc])
+AT_TEST([glr.cc])
+
+m4_popdef([AT_TEST])
- Re: bison-2.6.4-generated parser triggers pragma warnings in GCC 4.6.3,
Akim Demaille <=