bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

{master} merge maint


From: Théophile Ranquet
Subject: {master} merge maint
Date: Thu, 6 Dec 2012 12:41:40 +0100

commit ead47d22cbf8280bb8c5ecfd1ab8aab63e6764ef
Merge: d6dc4d3 9960a6a
Author: Theophile Ranquet <address@hidden>
Date:   Thu Dec 6 11:43:02 2012 +0100

    Merge remote-tracking branch 'origin/maint'

    * origin/maint:
      misc: pacify the Tiny C Compiler
      cpp: make the check of Flex version portable
      misc: require getline
      c++: support wide strings for file names
      doc: document carets
      tests: enhance existing tests with carets
      errors: show carets
      getargs: add support for --flags/-f

    Conflicts:
        doc/bison.texi
        m4/.gitignore
        src/complain.c
        src/flex-scanner.h
        src/getargs.c
        src/getargs.h
        src/gram.c
        src/main.c
        tests/headers.at


diff --git a/NEWS b/NEWS
index e9b7fd9..eabdcc6 100644
--- a/NEWS
+++ b/NEWS
@@ -247,6 +247,19 @@ GNU Bison NEWS
   The introduction of this feature, in 2.4, was four years ago. The --language
   option and the %language directive are no longer experimental.

+** New format for error reports: carets
+
+  Caret errors have been added to Bison, for example (taken from the
+  documentation):
+
+    input.y:3.20-23: error: ambiguous reference: '$exp'
+     exp: exp '+' exp { $exp = $1 + $2; };
+                        ^^^^
+
+  The default behaviour for now is still not to display these unless explictly
+  asked with -fall of -fcaret. However, in a later release, it will be made the
+  default behavior (but may still be deactivated with -fno-caret).
+
 ** New value for %define variable: api.pure full

   The %define variable api.pure requests a pure (reentrant) parser. However,
diff --git a/THANKS b/THANKS
index 909a6e0..dbe5479 100644
--- a/THANKS
+++ b/THANKS
@@ -68,6 +68,7 @@ Lie Yan                   address@hidden
 Magnus Fromreide          address@hidden
 Marc Autret               address@hidden
 Marc Mendiola             address@hidden
+Mark Boyall               address@hidden
 Martin Jacobs             address@hidden
 Martin Mokrejs            address@hidden
 Martin Nylin              address@hidden
diff --git a/bootstrap.conf b/bootstrap.conf
index cddc571..feff5ff 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -20,7 +20,9 @@ gnulib_modules='
   argmatch assert calloc-posix close closeout config-h c-strcase
   configmake
   dirname
-  error extensions fdl fopen-safer getopt-gnu
+  error extensions fdl fopen-safer
+  getline
+  getopt-gnu
   gettext git-version-gen gitlog-to-changelog
   gpl-3.0 hash inttypes isnan javacomp-script
   javaexec-script ldexpl malloc-gnu
diff --git a/build-aux/git-log-fix b/build-aux/git-log-fix
index af702fe..7211150 100644
--- a/build-aux/git-log-fix
+++ b/build-aux/git-log-fix
@@ -1,3 +1,8 @@
 # This file is expected to be used via gitlog-to-changelog's --amend=FILE
 # option.  It specifies what changes to make to each given SHA1's commit
 # log and metadata, using Perl-eval'able expressions.
+
+0db2648930e3b6c376a539aabe368aade83ee29a
+s/--flags/--feature/;
+s/flag_flag/feature_flag/;
+s/\bflag\b/feature/;
diff --git a/data/location.cc b/data/location.cc
index b49028f..631247a 100644
--- a/data/location.cc
+++ b/data/location.cc
@@ -124,8 +124,9 @@ m4_define([b4_position_define],
    ** \param ostr the destination output stream
    ** \param pos a reference to the position to redirect
    */
-  inline std::ostream&
-  operator<< (std::ostream& ostr, const position& pos)
+  template <typename YYChar>
+  inline std::basic_ostream<YYChar>&
+  operator<< (std::basic_ostream<YYChar>& ostr, const position& pos)
   {
     if (pos.filename)
       ostr << *pos.filename << ':';
@@ -248,7 +249,9 @@ m4_define([b4_location_define],
    **
    ** Avoid duplicate information.
    */
-  inline std::ostream& operator<< (std::ostream& ostr, const location& loc)
+  template <typename YYChar>
+  inline std::basic_ostream<YYChar>&
+  operator<< (std::basic_ostream<YYChar>& ostr, const location& loc)
   {
     position last = loc.end - 1;
     ostr << loc.begin;
diff --git a/doc/bison.texi b/doc/bison.texi
index 874e68e..28af1ae 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -9606,6 +9606,56 @@ S/R conflicts as errors.
 $ bison -Werror=yacc,conflicts-sr input.y
 $ bison -Werror=yacc,error=conflicts-sr input.y
 @end example
+
address@hidden -f address@hidden
address@hidden address@hidden
+Activate miscellaneous @var{feature}. @var{feature} can be one of:
address@hidden @code
address@hidden caret
address@hidden diagnostics-show-caret
+Show caret errors, in a manner similar to GCC's
address@hidden, or Clang's @option{-fcaret-diagnotics}. The
+location provided with the message is used to quote the corresponding line of
+the source file, underlining the important part of it with carets (^). Here is
+an example, using the following file @file{input.y}:
+
address@hidden
+%type <ival> exp
+%%
+exp: exp '+' exp @{ $exp = $1 + $2; @};
address@hidden example
+
+When invoked with @option{-fcaret}, Bison will report:
+
address@hidden
address@hidden
+input.y:3.20-23: error: ambiguous reference: '$exp'
+ exp: exp '+' exp @{ $exp = $1 + $2; @};
+                    ^^^^
address@hidden group
address@hidden
+input.y:3.1-3:       refers to: $exp at $$
+ exp: exp '+' exp @{ $exp = $1 + $2; @};
+ ^^^
address@hidden group
address@hidden
+input.y:3.6-8:       refers to: $exp at $1
+ exp: exp '+' exp @{ $exp = $1 + $2; @};
+      ^^^
address@hidden group
address@hidden
+input.y:3.14-16:     refers to: $exp at $3
+ exp: exp '+' exp @{ $exp = $1 + $2; @};
+              ^^^
address@hidden group
address@hidden
+input.y:3.32-33: error: $2 of 'exp' has no declared type
+ exp: exp '+' exp @{ $exp = $1 + $2; @};
+                                ^^
address@hidden group
address@hidden example
+
address@hidden table
 @end table

 @noindent
diff --git a/lib/.gitignore b/lib/.gitignore
index ba37d12..74cb308 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -101,7 +101,6 @@
 /isnanf.c
 /isnanl-nolibm.h
 /isnanl.c
-/iswblank.c
 /itold.c
 /ldexpl.c
 /localcharset.c
@@ -109,13 +108,10 @@
 /malloc.c
 /math.h
 /math.in.h
-/mbchar.c
-/mbchar.h
 /mbrtowc.c
 /mbsinit.c
 /mbswidth.c
 /mbswidth.h
-/mbuiter.h
 /memchr.c
 /memchr.valgrind
 /msvc-inval.c
@@ -215,8 +211,6 @@
 /stripslash.c
 /strndup.c
 /strnlen.c
-/strnlen1.c
-/strnlen1.h
 /strtol.c
 /strtoul.c
 /strverscmp.c
@@ -273,9 +267,5 @@
 /xstrndup.h
 /binary-io.c
 /xsize.c
-/bitrotate.c
-/math.c
-/sig-handler.c
-/stdio.c
-/unistd.c
-/wctype-h.c
+/getdelim.c
+/getline.c
diff --git a/m4/.gitignore b/m4/.gitignore
index 80193db..242ac2a 100644
--- a/m4/.gitignore
+++ b/m4/.gitignore
@@ -63,7 +63,6 @@
 /isnand.m4
 /isnanf.m4
 /isnanl.m4
-/iswblank.m4
 /javacomp.m4
 /javaexec.m4
 /largefile.m4
@@ -82,8 +81,6 @@
 /longlong.m4
 /malloc.m4
 /math_h.m4
-/mbchar.m4
-/mbiter.m4
 /mbrtowc.m4
 /mbsinit.m4
 /mbstate_t.m4
@@ -183,3 +180,6 @@
 /obstack-printf.m4
 /extern-inline.m4
 /non-recursive-gnulib-prefix-hack.m4
+/getdelim.m4
+/getline.m4
+/inline.m4
diff --git a/src/complain.c b/src/complain.c
index 2e4e71a..ee1b4a1 100644
--- a/src/complain.c
+++ b/src/complain.c
@@ -110,12 +110,15 @@ error_message (const location *loc, warnings
flags, const char *prefix,
   warnings_print_categories (flags);
   {
     size_t l = strlen (message);
-    if (l < 2 || message[l-2] != ':' || message[l-1] != ' ')
+    if (l < 2 || message[l - 2] != ':' || message[l - 1] != ' ')
       {
         putc ('\n', stderr);
         fflush (stderr);
+        if (loc && feature_flag & feature_caret)
+          location_caret (stderr, *loc);
       }
   }
+  fflush (stderr);
 }

 /** Raise a complaint. That can be a fatal error, a complaint or just a
diff --git a/src/flex-scanner.h b/src/flex-scanner.h
index c1e07ea..9b80744 100644
--- a/src/flex-scanner.h
+++ b/src/flex-scanner.h
@@ -23,18 +23,18 @@

 /* Whether this version of Flex is (strictly) greater than
    Major.Minor.Subminor.  */
-#define FLEX_VERSION_GT(Major, Minor, Subminor)                         \
-  (defined YY_FLEX_MAJOR_VERSION                                        \
-   && (Major < YY_FLEX_MAJOR_VERSION                                    \
-       || (Major == YY_FLEX_MAJOR_VERSION                               \
-           && (defined YY_FLEX_MINOR_VERSION                            \
-               && (Minor < YY_FLEX_MINOR_VERSION                        \
-                   || (Minor == YY_FLEX_MINOR_VERSION                   \
-                       && defined YY_FLEX_SUBMINOR_VERSION              \
-                       && Subminor < YY_FLEX_SUBMINOR_VERSION))))))
-
+#ifdef YY_FLEX_SUBMINOR_VERSION
+# define FLEX_VERSION               \
+  (YY_FLEX_MAJOR_VERSION) * 1000000 \
++ (YY_FLEX_MINOR_VERSION) * 1000    \
++ (YY_FLEX_SUBMINOR_VERSION)
+#else
+# define FLEX_VERSION               \
+  (YY_FLEX_MAJOR_VERSION) * 1000000 \
++ (YY_FLEX_MINOR_VERSION) * 1000
+#endif
 /* Pacify "gcc -Wmissing-prototypes" when flex 2.5.31 is used.  */
-#if ! FLEX_VERSION_GT (2, 5, 31)
+# if FLEX_VERSION <= 2005031
 int   FLEX_PREFIX (get_lineno) (void);
 FILE *FLEX_PREFIX (get_in) (void);
 FILE *FLEX_PREFIX (get_out) (void);
@@ -65,7 +65,7 @@ int   FLEX_PREFIX (lex_destroy) (void);
    versions according to the Flex manual) leak memory if yylex_destroy is not
    invoked.  However, yylex_destroy is not defined before Flex 2.5.9, so give
    an implementation here that at least appears to work with Flex 2.5.4.  */
-#if ! FLEX_VERSION_GT (2, 5, 9)
+#if FLEX_VERSION <= 2005009
 # define yylex_destroy() yy_delete_buffer (YY_CURRENT_BUFFER)
 #endif

diff --git a/src/getargs.c b/src/getargs.c
index 77c1cbf..0d43186 100644
--- a/src/getargs.c
+++ b/src/getargs.c
@@ -46,6 +46,7 @@ bool yacc_flag; /* for -y */
 bool nondeterministic_parser = false;
 bool glr_parser = false;

+int feature_flag = feature_none;
 int report_flag = report_none;
 int trace_flag = trace_none;

@@ -272,6 +273,27 @@ static const int warnings_types[] =

 ARGMATCH_VERIFY (warnings_args, warnings_types);

+/*-----------------------.
+| --feature's handling.  |
+`-----------------------*/
+
+static const char * const feature_args[] =
+{
+  "none",
+  "caret", "diagnostics-show-caret",
+  "all",
+  0
+};
+
+static const int feature_types[] =
+{
+  feature_none,
+  feature_caret, feature_caret,
+  feature_all
+};
+
+ARGMATCH_VERIFY (feature_args, feature_types);
+
 /*-------------------------------------------.
 | Display the help message and exit STATUS.  |
 `-------------------------------------------*/
@@ -315,6 +337,7 @@ Operation modes:\n\
       --print-datadir        output directory containing skeletons and XSLT\n\
   -y, --yacc                 emulate POSIX Yacc\n\
   -W, --warnings[=CATEGORY]  report the warnings falling in CATEGORY\n\
+  -f, --feature[=FEATURE]    activate miscellaneous features\n\
 \n\
 "), stdout);

@@ -331,8 +354,8 @@ Parser:\n\
                                    deprecated by '-Dapi.prefix=PREFIX'\n\
   -l, --no-lines                   don't generate '#line' directives\n\
   -k, --token-table                include a table of token names\n\
-\n\
 "), stdout);
+      putc ('\n', stdout);

       /* Keep -d and --defines separate so that ../build-aux/cross-options.pl
        * won't assume that -d also takes an argument.  */
@@ -348,8 +371,8 @@ Output:\n\
   -g, --graph[=FILE]         also output a graph of the automaton\n\
   -x, --xml[=FILE]           also output an XML report of the automaton\n\
                              (the XML schema is experimental)\n\
-\n\
 "), stdout);
+      putc ('\n', stdout);

       fputs (_("\
 Warning categories include:\n\
@@ -375,6 +398,14 @@ THINGS is a list of comma separated words that
can include:\n\
   `all'          include all the above information\n\
   `none'         disable the report\n\
 "), stdout);
+      putc ('\n', stdout);
+
+      fputs (_("\
+FEATURE is a list of comma separated words that can include:\n\
+  `caret'        show errors with carets\n\
+  `all'          all of the above\n\
+  `none'         disable all of the above\n\
+  "), stdout);

       putc ('\n', stdout);
       printf (_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
@@ -485,6 +516,7 @@ static char const short_options[] =
   "W::"
   "b:"
   "d"
+  "f::"
   "e"
   "g::"
   "h"
@@ -537,6 +569,7 @@ static struct option const long_options[] =

   /* Output.  */
   { "defines",     optional_argument,   0,   'd' },
+  { "feature",     optional_argument,   0,   'f' },

   /* Operation modes.  */
   { "fixed-output-files", no_argument,  0,   'y' },
@@ -629,6 +662,10 @@ getargs (int argc, char *argv[])
         version ();
         exit (EXIT_SUCCESS);

+      case 'f':
+        FLAGS_ARGMATCH (feature, optarg, feature_all);
+        break;
+
       case 'W':
         FLAGS_ARGMATCH (warnings, optarg, Wall);
         break;
diff --git a/src/getargs.h b/src/getargs.h
index 4eb3981..3c081fe 100644
--- a/src/getargs.h
+++ b/src/getargs.h
@@ -108,6 +108,18 @@ enum trace
 /** What debug items bison displays during its run.  */
 extern int trace_flag;

+/*-------------.
+| --features.  |
+`-------------*/
+
+enum feature
+  {
+    feature_none  = 0,         /**< No additional feature.  */
+    feature_caret = 1 << 0,    /**< Enhance the output of errors with
carets.  */
+    feature_all   = ~0         /**< All above features.  */
+  };
+/** What additional features to use.  */
+extern int feature_flag;

 /** Process the command line arguments.
  *
diff --git a/src/gram.c b/src/gram.c
index f58ac3b..dbcf8a2 100644
--- a/src/gram.c
+++ b/src/gram.c
@@ -312,10 +312,15 @@ grammar_rules_useless_report (const char *message)
       for (r = 0; r < nrules ; ++r)
         if (!rules[r].useful)
           {
-            complain (&rules[r].location, w | silent, "%s: ", message);
-            rule_print (&rules[r], stderr);
-            warnings_print_categories (w);
-            fprintf (stderr, "\n");
+            if (feature_flag & feature_caret)
+              complain (&rules[r].location, w, "%s", message);
+            else
+              {
+                complain (&rules[r].location, w | silent, "%s: ", message);
+                rule_print (&rules[r], stderr);
+                warnings_print_categories (w);
+                fprintf (stderr, "\n");
+              }
           }
     }
 }
diff --git a/src/graphviz.c b/src/graphviz.c
index 16ea8b9..9da5f6e 100644
--- a/src/graphviz.c
+++ b/src/graphviz.c
@@ -103,7 +103,7 @@ conclude_red (struct obstack *out, int source,
rule_number ruleno,
   /* If no lookahead tokens were valid transitions, this reduction is
      actually hidden, so cancel everything. */
   if (first)
-    return (void) obstack_finish0 (out);
+    (void) obstack_finish0 (out);
   else
     {
       char const *ed = enabled ? "" : "d";
diff --git a/src/location.c b/src/location.c
index c27ad14..1a7d65c 100644
--- a/src/location.c
+++ b/src/location.c
@@ -138,6 +138,89 @@ location_print (FILE *out, location loc)
   return res;
 }

+
+/* Persistant data used by location_caret to avoid reopening and rereading the
+   same file all over for each error.  */
+struct caret_info
+{
+  FILE* source;
+  size_t line;
+  size_t offset;
+};
+
+static struct caret_info caret_info = { NULL, 1, 0 };
+
+/* Free any allocated ressources and close any open file handles that are
+   left-over by the usage of location_caret.  */
+void
+cleanup_caret ()
+{
+  if (caret_info.source)
+    fclose (caret_info.source);
+}
+
+/* Output to OUT the line and caret corresponding to location LOC.  */
+void
+location_caret (FILE *out, location loc)
+{
+  /* FIXME: find a way to support X-file locations, and only open once each
+     file. That would make the procedure future-proof.  */
+  if (! (caret_info.source
+         || (caret_info.source = fopen (loc.start.file, "r")))
+      || loc.start.column == -1 || loc.start.line == -1)
+    return;
+
+  /* If the line we want to quote is seekable (the same line as the previous
+     location), just seek it. If it was before, we lost track of it, so
+     return to the start of file.  */
+  if (caret_info.line <= loc.start.line)
+    fseek (caret_info.source, caret_info.offset, SEEK_SET);
+  else
+    {
+      caret_info.line = 1;
+      caret_info.offset = 0;
+      fseek (caret_info.source, caret_info.offset, SEEK_SET);
+    }
+
+  /* Advance to the line's position, keeping track of the offset.  */
+  {
+    int i;
+    for (i = caret_info.line; i < loc.start.line; caret_info.offset++)
+      if (fgetc (caret_info.source) == '\n')
+        ++i;
+  }
+  caret_info.line = loc.start.line;
+
+  /* Read the actual line.  Don't update the offset, so that we keep a pointer
+     to the start of the line.  */
+  {
+    ssize_t len = 0;
+    char *buf = NULL;
+    if ((len = getline (&buf, (size_t*) &len, caret_info.source)) != -1)
+      {
+        /* The caret of a multiline location ends with the first line.  */
+        int end = loc.start.line != loc.end.line ? len : loc.end.column;
+
+        if (len)
+          {
+            int i = loc.start.column;
+            /* Quote the file, indent by a single column.  */
+            fputc (' ', out);
+            fwrite (buf, 1, len, out);
+
+            /* Print the caret, with the same indent as above.  */
+            fputc (' ', out);
+            fprintf (out, "%*s", loc.start.column - 1, "");
+            do {
+              fputc ('^', out);
+            } while (++i < end);
+          }
+        fputc ('\n', out);
+        free (buf);
+      }
+  }
+}
+
 void
 boundary_set_from_string (boundary *bound, char *loc_str)
 {
diff --git a/src/location.h b/src/location.h
index 369125b..7026d82 100644
--- a/src/location.h
+++ b/src/location.h
@@ -102,6 +102,13 @@ void location_compute (location *loc,
    characters.  */
 unsigned location_print (FILE *out, location loc);

+/* Free any allocated ressources and close any open file handles that are
+   left-over by the usage of location_caret.  */
+void cleanup_caret (void);
+
+/* Output to OUT the line and caret corresponding to location LOC.  */
+void location_caret (FILE *out, location loc);
+
 /* Return -1, 0, 1, depending whether a is before, equal, or
    after b.  */
 static inline int
diff --git a/src/main.c b/src/main.c
index 39b39c7..5386aa7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -215,5 +215,7 @@ main (int argc, char *argv[])
   timevar_stop (TV_TOTAL);
   timevar_print (stderr);

+  cleanup_caret ();
+
   return complaint_status ? EXIT_FAILURE : EXIT_SUCCESS;
 }
diff --git a/tests/actions.at b/tests/actions.at
index 6d160ef..cd7a58b 100644
--- a/tests/actions.at
+++ b/tests/actions.at
@@ -1329,6 +1329,21 @@ input.y:33.3-23: warning: unset value: $$ [-Wother]
 input.y:30.3-35.37: warning: unused value: $3 [-Wother]
 ]])

+AT_BISON_CHECK([-fcaret -o input.c input.y], 0,,
+[[input.y:24.70-72: warning: useless %destructor for type <*> [-Wother]
+ %printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
+                                                                      ^^^
+input.y:24.70-72: warning: useless %printer for type <*> [-Wother]
+ %printer { fprintf (yyoutput, "<*> printer should not be called"); } <*>
+                                                                      ^^^
+input.y:33.3-23: warning: unset value: $$ [-Wother]
+   {           @$ = 4; } // Only used.
+   ^^^^^^^^^^^^^^^^^^^^^
+input.y:30.3-35.37: warning: unused value: $3 [-Wother]
+   {           @$ = 1; } // Not set or used.
+   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+]])
+
 AT_COMPILE([input])
 AT_PARSER_CHECK([./input], 1,,
 [[Starting parse
diff --git a/tests/conflicts.at b/tests/conflicts.at
index 8b04449..c7ed2fe 100644
--- a/tests/conflicts.at
+++ b/tests/conflicts.at
@@ -40,6 +40,12 @@ AT_BISON_CHECK([-o input.c input.y], 0, [],
 [[input.y:4.9: warning: rule useless in parser due to conflicts: e:
/* empty */ [-Wother]
 ]])

+AT_BISON_CHECK([-fcaret -o input.c input.y], 0, [],
+[[input.y:4.9: warning: rule useless in parser due to conflicts [-Wother]
+ e: 'e' | /* Nothing. */;
+         ^
+]])
+
 AT_CLEANUP


diff --git a/tests/headers.at b/tests/headers.at
index c21fa35..351b8a7 100644
--- a/tests/headers.at
+++ b/tests/headers.at
@@ -229,27 +229,30 @@ AT_TEST([x8], [%define api.pure %define
api.push-pull both])
 # C++ output relies on namespaces and still uses yy a lot.
 #
 # Check there is no 'YY' left.
-# Ignore comments, YYPUSH_MORE(_DEFINED)?  (constant definition),
+# Ignore comments, YYChar (template parameter), YYPARSE_PARAM
+# (obsolete), YYPUSH_MORE(_DEFINED)?  (constant definition),
 # YY_\w+_INCLUDED (header guards).
 #
 # YYDEBUG (not renamed) can be read, but not changed.
 AT_CHECK([[$PERL -n -0777 -e '
   s{/\*.*?\*/}{}gs;
   s{//.*}{}g;
-  s{\b(YYPUSH_MORE(_DEFINED)?
+  s{\b(YYChar
+      |YYPARSE_PARAM
+      |YYPUSH_MORE(_DEFINED)?
       |YY_\w+_INCLUDED
       |YY_NULL
       |(defined|if)\ YYDEBUG
       )\b}{}gx;
   while (/^(.*YY.*)$/gm)
   {
-    print "$ARGV: $1\n";
+    print "$ARGV: invalid exported YY: $1\n";
   }
   if ($ARGV =~ /\.h$/)
   {
     while (/^(.*yy.*)$/gm)
     {
-      print "$ARGV: $1\n";
+      print "$ARGV: invalid exported yy: $1\n";
     }
   }
 ' -- *.hh *.h]])
diff --git a/tests/input.at b/tests/input.at
index 7ba0063..7f5fb88 100644
--- a/tests/input.at
+++ b/tests/input.at
@@ -925,6 +925,25 @@ input.y:19.13-20.0: error: missing '}' at end of file
 input.y:20.1: error: syntax error, unexpected end of file
 ]])

+AT_BISON_CHECK([-fcaret -o input.c input.y], 1, [],
+[[input.y:1.10-2.0: error: missing '"' at end of line
+ %token A "a
+          ^^
+input.y:4.10-5.0: error: missing "'" at end of line
+ %token C '1
+          ^^
+input.y:14.11-15.0: error: missing "'" at end of line
+ %type <f> 'a
+           ^^
+input.y:16.11-17.0: error: missing '"' at end of line
+ %type <f> "a
+           ^^
+input.y:19.13-20.0: error: missing '}' at end of file
+ %destructor { free ($$)
+             ^^^^^^^^^^^
+input.y:20.1: error: syntax error, unexpected end of file
+]])
+
 AT_CLEANUP


@@ -1157,6 +1176,18 @@ AT_BISON_CHECK([[-Dvar=cmd-d input-dg.y]], [[1]], [],
 <command line>:1:      previous definition
 ]])

+AT_DATA([[input-dg.y]],
+[[%define var "gram"
+%%
+start: ;
+]])
+AT_BISON_CHECK([[-fcaret -Dvar=cmd-d input-dg.y]], [[1]], [],
+[[input-dg.y:1.9-11: error: %define variable 'var' redefined
+ %define var "gram"
+         ^^^
+<command line>:2:      previous definition
+]])
+
 AT_DATA([[input-unused.y]],
 [[%%
 start: ;
diff --git a/tests/named-refs.at b/tests/named-refs.at
index ea37922..75e7303 100644
--- a/tests/named-refs.at
+++ b/tests/named-refs.at
@@ -393,6 +393,127 @@ test.y:46.46-54: error: invalid reference: '$then-a.f'
 test.y:45.12-46.65:  symbol not found in production: then
 test.y:45.41-46:     possibly meant: $[then-a].f at $4
 ]])
+
+AT_BISON_CHECK([-fcaret -o test.c test.y], 1, [],
+[[test.y:24.36-41: error: invalid reference: '$cond1'
+           { $if_stmt1 = new IfStmt($cond1, $then.f1, $else); };
+                                    ^^^^^^
+test.y:23.11-24.62:  symbol not found in production: cond1
+ if_stmt1: IF expr[cond] THEN stmt[then] ELSE stmt.list[else] FI
+           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+test.y:26.43-53: error: invalid reference: '$stmt.field'
+           { $if_stmt2 = new IfStmt($cond, $stmt.field, 0); };
+                                           ^^^^^^^^^^^
+test.y:25.11-26.60:  symbol not found in production: stmt
+ if_stmt2: IF expr[cond] THEN stmt[then] FI
+           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+test.y:25.35-38:     possibly meant: $then.field, hiding $stmt.field at $4
+ if_stmt2: IF expr[cond] THEN stmt[then] FI
+                                   ^^^^
+test.y:28.43-52: error: invalid reference: '$stmt.list'
+           { $if_stmt3 = new IfStmt($cond, $stmt.list, 0); };
+                                           ^^^^^^^^^^
+test.y:27.11-28.59:  symbol not found in production: stmt
+ if_stmt3: IF expr[cond] THEN stmt.list FI
+           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+test.y:27.30-38:     possibly meant: $[stmt.list] at $4
+ if_stmt3: IF expr[cond] THEN stmt.list FI
+                              ^^^^^^^^^
+test.y:30.43-46: error: ambiguous reference: '$xyz'
+           { $if_stmt4 = new IfStmt($cond, $xyz, $cond); };
+                                           ^^^^
+test.y:29.35-37:     refers to: $xyz at $4
+ if_stmt4: IF expr[cond] THEN stmt[xyz] ELSE stmt[xyz] FI
+                                   ^^^
+test.y:29.50-52:     refers to: $xyz at $6
+ if_stmt4: IF expr[cond] THEN stmt[xyz] ELSE stmt[xyz] FI
+                                                  ^^^
+test.y:32.43-52: error: invalid reference: '$stmt.list'
+           { $if_stmt5 = new IfStmt($cond, $stmt.list, $else); };
+                                           ^^^^^^^^^^
+test.y:31.11-32.63:  symbol not found in production: stmt
+ if_stmt5: IF expr[cond] THEN stmt.list[then] ELSE stmt.list[else] FI
+           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+test.y:31.40-43:     possibly meant: $then, hiding $[stmt.list] at $4
+ if_stmt5: IF expr[cond] THEN stmt.list[then] ELSE stmt.list[else] FI
+                                        ^^^^
+test.y:31.61-64:     possibly meant: $else, hiding $[stmt.list] at $6
+ if_stmt5: IF expr[cond] THEN stmt.list[then] ELSE stmt.list[else] FI
+                                                             ^^^^
+test.y:34.43-58: error: invalid reference: '$stmt.list.field'
+           { $if_stmt6 = new IfStmt($cond, $stmt.list.field, $else); };
+                                           ^^^^^^^^^^^^^^^^
+test.y:33.11-34.69:  symbol not found in production: stmt
+ if_stmt6: IF expr[cond] THEN stmt.list[then] ELSE stmt.list[else] FI
+           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+test.y:33.40-43:     possibly meant: $then.field, hiding
$[stmt.list].field at $4
+ if_stmt6: IF expr[cond] THEN stmt.list[then] ELSE stmt.list[else] FI
+                                        ^^^^
+test.y:33.61-64:     possibly meant: $else.field, hiding
$[stmt.list].field at $6
+ if_stmt6: IF expr[cond] THEN stmt.list[then] ELSE stmt.list[else] FI
+                                                             ^^^^
+test.y:36.43-54: error: invalid reference: '$[stmt.list]'
+           { $if_stmt7 = new IfStmt($cond, $[stmt.list].field, $else); };
+                                           ^^^^^^^^^^^^
+test.y:35.11-36.71:  symbol not found in production: stmt.list
+ if_stmt7: IF expr[cond] THEN stmt.list[then] ELSE stmt.list[else] FI
+           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+test.y:35.40-43:     possibly meant: $then, hiding $[stmt.list] at $4
+ if_stmt7: IF expr[cond] THEN stmt.list[then] ELSE stmt.list[else] FI
+                                        ^^^^
+test.y:35.61-64:     possibly meant: $else, hiding $[stmt.list] at $6
+ if_stmt7: IF expr[cond] THEN stmt.list[then] ELSE stmt.list[else] FI
+                                                             ^^^^
+test.y:38.43-49: error: invalid reference: '$then.1'
+           { $if_stmt8 = new IfStmt($cond, $then.1, $else); };
+                                           ^^^^^^^
+test.y:37.11-38.60:  symbol not found in production: then
+ if_stmt8: IF expr[cond] THEN stmt.list[then.1] ELSE stmt.list[else] FI
+           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+test.y:37.40-45:     possibly meant: $[then.1] at $4
+ if_stmt8: IF expr[cond] THEN stmt.list[then.1] ELSE stmt.list[else] FI
+                                        ^^^^^^
+test.y:40.43-55: error: invalid reference: '$then.1.field'
+           { $if_stmt9 = new IfStmt($cond, $then.1.field, $else); };
+                                           ^^^^^^^^^^^^^
+test.y:39.11-40.66:  symbol not found in production: then
+ if_stmt9: IF expr[cond] THEN stmt.list[then.1] ELSE stmt.list[else] FI
+           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+test.y:39.40-45:     possibly meant: $[then.1].field at $4
+ if_stmt9: IF expr[cond] THEN stmt.list[then.1] ELSE stmt.list[else] FI
+                                        ^^^^^^
+test.y:42.44-50: error: invalid reference: '$stmt.x'
+           { $if_stmt10 = new IfStmt($cond, $stmt.x, 0); };
+                                            ^^^^^^^
+test.y:41.12-42.57:  symbol not found in production: stmt
+ if_stmt10: IF expr[cond] THEN stmt[stmt.x] FI
+            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+test.y:41.36-41:     possibly meant: $[stmt.x].x, hiding $stmt.x at $4
+ if_stmt10: IF expr[cond] THEN stmt[stmt.x] FI
+                                    ^^^^^^
+test.y:41.36-41:     possibly meant: $[stmt.x] at $4
+ if_stmt10: IF expr[cond] THEN stmt[stmt.x] FI
+                                    ^^^^^^
+test.y:44.13-22: error: invalid reference: '$if-stmt-a'
+           { $if-stmt-a = new IfStmt($cond, $then, $else); };
+             ^^^^^^^^^^
+test.y:43.12-44.59:  symbol not found in production: if
+ if-stmt-a: IF expr[cond] THEN stmt.list[then] ELSE stmt.list[else] FI
+            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+test.y:43.1-9:       possibly meant: $[if-stmt-a] at $$
+ if-stmt-a: IF expr[cond] THEN stmt.list[then] ELSE stmt.list[else] FI
+ ^^^^^^^^^
+test.y:46.46-54: error: invalid reference: '$then-a.f'
+           { $[if-stmt-b] = new IfStmt($cond, $then-a.f, $else); };
+                                              ^^^^^^^^^
+test.y:45.12-46.65:  symbol not found in production: then
+ if-stmt-b: IF expr[cond] THEN if-stmt-a[then-a] ELSE stmt.list[else] FI
+            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+test.y:45.41-46:     possibly meant: $[then-a].f at $4
+ if-stmt-b: IF expr[cond] THEN if-stmt-a[then-a] ELSE stmt.list[else] FI
+                                         ^^^^^^
+]])
+
 AT_CLEANUP

 #######################################################################
diff --git a/tests/reduce.at b/tests/reduce.at
index 2d9093f..8ac894c 100644
--- a/tests/reduce.at
+++ b/tests/reduce.at
@@ -142,6 +142,65 @@ useless8: '8';
 useless9: '9';
 ]])

+AT_BISON_CHECK([[-fcaret input.y]], 0, [],
+[[input.y: warning: 9 nonterminals useless in grammar [-Wother]
+input.y: warning: 9 rules useless in grammar [-Wother]
+input.y:6.1-8: warning: nonterminal useless in grammar: useless1 [-Wother]
+ useless1: '1';
+ ^^^^^^^^
+input.y:7.1-8: warning: nonterminal useless in grammar: useless2 [-Wother]
+ useless2: '2';
+ ^^^^^^^^
+input.y:8.1-8: warning: nonterminal useless in grammar: useless3 [-Wother]
+ useless3: '3';
+ ^^^^^^^^
+input.y:9.1-8: warning: nonterminal useless in grammar: useless4 [-Wother]
+ useless4: '4';
+ ^^^^^^^^
+input.y:10.1-8: warning: nonterminal useless in grammar: useless5 [-Wother]
+ useless5: '5';
+ ^^^^^^^^
+input.y:11.1-8: warning: nonterminal useless in grammar: useless6 [-Wother]
+ useless6: '6';
+ ^^^^^^^^
+input.y:12.1-8: warning: nonterminal useless in grammar: useless7 [-Wother]
+ useless7: '7';
+ ^^^^^^^^
+input.y:13.1-8: warning: nonterminal useless in grammar: useless8 [-Wother]
+ useless8: '8';
+ ^^^^^^^^
+input.y:14.1-8: warning: nonterminal useless in grammar: useless9 [-Wother]
+ useless9: '9';
+ ^^^^^^^^
+input.y:6.11-13: warning: rule useless in grammar [-Wother]
+ useless1: '1';
+           ^^^
+input.y:7.11-13: warning: rule useless in grammar [-Wother]
+ useless2: '2';
+           ^^^
+input.y:8.11-13: warning: rule useless in grammar [-Wother]
+ useless3: '3';
+           ^^^
+input.y:9.11-13: warning: rule useless in grammar [-Wother]
+ useless4: '4';
+           ^^^
+input.y:10.11-13: warning: rule useless in grammar [-Wother]
+ useless5: '5';
+           ^^^
+input.y:11.11-13: warning: rule useless in grammar [-Wother]
+ useless6: '6';
+           ^^^
+input.y:12.11-13: warning: rule useless in grammar [-Wother]
+ useless7: '7';
+           ^^^
+input.y:13.11-13: warning: rule useless in grammar [-Wother]
+ useless8: '8';
+           ^^^
+input.y:14.11-13: warning: rule useless in grammar [-Wother]
+ useless9: '9';
+           ^^^
+]])
+
 AT_BISON_CHECK([[input.y]], 0, [],
 [[input.y: warning: 9 nonterminals useless in grammar [-Wother]
 input.y: warning: 9 rules useless in grammar [-Wother]
@@ -238,6 +297,26 @@ non_productive: non_productive useless_token
 %%
 ]])

+AT_BISON_CHECK([[-fcaret not-reduced.y]], 0, [],
+[[not-reduced.y: warning: 2 nonterminals useless in grammar [-Wother]
+not-reduced.y: warning: 3 rules useless in grammar [-Wother]
+not-reduced.y:14.1-13: warning: nonterminal useless in grammar:
not_reachable [-Wother]
+ not_reachable: useful  { /* A not reachable action. */ }
+ ^^^^^^^^^^^^^
+not-reduced.y:11.6-19: warning: nonterminal useless in grammar:
non_productive [-Wother]
+    | non_productive    { /* A non productive action. */ }
+      ^^^^^^^^^^^^^^
+not-reduced.y:11.6-57: warning: rule useless in grammar [-Wother]
+    | non_productive    { /* A non productive action. */ }
+      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+not-reduced.y:14.16-56: warning: rule useless in grammar [-Wother]
+ not_reachable: useful  { /* A not reachable action. */ }
+                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+not-reduced.y:17.17-18.63: warning: rule useless in grammar [-Wother]
+ non_productive: non_productive useless_token
+                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+]])
+
 AT_BISON_CHECK([[not-reduced.y]], 0, [],
 [[not-reduced.y: warning: 2 nonterminals useless in grammar [-Wother]
 not-reduced.y: warning: 3 rules useless in grammar [-Wother]
diff --git a/tests/regression.at b/tests/regression.at
index 7691420..c08059e 100644
--- a/tests/regression.at
+++ b/tests/regression.at
@@ -481,6 +481,14 @@ AT_BISON_CHECK([-o input.c input.y], [[0]], [[]],
 [[input.y:22.8-14: warning: symbol SPECIAL redeclared [-Wother]
 input.y:22.8-63: warning: symbol
"\\'?\"\a\b\f\n\r\t\v\001\201\001\201??!" used more than once as a
literal string [-Wother]
 ]])
+AT_BISON_CHECK([-fcaret -o input.c input.y], [[0]], [[]],
+[[input.y:22.8-14: warning: symbol SPECIAL redeclared [-Wother]
+ %token SPECIAL "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!"
+        ^^^^^^^
+input.y:22.8-63: warning: symbol
"\\'?\"\a\b\f\n\r\t\v\001\201\001\201??!" used more than once as a
literal string [-Wother]
+ %token SPECIAL "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!"
+        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+]])
 AT_COMPILE([input])

 # Checking the error message here guarantees that yytname, which does contain



reply via email to

[Prev in Thread] Current Thread [Next in Thread]