mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-17 00:03:03 +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.
|
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
|
** Additional yylex/yyparse arguments
|
||||||
|
|
||||||
The new directive %param declares additional arguments to both yylex and
|
The new directive %param declares additional arguments to both yylex and
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ typedef struct code_props {
|
|||||||
*/
|
*/
|
||||||
bool is_predicate;
|
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. */
|
/** \c NULL iff \c code_props::kind is not \c CODE_PROPS_RULE_ACTION. */
|
||||||
struct symbol_list *rule;
|
struct symbol_list *rule;
|
||||||
@@ -86,8 +90,17 @@ typedef struct code_props {
|
|||||||
void code_props_none_init (code_props *self);
|
void code_props_none_init (code_props *self);
|
||||||
|
|
||||||
/** Equivalent to \c code_props_none_init. */
|
/** Equivalent to \c code_props_none_init. */
|
||||||
#define CODE_PROPS_NONE_INIT \
|
#define CODE_PROPS_NONE_INIT \
|
||||||
{CODE_PROPS_NONE, NULL, EMPTY_LOCATION_INIT, false, false, NULL, NULL}
|
{ \
|
||||||
|
/* .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. */
|
/** Initialized by \c CODE_PROPS_NONE_INIT with no further modification. */
|
||||||
extern code_props const code_props_none;
|
extern code_props const code_props_none;
|
||||||
|
|||||||
@@ -888,24 +888,20 @@ void
|
|||||||
code_props_plain_init (code_props *self, char const *code,
|
code_props_plain_init (code_props *self, char const *code,
|
||||||
location code_loc)
|
location code_loc)
|
||||||
{
|
{
|
||||||
|
code_props_none_init (self);
|
||||||
self->kind = CODE_PROPS_PLAIN;
|
self->kind = CODE_PROPS_PLAIN;
|
||||||
self->code = code;
|
self->code = code;
|
||||||
self->location = code_loc;
|
self->location = code_loc;
|
||||||
self->is_value_used = false;
|
|
||||||
self->rule = NULL;
|
|
||||||
self->named_ref = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
code_props_symbol_action_init (code_props *self, char const *code,
|
code_props_symbol_action_init (code_props *self, char const *code,
|
||||||
location code_loc)
|
location code_loc)
|
||||||
{
|
{
|
||||||
|
code_props_none_init (self);
|
||||||
self->kind = CODE_PROPS_SYMBOL_ACTION;
|
self->kind = CODE_PROPS_SYMBOL_ACTION;
|
||||||
self->code = code;
|
self->code = code;
|
||||||
self->location = code_loc;
|
self->location = code_loc;
|
||||||
self->is_value_used = false;
|
|
||||||
self->rule = NULL;
|
|
||||||
self->named_ref = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -913,10 +909,10 @@ code_props_rule_action_init (code_props *self, char const *code,
|
|||||||
location code_loc, symbol_list *rule,
|
location code_loc, symbol_list *rule,
|
||||||
named_ref *name, bool is_predicate)
|
named_ref *name, bool is_predicate)
|
||||||
{
|
{
|
||||||
|
code_props_none_init (self);
|
||||||
self->kind = CODE_PROPS_RULE_ACTION;
|
self->kind = CODE_PROPS_RULE_ACTION;
|
||||||
self->code = code;
|
self->code = code;
|
||||||
self->location = code_loc;
|
self->location = code_loc;
|
||||||
self->is_value_used = false;
|
|
||||||
self->rule = rule;
|
self->rule = rule;
|
||||||
self->named_ref = name;
|
self->named_ref = name;
|
||||||
self->is_predicate = is_predicate;
|
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++;
|
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
|
/* Set the semantic type status associated to the current symbol to
|
||||||
'declared' so that we could check semantic types unnecessary uses. */
|
'declared' so that we could check semantic types unnecessary uses. */
|
||||||
if (sym->type_name)
|
if (sym->type_name)
|
||||||
@@ -434,7 +443,16 @@ symbol_check_defined (symbol *sym)
|
|||||||
static inline bool
|
static inline bool
|
||||||
semantic_type_check_defined (semantic_type *sem_type)
|
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,
|
warn_at (sem_type->location,
|
||||||
_("type <%s> is used, but is not associated to any symbol"),
|
_("type <%s> is used, but is not associated to any symbol"),
|
||||||
sem_type->tag);
|
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
|
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. ##
|
## Unused values with default %destructor. ##
|
||||||
## ---------------------------------------- ##
|
## ---------------------------------------- ##
|
||||||
|
|||||||
Reference in New Issue
Block a user