From: Akim Demaille Date: Wed, 31 Dec 2014 13:15:06 +0000 (+0100) Subject: yacc.c: fix broken union when api.value.type=union and %defines are used X-Git-Tag: v3.0.3~21 X-Git-Url: https://git.saurik.com/bison.git/commitdiff_plain/8d4dc896cb3aac3afaf82130a137c9d1afe37e48 yacc.c: fix broken union when api.value.type=union and %defines are used Reported by Rich Wilson. * data/c.m4 (b4_symbol_type_register): Append to b4_union_members, not b4_user_union_members. The latter invokes the former, but it is the former which is reinitialized to empty by b4_value_type_setup_union. * tests/types.at: Check it. This reveals another bug, this time in the case of glr.c parsers. * data/glr.c: Generate the header file before the implementation file, to be sure that the setup is run before what depends on it. --- diff --git a/NEWS b/NEWS index 9c5cb42f..cb2cd641 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,11 @@ GNU Bison NEWS ** Bug fixes +*** %define api.value.type union with %defines + + The yacc.c and glr.c parsers were broken when %defines was used + together with "%define api.value.type union". + *** Redeclarations are reported in proper order On diff --git a/THANKS b/THANKS index 780ecd5b..1b1ff716 100644 --- a/THANKS +++ b/THANKS @@ -112,6 +112,7 @@ Quoc Peyrot chojin@lrde.epita.fr R Blake blakers@mac.com Raja R Harinath harinath@cs.umn.edu Ralf Wildenhues Ralf.Wildenhues@gmx.de +Rich Wilson richaw@gmail.com Richard Stallman rms@gnu.org Rici Lake ricilake@gmail.com Rob Conde rob.conde@ai-solutions.com diff --git a/data/c.m4 b/data/c.m4 index 7f851448..1f1a23fa 100644 --- a/data/c.m4 +++ b/data/c.m4 @@ -560,15 +560,15 @@ b4_locations_if([, yylocationp])[]b4_user_args[); # b4_symbol_type_register(SYMBOL-NUM) # ----------------------------------- # Symbol SYMBOL-NUM has a type (for variant) instead of a type-tag. -# Extend the definition of %union's body with a field of that type, -# and extend the symbol's "type" field to point to the field name, -# instead of the type name. +# Extend the definition of %union's body (b4_union_members) with a +# field of that type, and extend the symbol's "type" field to point to +# the field name, instead of the type name. m4_define([b4_symbol_type_register], [m4_define([b4_symbol($1, type_tag)], [b4_symbol_if([$1], [has_id], [b4_symbol([$1], [id])], [yytype_[]b4_symbol([$1], [number])])])dnl -m4_append([b4_user_union_members], +m4_append([b4_union_members], m4_expand([ b4_symbol_tag_comment([$1])dnl b4_symbol([$1], [type]) b4_symbol([$1], [type_tag]);])) diff --git a/data/glr.c b/data/glr.c index 236a4b41..f34af1f2 100644 --- a/data/glr.c +++ b/data/glr.c @@ -178,6 +178,39 @@ m4_if(b4_skeleton, ["glr.c"], ## Output files. ## ## -------------- ## +# Unfortunately the order of generation between the header and the +# implementation file matters (for glr.c) because of the current +# implementation of api.value.type=union. In that case we still use a +# union for YYSTYPE, but we generate the contents of this union when +# setting up YYSTYPE. This is needed for other aspects, such as +# defining yy_symbol_value_print, since we need to now the name of the +# members of this union. +# +# To avoid this issue, just generate the header before the +# implementation file. But we should also make them more independant. + +# ----------------- # +# The header file. # +# ----------------- # + +# glr.cc produces its own header. +m4_if(b4_skeleton, ["glr.c"], +[b4_defines_if( +[b4_output_begin([b4_spec_defines_file]) +b4_copyright([Skeleton interface for Bison GLR parsers in C], + [2002-2014])[ + +]b4_cpp_guard_open([b4_spec_defines_file])[ +]b4_shared_declarations[ +]b4_cpp_guard_close([b4_spec_defines_file])[ +]b4_output_end() +])]) + + +# ------------------------- # +# The implementation file. # +# ------------------------- # + b4_output_begin([b4_parser_file_name]) b4_copyright([Skeleton implementation for Bison GLR parsers in C], [2002-2014])[ @@ -2550,16 +2583,3 @@ m4_if(b4_prefix, [yy], [], ]b4_epilogue[]dnl b4_output_end() - -# glr.cc produces its own header. -m4_if(b4_skeleton, ["glr.c"], -[b4_defines_if( -[b4_output_begin([b4_spec_defines_file]) -b4_copyright([Skeleton interface for Bison GLR parsers in C], - [2002-2014])[ - -]b4_cpp_guard_open([b4_spec_defines_file])[ -]b4_shared_declarations[ -]b4_cpp_guard_close([b4_spec_defines_file])[ -]b4_output_end() -])]) diff --git a/tests/types.at b/tests/types.at index 2c9203e1..29f51e2f 100644 --- a/tests/types.at +++ b/tests/types.at @@ -61,15 +61,16 @@ AT_CLEANUP ## api.value.type. ## ## ---------------- ## -# AT_TEST($1: BISON-DIRECTIVES, -# $2: MORE-BISON-DIRECTIVES, -# $3: PARSER-ACTION, -# $4: INPUT, $5: SCANNER-ACTION, -# $6: RESULT) +# _AT_TEST($1: BISON-DIRECTIVES, +# $2: MORE-BISON-DIRECTIVES, +# $3: PARSER-ACTION, +# $4: INPUT, +# $5: SCANNER-ACTION, +# $6: RESULT) # -------------------------------------- # Compile the grammar and check the expected result. # BISON-DIRECTIVES are passed to AT_SETUP, contrary to MORE-BISON-DIRECTIVES. -m4_pushdef([AT_TEST], +m4_pushdef([_AT_TEST], [ AT_SETUP([$1]) AT_KEYWORDS([api.value.type]) @@ -105,6 +106,25 @@ AT_BISON_OPTION_POPDEFS AT_CLEANUP ]) +# AT_TEST($1: BISON-DIRECTIVES, +# $2: MORE-BISON-DIRECTIVES, +# $3: PARSER-ACTION, +# $4: INPUT, +# $5: SCANNER-ACTION, +# $6: RESULT) +# -------------------------------------- +# Check with and without %defines, to avoid regressions. It turns out +# that in that case yacc.c calls the set-up of the %union twice, +# because YYSTYPE is defined once in the header, and once in the +# implementation file (eventually it'd be better to include the header +# file, but that's another story). Unfortunately running these macros +# a second time doubled the side-effects and resulted in a double +# definition of the union members. +m4_pushdef([AT_TEST], +[_AT_TEST([$1], [$2], [$3], [$4], [$5], [$6]) + _AT_TEST([$1 %defines], [$2], [$3], [$4], [$5], [$6]) +]) + m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]], [# A built-in type. AT_TEST([%skeleton "]b4_skel[" @@ -228,3 +248,4 @@ m4_foreach([b4_skel], [[yacc.c], [glr.c], [lalr1.cc], [glr.cc]], ]) m4_popdef([AT_TEST]) +m4_popdef([_AT_TEST])