bison-patches
[Top][All Lists]
Advanced

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

[PATCH 1/2] diagnostics: complain about undeclared string tokens


From: Akim Demaille
Subject: [PATCH 1/2] diagnostics: complain about undeclared string tokens
Date: Sun, 17 Nov 2019 18:37:02 +0100

String literals, which allow for better error messages, are (too)
liberally accepted by Bison, which might result in silent errors.  For
instance

    %type <exVal> cond "condition"

does not define “condition” as a string alias to 'cond' (nonterminal
symbols do not have string aliases).  It is rather equivalent to

    %nterm <exVal> cond
    %token <exVal> "condition"

i.e., it gives the type 'exVal' to the "condition" token, which was
clearly not the intention.

Introduce -Wdangling-alias to catch this.

* src/complain.h, src/complain.c: Add support for -Wdangling-alias.
(argmatch_warning_args): Sort.
* src/symtab.c (symbol_check_defined): Complain about dangling
aliases.
* doc/bison.texi: Document it.
* tests/input.at (Dangling aliases): New test.
---
 NEWS           | 38 ++++++++++++++++++++++++++++++++++++
 doc/bison.texi | 53 +++++++++++++++++++++++++++++++++++++++++++++++---
 src/complain.c | 18 +++++++++--------
 src/complain.h |  4 +++-
 src/symtab.c   |  9 ++++++++-
 tests/input.at | 25 ++++++++++++++++++++++++
 6 files changed, 134 insertions(+), 13 deletions(-)

diff --git a/NEWS b/NEWS
index 742ea743..4eb22cb7 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,44 @@ GNU Bison NEWS
 
 ** New Features
 
+*** New diagnostic: -Wdangling-alias
+
+  String literals, which allow for better error messages, are (too)
+  liberally accepted by Bison, which might result in silent errors.  For
+  instance
+
+    %type <exVal> cond "condition"
+
+  does not define "condition" as a string alias to 'cond' (nonterminal
+  symbols do not have string aliases).  It is rather equivalent to
+
+    %nterm <exVal> cond
+    %token <exVal> "condition"
+
+  i.e., it gives the type 'exVal' to the "condition" token, which was
+  clearly not the intention.
+
+  Also, because string aliases need not be defined, typos such as "baz"
+  instead of "bar" will be not reported.
+
+  The option -Wdangling-alias catches these situations.  On
+
+    %token BAR "bar"
+    %type <ival> foo "foo"
+    %%
+    foo: "baz" {}
+
+  bison -Wdangling-alias reports
+
+    warning: string literal not attached to a symbol
+          | %type <ival> foo "foo"
+          |                  ^~~~~
+    warning: string literal not attached to a symbol
+          | foo: "baz" {}
+          |      ^~~~~
+
+   The -Wall option does not (yet?) include -Wdangling-alias.
+
 *** Better POSIX Yacc compatibility diagnostics
 
   POSIX Yacc restricts %type to nonterminals.  This is now diagnosed by
diff --git a/doc/bison.texi b/doc/bison.texi
index d9495ffe..96dbd2a5 100644
--- a/doc/bison.texi
+++ b/doc/bison.texi
@@ -3551,8 +3551,9 @@ They are still considered distinct rules even when joined 
in this way.
 @findex %empty
 
 A rule is said to be @dfn{empty} if its right-hand side (@var{components})
-is empty.  It means that @var{result} can match the empty string.  For
-example, here is how to define an optional semicolon:
+is empty.  It means that @var{result} in the previous example can match the
+empty string.  As another example, here is how to define an optional
+semicolon:
 
 @example
 semicolon.opt: | ";";
@@ -10531,6 +10532,52 @@ unexpected number of conflicts is an error, and an 
expected number of
 conflicts is not reported, so @option{-W} and @option{--warning} then have
 no effect on the conflict report.
 
+@item dangling-alias
+Report string literals that are not bound to a token symbol.
+
+String literals, which allow for better error messages, are (too) liberally
+accepted by Bison, which might result in silent errors.  For instance
+
+@example
+%type <exVal> cond "condition"
+@end example
+
+@noindent
+does not define ``condition'' as a string alias to @code{cond}---nonterminal
+symbols do not have string aliases.  It is rather equivalent to
+
+@example
+%nterm <exVal> cond
+%token <exVal> "condition"
+@end example
+
+@noindent
+i.e., it gives the @samp{"condition"} token the type @code{exVal}.
+
+Also, because string aliases do not need to be defined, typos such as
+@samp{"baz"} instead of @samp{"bar"} will be not reported.
+
+The option @option{-Wdangling-alias} catches these situations.  On
+
+@example
+%token BAR "bar"
+%type <ival> foo "foo"
+%%
+foo: "baz" @{@}
+@end example
+
+@noindent
+@command{bison -Wdangling-alias} reports
+
+@example
+@dwarning{warning}: string literal not attached to a symbol
+      | %type <ival> foo @dwarning{"foo"}
+      |                  @dwarning{^~~~~}
+@dwarning{warning}: string literal not attached to a symbol
+      | foo: @dwarning{"baz"} @{@}
+      |      @dwarning{^~~~~}
+@end example
+
 @item deprecated
 Deprecated constructs whose support will be removed in future versions of
 Bison.
@@ -10632,7 +10679,7 @@ releases of Bison may move warnings from this category 
to new, more specific
 categories.
 
 @item all
-All the warnings except @code{yacc}.
+All the warnings except @code{dangling-alias} and @code{yacc}.
 
 @item none
 Turn off all the warnings.
diff --git a/src/complain.c b/src/complain.c
index 87563d59..d945d583 100644
--- a/src/complain.c
+++ b/src/complain.c
@@ -113,13 +113,14 @@ static const argmatch_warning_doc argmatch_warning_docs[] 
=
 {
   { "conflicts-sr",     N_("S/R conflicts (enabled by default)") },
   { "conflicts-rr",     N_("R/R conflicts (enabled by default)") },
+  { "dangling-alias",   N_("string aliases not attached to a symbol") },
   { "deprecated",       N_("obsolete constructs") },
   { "empty-rule",       N_("empty rules without %empty") },
   { "midrule-values",   N_("unset or unused midrule values") },
   { "precedence",       N_("useless precedence and associativity") },
   { "yacc",             N_("incompatibilities with POSIX Yacc") },
   { "other",            N_("all other warnings (enabled by default)") },
-  { "all",              N_("all the warnings except 'yacc'") },
+  { "all",              N_("all the warnings except 'dangling-alias' and 
'yacc'") },
   { "no-CATEGORY",      N_("turn off warnings in CATEGORY") },
   { "none",             N_("turn off all the warnings") },
   { "error[=CATEGORY]", N_("treat warnings as errors") },
@@ -128,17 +129,18 @@ static const argmatch_warning_doc argmatch_warning_docs[] 
=
 
 static const argmatch_warning_arg argmatch_warning_args[] =
 {
-  { "none",           Wnone },
-  { "midrule-values", Wmidrule_values },
-  { "yacc",           Wyacc },
-  { "conflicts-sr",   Wconflicts_sr },
+  { "all",            Wall },
   { "conflicts-rr",   Wconflicts_rr },
+  { "conflicts-sr",   Wconflicts_sr },
+  { "dangling-alias", Wdangling_alias },
   { "deprecated",     Wdeprecated },
   { "empty-rule",     Wempty_rule },
-  { "precedence",     Wprecedence },
-  { "other",          Wother },
-  { "all",            Wall },
   { "everything",     Weverything },
+  { "midrule-values", Wmidrule_values },
+  { "none",           Wnone },
+  { "other",          Wother },
+  { "precedence",     Wprecedence },
+  { "yacc",           Wyacc },
   { NULL, Wnone }
 };
 
diff --git a/src/complain.h b/src/complain.h
index 4b73d08d..5d112c23 100644
--- a/src/complain.h
+++ b/src/complain.h
@@ -47,6 +47,7 @@ typedef enum
   {
     warning_conflicts_rr,
     warning_conflicts_sr,
+    warning_dangling_alias,
     warning_deprecated,
     warning_empty_rule,
     warning_midrule_values,
@@ -104,6 +105,7 @@ typedef enum
 
     Wconflicts_rr     = 1 << warning_conflicts_rr,
     Wconflicts_sr     = 1 << warning_conflicts_sr,
+    Wdangling_alias   = 1 << warning_dangling_alias,
     Wdeprecated       = 1 << warning_deprecated,
     Wempty_rule       = 1 << warning_empty_rule,
     Wmidrule_values   = 1 << warning_midrule_values,
@@ -118,7 +120,7 @@ typedef enum
 
     /**< All above warnings.  */
     Weverything       = ~complaint & ~fatal & ~silent,
-    Wall              = Weverything & ~Wyacc
+    Wall              = Weverything & ~Wdangling_alias & ~Wyacc
   } warnings;
 
 /** Whether the warnings of \a flags are all unset.
diff --git a/src/symtab.c b/src/symtab.c
index 73111b51..589da0ae 100644
--- a/src/symtab.c
+++ b/src/symtab.c
@@ -26,12 +26,12 @@
 #include <assure.h>
 #include <fstrcmp.h>
 #include <hash.h>
+#include <quote.h>
 
 #include "complain.h"
 #include "getargs.h"
 #include "gram.h"
 #include "intprops.h"
-#include "quote.h"
 
 static struct hash_table *symbol_table = NULL;
 static struct hash_table *semantic_type_table = NULL;
@@ -610,6 +610,13 @@ symbol_check_defined (symbol *sym)
       s->number = nvars++;
     }
 
+  if (s->class == token_sym
+      && sym->tag[0] == '"'
+      && !sym->is_alias)
+    complain (&sym->location, Wdangling_alias,
+              _("string literal %s not attached to a symbol"),
+              sym->tag);
+
   for (int i = 0; i < 2; ++i)
     symbol_code_props_get (sym, i)->is_used = true;
 
diff --git a/tests/input.at b/tests/input.at
index 00e3a508..96e20a71 100644
--- a/tests/input.at
+++ b/tests/input.at
@@ -298,6 +298,31 @@ input.y:8.14: error: syntax error, unexpected integer
 AT_CLEANUP
 
 
+## ------------------ ##
+## Dangling aliases.  ##
+## ------------------ ##
+
+AT_SETUP([Dangling aliases])
+
+AT_DATA([input.y],
+[[%token FOO "foo"
+%type <val> "bar"
+%%
+expr: "foo" "bar" "baz"
+]])
+
+AT_BISON_CHECK([-fcaret -Wdangling input.y], [0], [],
+[[input.y:2.13-17: warning: string literal "bar" not attached to a symbol 
[-Wdangling-alias]
+    2 | %type <val> "bar"
+      |             ^~~~~
+input.y:4.19-23: warning: string literal "baz" not attached to a symbol 
[-Wdangling-alias]
+    4 | expr: "foo" "bar" "baz"
+      |                   ^~~~~
+]])
+
+AT_CLEANUP
+
+
 ## --------------------- ##
 ## Symbol declarations.  ##
 ## --------------------- ##
-- 
2.24.0




reply via email to

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