[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