mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
warnings: raise warning for useless printers or destructors
* src/scan-code.h (code_props): Add field 'is_used'. (CODE_PROPS_NONE_INIT): Adjust. * src/scan-code.l (code_props_plain_init, code_props_symbol_action_init) (code_props_rule_action_init): Instead of implementing several times the initialization of the code_props structures, use code_props_none_init. * src/symtab.c (symbol_check_defined): If a symbol does not have a destructor (resp. printer) but has a type which has a destructor (resp. printer), then set field 'is_used' to true. (semantic_type_check_defined): If a type has a destructor (resp. printer) but all symbols of this type have already a destructor (resp. printer), then raise a warning. * tests/input.at (Useless printers or destructors): New. Signed-off-by: Akim Demaille <akim@lrde.epita.fr>
This commit is contained in:
committed by
Akim Demaille
parent
9641b918ba
commit
ea9a35c605
14
NEWS
14
NEWS
@@ -31,6 +31,20 @@ GNU Bison NEWS
|
||||
|
||||
This is now only a warning.
|
||||
|
||||
** Warnings about useless destructors or printers
|
||||
|
||||
Bison now warns about useless destructors or printers. In the following
|
||||
example, the printer for <type1>, and the destructor for <type2> are
|
||||
useless: all symbols of <type1> (token1) already have a printer, and all
|
||||
symbols of type <type2> (token2) already have a destructor.
|
||||
|
||||
%token <type1> token1
|
||||
<type2> token2
|
||||
<type3> token3
|
||||
<type4> token4
|
||||
%printer {} token1 <type1> <type3>
|
||||
%destructor {} token2 <type2> <type4>
|
||||
|
||||
** Additional yylex/yyparse arguments
|
||||
|
||||
The new directive %param declares additional arguments to both yylex and
|
||||
|
||||
@@ -69,6 +69,10 @@ typedef struct code_props {
|
||||
*/
|
||||
bool is_predicate;
|
||||
|
||||
/**
|
||||
* Whether this is actually used (i.e., not completely masked by
|
||||
* other code props). */
|
||||
bool is_used;
|
||||
|
||||
/** \c NULL iff \c code_props::kind is not \c CODE_PROPS_RULE_ACTION. */
|
||||
struct symbol_list *rule;
|
||||
@@ -86,8 +90,17 @@ typedef struct code_props {
|
||||
void code_props_none_init (code_props *self);
|
||||
|
||||
/** Equivalent to \c code_props_none_init. */
|
||||
#define CODE_PROPS_NONE_INIT \
|
||||
{CODE_PROPS_NONE, NULL, EMPTY_LOCATION_INIT, false, false, NULL, NULL}
|
||||
#define CODE_PROPS_NONE_INIT \
|
||||
{ \
|
||||
/* .kind = */ CODE_PROPS_NONE, \
|
||||
/* .code = */ NULL, \
|
||||
/* .location = */ EMPTY_LOCATION_INIT, \
|
||||
/* .is_value_used = */ false, \
|
||||
/* .is_predicate = */ false, \
|
||||
/* .is_used = */ false, \
|
||||
/* .rule = */ NULL, \
|
||||
/* .named_ref = */ NULL \
|
||||
}
|
||||
|
||||
/** Initialized by \c CODE_PROPS_NONE_INIT with no further modification. */
|
||||
extern code_props const code_props_none;
|
||||
|
||||
@@ -888,24 +888,20 @@ void
|
||||
code_props_plain_init (code_props *self, char const *code,
|
||||
location code_loc)
|
||||
{
|
||||
code_props_none_init (self);
|
||||
self->kind = CODE_PROPS_PLAIN;
|
||||
self->code = code;
|
||||
self->location = code_loc;
|
||||
self->is_value_used = false;
|
||||
self->rule = NULL;
|
||||
self->named_ref = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
code_props_symbol_action_init (code_props *self, char const *code,
|
||||
location code_loc)
|
||||
{
|
||||
code_props_none_init (self);
|
||||
self->kind = CODE_PROPS_SYMBOL_ACTION;
|
||||
self->code = code;
|
||||
self->location = code_loc;
|
||||
self->is_value_used = false;
|
||||
self->rule = NULL;
|
||||
self->named_ref = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -913,10 +909,10 @@ code_props_rule_action_init (code_props *self, char const *code,
|
||||
location code_loc, symbol_list *rule,
|
||||
named_ref *name, bool is_predicate)
|
||||
{
|
||||
code_props_none_init (self);
|
||||
self->kind = CODE_PROPS_RULE_ACTION;
|
||||
self->code = code;
|
||||
self->location = code_loc;
|
||||
self->is_value_used = false;
|
||||
self->rule = rule;
|
||||
self->named_ref = name;
|
||||
self->is_predicate = is_predicate;
|
||||
|
||||
20
src/symtab.c
20
src/symtab.c
@@ -419,6 +419,15 @@ symbol_check_defined (symbol *sym)
|
||||
sym->number = nvars++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
if (sym->props[i].kind == CODE_PROPS_NONE && sym->type_name)
|
||||
{
|
||||
semantic_type *sem_type = semantic_type_get (sym->type_name, NULL);
|
||||
if (sem_type
|
||||
&& sem_type->props[i].kind != CODE_PROPS_NONE)
|
||||
sem_type->props[i].is_used = true;
|
||||
}
|
||||
|
||||
/* Set the semantic type status associated to the current symbol to
|
||||
'declared' so that we could check semantic types unnecessary uses. */
|
||||
if (sym->type_name)
|
||||
@@ -434,7 +443,16 @@ symbol_check_defined (symbol *sym)
|
||||
static inline bool
|
||||
semantic_type_check_defined (semantic_type *sem_type)
|
||||
{
|
||||
if (sem_type->status != declared)
|
||||
if (sem_type->status == declared)
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
if (sem_type->props[i].kind != CODE_PROPS_NONE
|
||||
&& ! sem_type->props[i].is_used)
|
||||
warn_at (sem_type->location,
|
||||
_("useless %s for type <%s>"),
|
||||
code_props_type_string (i), sem_type->tag);
|
||||
}
|
||||
else
|
||||
warn_at (sem_type->location,
|
||||
_("type <%s> is used, but is not associated to any symbol"),
|
||||
sem_type->tag);
|
||||
|
||||
@@ -323,6 +323,51 @@ input.y:5.25-31: warning: type <type4> is used, but is not associated to any sym
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
## --------------------------------- ##
|
||||
## Useless printers or destructors. ##
|
||||
## --------------------------------- ##
|
||||
|
||||
AT_SETUP([Useless printers or destructors])
|
||||
|
||||
AT_DATA([[input.y]],
|
||||
[[%token <type1> token1
|
||||
%token <type2> token2
|
||||
%token <type3> token3
|
||||
%token <type4> token4
|
||||
%token <type5> token51 token52
|
||||
%token <type6> token61 token62
|
||||
%token <type7> token7
|
||||
|
||||
%printer {} token1
|
||||
%destructor {} token2
|
||||
%printer {} token51
|
||||
%destructor {} token61
|
||||
|
||||
%printer {} token7
|
||||
|
||||
%printer {} <type1>
|
||||
%destructor {} <type2>
|
||||
%printer {} <type3>
|
||||
%destructor {} <type4>
|
||||
|
||||
%printer {} <type5>
|
||||
%destructor {} <type6>
|
||||
|
||||
%destructor {} <type7>
|
||||
|
||||
%%
|
||||
exp: "a";
|
||||
]])
|
||||
|
||||
AT_BISON_CHECK([input.y], [0], [],
|
||||
[[input.y:16.13-19: warning: useless %printer for type <type1>
|
||||
input.y:17.16-22: warning: useless %destructor for type <type2>
|
||||
]])
|
||||
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
## ---------------------------------------- ##
|
||||
## Unused values with default %destructor. ##
|
||||
## ---------------------------------------- ##
|
||||
|
||||
Reference in New Issue
Block a user