diff --git a/Makefile.am b/Makefile.am index 339a3c63..becd1d39 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,8 +24,10 @@ SUBDIRS = po runtime-po . aclocaldir = @aclocaldir@ aclocal_DATA = m4/bison-i18n.m4 -EXTRA_DIST = .prev-version .version \ - cfg.mk ChangeLog-1998 ChangeLog-2012 PACKAGING +EXTRA_DIST = .prev-version .version cfg.mk PACKAGING \ + ChangeLog-1998 ChangeLog-2012 ChangeLog + +dist_doc_DATA = AUTHORS COPYING NEWS README THANKS TODO ## Running the bison from this tarball. To generate our own parser, ## but also to run the tests. Of course, you ought to keep a sane diff --git a/NEWS b/NEWS index 39322da8..e6521bf9 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,41 @@ GNU Bison NEWS * Noteworthy changes in release ?.? (????-??-??) [?] +** Bug fixes + +*** Redeclarations are reported in proper order + + On + + %token FOO "foo" + %printer {} "foo" + %printer {} FOO + + bison used to report: + + /tmp/foo.yy:2.10-11: error: %printer redeclaration for FOO + %printer {} "foo" + ^^ + /tmp/foo.yy:3.10-11: previous declaration + %printer {} FOO + ^^ + + Now, the "previous" declaration is always the first one. + + +** Documentation + + Bison now installs various files in its docdir (which defaults to + '/usr/local/share/doc/bison'), including the three fully blown examples + extracted from the documentation: + + - rpcalc + Reverse polish calculator, a simple introductory example. + - mfcalc + Multi-function Calc, a calculator with memory and functions and located + error messages. + - calc++ + a calculator in C++ using variant support and token constructors. * Noteworthy changes in release 3.0.2 (2013-12-05) [stable] diff --git a/configure.ac b/configure.ac index f3dcdfd8..2658d73e 100644 --- a/configure.ac +++ b/configure.ac @@ -71,12 +71,15 @@ AC_CACHE_CHECK([whether pragma GCC diagnostic push works], CFLAGS=$save_CFLAGS]) AC_ARG_ENABLE([gcc-warnings], -[ --enable-gcc-warnings turn on lots of GCC warnings (not recommended)], +[ --enable-gcc-warnings turn on lots of GCC warnings (not recommended). + Also, issue synclines from the examples/ to + the corresponding source in the Texinfo doc.], [case $enable_gcc_warnings in yes|no) ;; *) AC_MSG_ERROR([invalid value for --gcc-warnings: $enable_gcc_warnings]);; esac], [enable_gcc_warnings=no]) +AM_CONDITIONAL([ENABLE_GCC_WARNINGS], [test "$enable_gcc_warnings" = yes]) if test "$enable_gcc_warnings" = yes; then warn_common='-Wall-Wextra -Wno-sign-compare -Wcast-align -Wdocumentation -Wformat -Wpointer-arith -Wwrite-strings' diff --git a/examples/calc++/local.mk b/examples/calc++/local.mk index d920e634..018d007a 100644 --- a/examples/calc++/local.mk +++ b/examples/calc++/local.mk @@ -27,11 +27,11 @@ SUFFIXES += .yy .stamp $(AM_V_at)$(YACCCOMPILE) -o $*.cc $< $(AM_V_at)mv -f $@.tmp $@ -$(calc_sources_generated): %D%/calc++-parser.stamp +$(calcxx_sources_generated): %D%/calc++-parser.stamp @test -f $@ || rm -f %D%/calc++-parser.stamp @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) %D%/calc++-parser.stamp CLEANFILES += \ - $(calc_sources_generated) \ + $(calcxx_sources_generated) \ %D%/calc++-parser.output \ %D%/calc++-parser.stamp \ %D%/calc++-scanner.cc @@ -42,31 +42,31 @@ CLEANFILES += \ ## -------------------- ## # Avoid using BUILT_SOURCES which is too global. -$(%C%_calc___OBJECTS): $(calc_sources_generated) +$(%C%_calc___OBJECTS): $(calcxx_sources_generated) -calc_sources_extracted = \ +calcxx_sources_extracted = \ %D%/calc++-driver.cc \ %D%/calc++-driver.hh \ %D%/calc++-scanner.ll \ %D%/calc++.cc -calc_extracted = \ - $(calc_sources_extracted) \ +calcxx_extracted = \ + $(calcxx_sources_extracted) \ %D%/calc++-parser.yy -extracted += $(calc_extracted) -calc_sources_generated = \ +extracted += $(calcxx_extracted) +calcxx_sources_generated = \ %D%/calc++-parser.cc \ %D%/calc++-parser.hh \ %D%/location.hh \ %D%/position.hh \ %D%/stack.hh -calc_sources = \ - $(calc_sources_extracted) \ - $(calc_sources_generated) +calcxx_sources = \ + $(calcxx_sources_extracted) \ + $(calcxx_sources_generated) if FLEX_CXX_WORKS check_PROGRAMS += %D%/calc++ nodist_%C%_calc___SOURCES = \ - $(calc_sources) + $(calcxx_sources) %C%_calc___CPPFLAGS = -I$(top_builddir)/%D% %C%_calc___CXXFLAGS = $(AM_CXXFLAGS) $(FLEX_SCANNER_CXXFLAGS) @@ -74,3 +74,11 @@ dist_TESTS += %D%/calc++.test else EXTRA_DIST += %D%/calc++.test endif + + +## ------------ ## +## Installing. ## +## ------------ ## + +calcxxdir = $(docdir)/examples/calc++ +calcxx_DATA = $(calcxx_extracted) diff --git a/examples/extexi b/examples/extexi index 24a005eb..d4ce653d 100755 --- a/examples/extexi +++ b/examples/extexi @@ -19,7 +19,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -# Usage: extexi input-file.texi ... -- [FILES to extract] +# Usage: extexi [OPTION...] input-file.texi ... -- [FILES to extract] # Look for @example environments preceded with lines such as: # @@ -35,6 +35,9 @@ use strict; +# Whether we generate synclines. +my $synclines = 0; + # normalize($block) # ----------------- # Remove Texinfo mark up. @@ -102,7 +105,7 @@ sub process ($) { # Bison supports synclines, but not Flex. $input .= sprintf ("#line %s \"$in\"\n", $. + 1) - if $file =~ /\.[chy]*$/; + if $synclines && $file =~ /\.[chy]*$/; next; } elsif (/^\@end (small)?example$/) @@ -136,15 +139,19 @@ my @input; my $seen_dash = 0; for my $arg (@ARGV) { - if ($arg eq '--') - { - $seen_dash = 1; - } - elsif ($seen_dash) + if ($seen_dash) { use File::Basename; $file_wanted{basename($arg)} = $arg; } + elsif ($arg eq '--') + { + $seen_dash = 1; + } + elsif ($arg eq '--synclines') + { + $synclines = 1; + } else { push @input, $arg; diff --git a/examples/local.mk b/examples/local.mk index 9f7863c1..8274e007 100644 --- a/examples/local.mk +++ b/examples/local.mk @@ -25,7 +25,10 @@ AM_CXXFLAGS = \ doc = $(top_srcdir)/doc/bison.texi extexi = $(top_srcdir)/%D%/extexi -extract = VERSION="$(VERSION)" $(PERL) $(extexi) $(doc) -- +if ENABLE_GCC_WARNINGS +extexiFLAGS = --synclines +endif +extract = VERSION="$(VERSION)" $(PERL) $(extexi) $(extexiFLAGS) $(doc) -- extracted = CLEANFILES += $(extracted) %D%/extracted.stamp %D%/extracted.stamp: $(doc) $(extexi) diff --git a/examples/mfcalc/local.mk b/examples/mfcalc/local.mk index 97ea63b3..361a4a5f 100644 --- a/examples/mfcalc/local.mk +++ b/examples/mfcalc/local.mk @@ -30,3 +30,10 @@ nodist_%C%_mfcalc_SOURCES = $(mfcalc_sources) %C%_mfcalc_CPPFLAGS = -I$(top_builddir)/%D% dist_TESTS += %D%/mfcalc.test + +## ------------ ## +## Installing. ## +## ------------ ## + +mfcalcdir = $(docdir)/examples/mfcalc +mfcalc_DATA = $(mfcalc_extracted) diff --git a/examples/rpcalc/local.mk b/examples/rpcalc/local.mk index 97f35356..125bb3ba 100644 --- a/examples/rpcalc/local.mk +++ b/examples/rpcalc/local.mk @@ -30,3 +30,10 @@ nodist_%C%_rpcalc_SOURCES = $(rpcalc_sources) %C%_rpcalc_CPPFLAGS = -I$(top_builddir)/%D% dist_TESTS += %D%/rpcalc.test + +## ------------ ## +## Installing. ## +## ------------ ## + +rpcalcdir = $(docdir)/examples/rpcalc +rpcalc_DATA = $(rpcalc_extracted) diff --git a/src/symtab.c b/src/symtab.c index f6761c4a..5a8b6169 100644 --- a/src/symtab.c +++ b/src/symtab.c @@ -138,6 +138,42 @@ symbol_free (void *ptr) if (!sym->is_alias) sym_content_free (sym->content); free (sym); + +} + +/* If needed, swap first and second so that first has the earliest + location (according to location_cmp). + + Many symbol features (e.g., user token numbers) are not assigned + during the parsing, but in a second step, via a traversal of the + symbol table sorted on tag. + + However, error messages make more sense if we keep the first + declaration first. +*/ + +static +void symbols_sort (symbol **first, symbol **second) +{ + if (0 < location_cmp ((*first)->location, (*second)->location)) + { + symbol* tmp = *first; + *first = *second; + *second = tmp; + } +} + +/* Likewise, for locations. */ + +static +void locations_sort (location *first, location *second) +{ + if (0 < location_cmp (*first, *second)) + { + location tmp = *first; + *first = *second; + *second = tmp; + } } char const * @@ -250,6 +286,7 @@ symbol_redeclaration (symbol *s, const char *what, location first, location second) { unsigned i = 0; + locations_sort (&first, &second); complain_indent (&second, complaint, &i, _("%s redeclaration for %s"), what, s->tag); i += SUB_INDENT; @@ -262,6 +299,7 @@ semantic_type_redeclaration (semantic_type *s, const char *what, location first, location second) { unsigned i = 0; + locations_sort (&first, &second); complain_indent (&second, complaint, &i, _("%s redeclaration for <%s>"), what, s->tag); i += SUB_INDENT; @@ -570,17 +608,7 @@ static void user_token_number_redeclaration (int num, symbol *first, symbol *second) { unsigned i = 0; - /* User token numbers are not assigned during the parsing, but in a - second step, via a traversal of the symbol table sorted on tag. - - However, error messages make more sense if we keep the first - declaration first. */ - if (location_cmp (first->location, second->location) > 0) - { - symbol* tmp = first; - first = second; - second = tmp; - } + symbols_sort (&first, &second); complain_indent (&second->location, complaint, &i, _("user token number %d redeclaration for %s"), num, second->tag); diff --git a/tests/input.at b/tests/input.at index 969e53fc..205342bd 100644 --- a/tests/input.at +++ b/tests/input.at @@ -654,50 +654,118 @@ AT_CLEANUP AT_SETUP([Incompatible Aliases]) -AT_DATA([input.y], -[[%token foo "foo" +m4_pushdef([AT_TEST], +[AT_DATA([input.y], [$1]) +AT_BISON_CHECK([-fcaret input.y], [1], [], [$2]) +]) -%type foo -%printer {bar} foo -%destructor {bar} foo -%left foo - -%type "foo" -%printer {baz} "foo" -%destructor {baz} "foo" -%left "foo" +# Use the string-alias first to check the order between "first +# declaration" and second. +AT_TEST([[%token foo "foo" +%type "foo" +%type foo %% exp: foo; +]], +[[input.y:3.7-11: error: %type redeclaration for foo + %type foo + ^^^^^ +input.y:2.7-11: previous declaration + %type "foo" + ^^^^^ ]]) -AT_BISON_CHECK([-fcaret input.y], [1], [], -[[input.y:8.7-11: error: %type redeclaration for "foo" - %type "foo" - ^^^^^ -input.y:3.7-11: previous declaration - %type foo - ^^^^^ -input.y:9.10-14: error: %printer redeclaration for "foo" - %printer {baz} "foo" +AT_TEST([[%token foo "foo" +%printer {bar} "foo" +%printer {baz} foo +%% +exp: foo; +]], +[[input.y:3.10-14: error: %printer redeclaration for foo + %printer {baz} foo ^^^^^ -input.y:4.10-14: previous declaration - %printer {bar} foo +input.y:2.10-14: previous declaration + %printer {bar} "foo" ^^^^^ -input.y:10.13-17: error: %destructor redeclaration for "foo" - %destructor {baz} "foo" +]]) + +AT_TEST([[%token foo "foo" +%destructor {bar} "foo" +%destructor {baz} foo +%% +exp: foo; +]], +[[input.y:3.13-17: error: %destructor redeclaration for foo + %destructor {baz} foo ^^^^^ -input.y:5.13-17: previous declaration - %destructor {bar} foo +input.y:2.13-17: previous declaration + %destructor {bar} "foo" ^^^^^ -input.y:11.1-5: error: %left redeclaration for "foo" - %left "foo" +]]) + +AT_TEST([[%token foo "foo" +%left "foo" +%left foo +%% +exp: foo; +]], +[[input.y:3.1-5: error: %left redeclaration for foo + %left foo ^^^^^ -input.y:6.1-5: previous declaration - %left foo +input.y:2.1-5: previous declaration + %left "foo" ^^^^^ ]]) +# This time, declare the alias after its use. + +# Precedence/associativity. +## FIXME: AT_TEST([[%left "foo" +## FIXME: %left foo +## FIXME: %token foo "foo" +## FIXME: %% +## FIXME: exp: foo; +## FIXME: ]], +## FIXME: [[input.y:2.1-5: error: %left redeclaration for foo +## FIXME: %left foo +## FIXME: ^^^^^ +## FIXME: input.y:1.1-5: previous declaration +## FIXME: %left "foo" +## FIXME: ^^^^^ +## FIXME: ]]) + +## FIXME: # Printer. +## FIXME: AT_TEST([[%printer {} "foo" +## FIXME: %printer {} foo +## FIXME: %token foo "foo" +## FIXME: %% +## FIXME: exp: foo; +## FIXME: ]], +## FIXME: [[input.y:2.10-11: error: %printer redeclaration for foo +## FIXME: %printer {} foo +## FIXME: ^^ +## FIXME: input.y:1.10-11: previous declaration +## FIXME: %printer {} "foo" +## FIXME: ^^ +## FIXME: ]]) + +## FIXME: # Destructor. +## FIXME: AT_TEST([[%destructor {} "foo" +## FIXME: %destructor {} foo +## FIXME: %token foo "foo" +## FIXME: %% +## FIXME: exp: foo; +## FIXME: ]], +## FIXME: [[input.y:2.13-14: error: %destructor redeclaration for foo +## FIXME: %destructor {} foo +## FIXME: ^^ +## FIXME: input.y:1.13-14: previous declaration +## FIXME: %destructor {} "foo" +## FIXME: ^^ +## FIXME: ]]) + +m4_popdef([AT_TEST]) AT_CLEANUP