[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Bug with '#line' directive in bison 3.0.2
From: |
Akim Demaille |
Subject: |
Re: Bug with '#line' directive in bison 3.0.2 |
Date: |
Sun, 4 Jan 2015 14:28:01 +0100 |
> Le 29 sept. 2014 à 03:43, Stephen Cameron <address@hidden> a écrit :
>
> Hi,
>
> I think I have found a bug in bison v. 3.0.2.
>
> address@hidden ~/github/simple-expression-parser $ yacc --version
> bison (GNU Bison) 3.0.2
> Written by Robert Corbett and Richard Stallman.
>
> Copyright (C) 2013 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions. There is NO
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> address@hidden ~/github/simple-expression-parser $
>
> Note that is the version of bison shipped with e.g. Linux Mint 17.
>
> Below is some output (y.tab.h) of yacc (bison) v 3.0.2
>
> Notice the '#line' directive which does not start at the beginning of a
> line:
>
> "union #line 49 "expression-parser.y" /* yacc.c:1909 */"
>
> gcc will not compile this. I think that means it's a bug in bison.
> Earlier versions of bison produce correct output (e.g. v. 2.5 works
> correctly, and the '#line' directive begins on a new line.)
>
> -------8<--------8<-------8<-------8<--------8<-------8<-------8<--------8<-------8<
> [...]
> /* Value type. */
> #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
> typedef union #line 49 "expression-parser.y" /* yacc.c:1909 */
> valtype
> YYSTYPE;
> union #line 49 "expression-parser.y" /* yacc.c:1909 */
> valtype
>
> {
> #line 49 "expression-parser.y" /* yacc.c:1909 */
>
> struct parser_value_type {
> double dval;
> long long ival;
> int has_dval;
> int has_error;
> } v;
>
> #line 77 "y.tab.h" /* yacc.c:1909 */
> };
> # define YYSTYPE_IS_TRIVIAL 1
> [...]
> -------8<--------8<-------8<-------8<--------8<-------8<-------8<--------8<-------8<
>
> The program which caused this is a simple arithmetic expression parser
> (basic yacc 101 stuff). It is here:
> https://github.com/smcameron/simple-expression-parser
Hi!
I'm sorry about this issue. I will apply the following patch,
which should address your issue. I'm curious though: why exactly
do you provide a tag name to the %union? What is wrong with just
using YYSTYPE?
commit 9e0f2feae1ca02c97c56ca03dd974afdf87748d6
Author: Akim Demaille <address@hidden>
Date: Sun Jan 4 14:16:23 2015 +0100
%union: fix the support for named %union
Bison supports a union tag, for obscure reasons. But it does a poor
job at it, especially since Bison 3.0.
Reported by Stephen Cameron and Tobias Frost.
It did not ensure that the name was not given several times. An easy
way to do this is to make the %union tag be handled as a %define
variable, as they cannot be defined several times.
Since Bison 3.0, the synclines were wrongly placed, resulting in
invalid code. Addressing this issue, because of the way the union tag
was stored (as a code muscle), would have been tedious. Unless we
rather define the %union tag as a %percent variable, whose synclines
are easier to manipulate.
So replace the b4_union_name muscle by the api.value.union.name
%define variable, document, and check.
* data/bison.m4: Make sure that api.value.union.name has a keyword value.
* data/c++.m4: Make sure that api.value.union.name is not defined.
* data/c.m4 (b4_union_name): No longer use it, use api.value.union.name.
* doc/bison.texi (%define Summary): Document it.
* src/parse-gram.y (union_name): No longer define b4_uion_name, but
api.value.union.name.
* tests/input.at (Redefined %union name): New.
* tests/synclines.at (%union name syncline): New.
* tests/types.at: Check named %unions.
diff --git a/THANKS b/THANKS
index 4559a90..943cbb1 100644
--- a/THANKS
+++ b/THANKS
@@ -126,6 +126,7 @@ Sebastien Fricker address@hidden
Sergei Steshenko address@hidden
Shura address@hidden
Stefano Lattarini address@hidden
+Stephen Cameron address@hidden
Steve Murphy address@hidden
Sum Wu address@hidden
Théophile Ranquet address@hidden
@@ -133,6 +134,7 @@ Thiru Ramakrishnan address@hidden
Tim Josling address@hidden
Tim Landscheidt address@hidden
Tim Van Holder address@hidden
+Tobias Frost address@hidden
Tom Lane address@hidden
Tom Tromey address@hidden
Tommy Nordgren address@hidden
diff --git a/data/bison.m4 b/data/bison.m4
index c443032..967aaaa 100644
--- a/data/bison.m4
+++ b/data/bison.m4
@@ -1061,3 +1061,6 @@ b4_percent_define_ifdef([api.value.type],
[['%s' and '%s' cannot be used together]],
[%yacc],
[%define api.value.type "union"])])])])
+
+# api.value.union.name.
+b4_percent_define_check_kind([api.value.union.name], [keyword])
diff --git a/data/c++.m4 b/data/c++.m4
index 4927899..e4559be 100644
--- a/data/c++.m4
+++ b/data/c++.m4
@@ -17,6 +17,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# Sanity checks, before defaults installed by c.m4.
+b4_percent_define_ifdef([[api.value.union.name]],
+ [b4_complain_at(b4_percent_define_get_loc([[api.value.union.name]]),
+ [named %union is invalid in C++])])
+
m4_include(b4_pkgdatadir/[c.m4])
# b4_comment(TEXT, [PREFIX])
diff --git a/data/c.m4 b/data/c.m4
index 1f1a23f..16713de 100644
--- a/data/c.m4
+++ b/data/c.m4
@@ -97,7 +97,8 @@ m4_define([b4_api_PREFIX],
m4_define_default([b4_prefix], [b4_api_prefix])
# If the %union is not named, its name is YYSTYPE.
-m4_define_default([b4_union_name], [b4_api_PREFIX[]STYPE])
+b4_percent_define_default([[api.value.union.name]],
+ [b4_api_PREFIX[][STYPE]])
## ------------------------ ##
@@ -608,10 +609,9 @@ m4_copy_force([b4_symbol_value_union], [b4_symbol_value])
])
-# ---------------- #
-# api.value.type. #
-# ---------------- #
-
+# -------------------------- #
+# api.value.type = variant. #
+# -------------------------- #
# b4_value_type_setup_variant
# ---------------------------
@@ -686,11 +686,12 @@ typedef ]b4_percent_define_get([[api.value.type]])[
]b4_api_PREFIX[STYPE;
[m4_bmatch(b4_percent_define_get([[api.value.type]]),
[union\|union-directive],
[[#if ! defined ]b4_api_PREFIX[STYPE && ! defined
]b4_api_PREFIX[STYPE_IS_DECLARED
-typedef union ]b4_union_name[ ]b4_api_PREFIX[STYPE;
-union ]b4_union_name[
+]b4_percent_define_get_syncline([[api.value.union.name]])[
+union ]b4_percent_define_get([[api.value.union.name]])[
{
]b4_user_union_members[
};
+typedef union ]b4_percent_define_get([[api.value.union.name]])[
]b4_api_PREFIX[STYPE;
# define ]b4_api_PREFIX[STYPE_IS_TRIVIAL 1
# define ]b4_api_PREFIX[STYPE_IS_DECLARED 1
#endif
diff --git a/doc/bison.texi b/doc/bison.texi
index 665664b..f33fc15 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -3851,7 +3851,7 @@ example:
@noindent
specifies the union tag @code{value}, so the corresponding C type is
@code{union value}. If you do not specify a tag, it defaults to
address@hidden
address@hidden (@pxref{%define Summary,,api.value.union.name}).
As another extension to POSIX, you may specify multiple @code{%union}
declarations; their contents are concatenated. However, only the first
@@ -6014,12 +6014,12 @@ Use this @var{type} as semantic value.
@item Default Value:
@itemize @minus
@item
address@hidden if @code{%union} is used, otherwise @dots{}
address@hidden if @code{%union} is used, otherwise @dots{}
@item
@code{int} if type tags are used (i.e., @samp{%token <@var{type}>@dots{}} or
address@hidden <@var{type}>@dots{}} is used), otherwise @dots{}
address@hidden <@var{type}>@dots{}} is used), otherwise @dots{}
@item
address@hidden""}
+undefined.
@end itemize
@item History:
@@ -6030,6 +6030,30 @@ introduced in Bison 3.0. Was introduced for Java only
in 2.3b as
@c api.value.type
address@hidden ==================================================
api.value.union.name
address@hidden Directive {%define api.value.union.name} @var{name}
address@hidden @bullet
address@hidden Language(s):
+C
+
address@hidden Purpose:
+The tag of the generated @code{union} (@emph{not} the name of the
address@hidden). This variable is set to @address@hidden when @samp{%union
address@hidden is used. There is no clear reason to give this union a name.
+
address@hidden Accepted Values:
+Any valid identifier.
+
address@hidden Default Value:
address@hidden
+
address@hidden History:
+Introduced in Bison 3.0.3.
address@hidden itemize
address@hidden deffn
address@hidden api.value.type
+
+
@c ================================================== location_type
@deffn Directive {%define location_type}
Obsoleted by @code{api.location.type} since Bison 2.7.
diff --git a/src/parse-gram.y b/src/parse-gram.y
index 741d743..6a68071 100644
--- a/src/parse-gram.y
+++ b/src/parse-gram.y
@@ -421,7 +421,9 @@ code_props_type:
union_name:
%empty {}
-| ID { muscle_code_grow ("union_name", $1, @1); }
+| ID { muscle_percent_define_insert ("api.value.union.name",
+ @1, muscle_keyword, $1,
+ MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); }
;
grammar_declaration:
diff --git a/tests/input.at b/tests/input.at
index cec82dd..33da53d 100644
--- a/tests/input.at
+++ b/tests/input.at
@@ -1904,6 +1904,51 @@ m4_popdef([AT_TEST])
AT_CLEANUP
+## ----------------------- ##
+## Redefined %union name. ##
+## ----------------------- ##
+
+AT_SETUP([[Redefined %union name]])
+
+# AT_TEST(DIRECTIVES, ERROR)
+# --------------------------
+m4_pushdef([AT_TEST],
+[AT_DATA([[input.y]],
+[$1
+%%
+exp: %empty;
+])
+
+AT_BISON_CHECK([[input.y]], [[1]], [[]],
+[$2])
+])
+
+AT_TEST([[%union foo {};
+%union {};
+%union foo {};
+%define api.value.union.name foo]],
+[[input.y:3.8-10: error: %define variable 'api.value.union.name' redefined
+input.y:1.8-10: previous definition
+input.y:4.9-28: error: %define variable 'api.value.union.name' redefined
+input.y:3.8-10: previous definition
+]])
+
+AT_TEST([[%define api.value.union.name {foo}]],
+[[input.y:1.9-28: error: %define variable 'api.value.union.name' requires
keyword values
+input.y:1.9-28: error: %define variable 'api.value.union.name' is not used
+]])
+
+AT_TEST([[%define api.value.union.name "foo"]],
+[[input.y:1.9-28: error: %define variable 'api.value.union.name' requires
keyword values
+input.y:1.9-28: error: %define variable 'api.value.union.name' is not used
+]])
+
+m4_popdef([AT_TEST])
+AT_CLEANUP
+
+
+
+
## -------------- ##
## Stray $ or @. ##
## -------------- ##
diff --git a/tests/synclines.at b/tests/synclines.at
index 72d5d85..77499b7 100644
--- a/tests/synclines.at
+++ b/tests/synclines.at
@@ -182,6 +182,35 @@ exp: '0';
])
+## ---------------------- ##
+## %union name syncline. ##
+## ---------------------- ##
+
+# Check that invalid union names are properly reported in the
+# source file.
+AT_SETUP([%union name syncline])
+AT_BISON_OPTION_PUSHDEFS
+AT_DATA([[input.y]],
+[[%union break
+{
+ char dummy;
+}
+%{
+]AT_YYERROR_DECLARE_EXTERN[
+]AT_YYLEX_DECLARE_EXTERN[
+%}
+%%
+exp: '0';
+%%
+]])
+
+AT_BISON_CHECK([-o input.c input.y])
+AT_SYNCLINES_COMPILE([input.c])
+AT_CHECK([[grep '^input.y:1' stdout]], 0, [ignore])
+AT_BISON_OPTION_POPDEFS
+AT_CLEANUP
+
+
## ----------------------- ##
## Postprologue syncline. ##
## ----------------------- ##
diff --git a/tests/types.at b/tests/types.at
index 29f51e2..8ddf694 100644
--- a/tests/types.at
+++ b/tests/types.at
@@ -197,18 +197,23 @@ m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc],
[glr.cc]],
AT_VAL.fval = .2f],
[10 0.2])
- # A %union.
- AT_TEST([%skeleton "]b4_skel["
- %union { float fval; int ival; };],
- [%token <ival> '1';
- %token <fval> '2';],
- ['1' '2' { printf ("%d %2.1f\n", $1, $2); }],
- ["12"],
- [if (res == '1')
- AT_VAL.ival = 10;
- else
- AT_VAL.fval = 0.2f],
- [10 0.2])
+ # A %union and a named %union. In C++ named %union is an error.
+ m4_foreach([b4_union],
+ [m4_bmatch(b4_skel, [\.cc$],
+ [[%union]],
+ [[%union], [%union foo],
+ [%define api.value.union.name foo; %union]])],
+ [AT_TEST([%skeleton "]b4_skel["
+ ]b4_union[ { float fval; int ival; };],
+ [%token <ival> '1';
+ %token <fval> '2';],
+ ['1' '2' { printf ("%d %2.1f\n", $1, $2); }],
+ ["12"],
+ [if (res == '1')
+ AT_VAL.ival = 10;
+ else
+ AT_VAL.fval = 0.2f],
+ [10 0.2])])
# A Bison-defined union.
# The tokens names are not available directly in C++, we use their
@@ -249,3 +254,22 @@ m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc],
[glr.cc]],
m4_popdef([AT_TEST])
m4_popdef([_AT_TEST])
+
+
+## ------------------- ##
+## C++: Named %union. ##
+## ------------------- ##
+
+m4_foreach([b4_skel], [[lalr1.cc], [glr.cc]],
+[AT_SETUP([b4_skel: Named %union])
+AT_DATA([input.y],
+[%skeleton "]b4_skel["
+%union foo { float fval; int ival; };
+%%
+exp: %empty;
+])
+AT_BISON_CHECK([input.y], 1, [],
+[[input.y:2.8-10: error: named %union is invalid in C++
+]])
+AT_CLEANUP
+])
- Re: Bug with '#line' directive in bison 3.0.2,
Akim Demaille <=