Skip to content

Commit f7022e0

Browse files
committed
diagnostics: report useless actions
In order for the useless chain productions to work properly, there should not be actions that make explicit the default behavior. * src/scan-code.l (strspacecmp, useless_default_action): New. (translate_action): Report useless actions. * src/reader.c (grammar_rule_check_and_complete): Don't trigger this warning when generating explicit actions for C++. * tests/actions.at (Useless default actions): New.
1 parent f28c1e3 commit f7022e0

File tree

3 files changed

+121
-4
lines changed

3 files changed

+121
-4
lines changed

src/reader.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,10 @@ grammar_rule_check_and_complete (symbol_list *r)
300300
|| STREQ (skeleton, "lalr1.cc")));
301301
if (is_cxx)
302302
{
303-
code_props_rule_action_init (&r->action_props, "{ $$ = $1; }",
303+
/* Parens around $1 to avoid triggering the warning
304+
about useless explicit actions. */
305+
code_props_rule_action_init (&r->action_props,
306+
"{ $$ = ($1); }",
304307
r->rhs_loc, r,
305308
/* name */ NULL,
306309
/* type */ NULL,

src/scan-code.l

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <quote.h>
2727

2828
#include "src/complain.h"
29+
#include "src/fixits.h"
2930
#include "src/getargs.h"
3031
#include "src/muscle-tab.h"
3132
#include "src/reader.h"
@@ -290,9 +291,9 @@ variant_add (uniqstr id, location id_loc, int symbol_index,
290291
char const *cp, char const *cp_end, bool explicit_bracketing)
291292
{
292293
char const *prefix_end = find_prefix_end (id, cp, cp_end);
293-
if (prefix_end &&
294-
(prefix_end == cp_end ||
295-
(!explicit_bracketing && is_dot_or_dash (*prefix_end))))
294+
if (prefix_end
295+
&& (prefix_end == cp_end
296+
|| (!explicit_bracketing && is_dot_or_dash (*prefix_end))))
296297
{
297298
variant *r = variant_table_grow ();
298299
r->symbol_index = symbol_index;
@@ -739,6 +740,70 @@ handle_action_at (symbol_list *rule, char *text, const location *at_loc)
739740
}
740741

741742

743+
/* Comparing two strings, ignoring spaces. */
744+
static int
745+
strspacecmp (const char *cp1, const char* cp2)
746+
{
747+
aver (cp1 && cp2);
748+
while (*cp1 && *cp2)
749+
{
750+
while (c_isspace (*cp1))
751+
++cp1;
752+
while (c_isspace (*cp2))
753+
++cp2;
754+
if (*cp1 == *cp2)
755+
{
756+
++cp1;
757+
++cp2;
758+
}
759+
else
760+
break;
761+
}
762+
return *cp1 - *cp2;
763+
}
764+
765+
/* Whether this rule could have been left implicit.
766+
767+
A more natural place for this check is
768+
grammar_rule_check_and_complete, but it is called after the action
769+
was translated. Maybe we should compare translated code
770+
instead? */
771+
772+
static bool
773+
useless_default_action (code_props *self)
774+
{
775+
/* Somewhat duplicates a part of grammar_rule_check_and_complete. */
776+
symbol_list const *r = self->rule;
777+
char const *lhs_type = r->content.sym->content->type_name;
778+
if (!lhs_type)
779+
return false;
780+
781+
/* The default action is installed for any rule with a non-empty
782+
RHS. But it feels less natural not to write the action in this
783+
case. Besides, the real point of -Wuseless-action is to help
784+
getting rid of useless chain rules by exhibiting more
785+
opportunities. And this is only for rules with a single RHS
786+
symbol (so two symbols with the LHS). */
787+
if (symbol_list_length (r) != 2)
788+
return false;
789+
790+
/* If the first rhs is a dummy, then we cannot simply remove the
791+
default action that is afterwards. Something fishy is going on,
792+
but maybe a different warning for this case?
793+
794+
foo: bar { $$ = 42; } { $$ = $1; } */
795+
symbol const *rhs = r->next->content.sym;
796+
if (symbol_is_dummy (rhs))
797+
return false;
798+
799+
char const *rhs_type = rhs->content->type_name;
800+
if (!UNIQSTR_EQ (lhs_type, rhs_type ? rhs_type : ""))
801+
return false;
802+
803+
return strspacecmp (self->code, "{ $$ = $1; }") == 0;
804+
}
805+
806+
742807
/*-------------------------.
743808
| Initialize the scanner. |
744809
`-------------------------*/
@@ -757,6 +822,15 @@ translate_action (code_props *self, int sc_context)
757822
initialized = true;
758823
}
759824

825+
/* Warn about explicit default actions. */
826+
if (sc_context == SC_RULE_ACTION
827+
&& warning_is_enabled (Wuseless_action)
828+
&& useless_default_action (self))
829+
{
830+
complain (&self->location, Wuseless_action, _("useless explicit action"));
831+
fixits_register (&self->location, "");
832+
}
833+
760834
loc->start = loc->end = self->location.start;
761835
yy_switch_to_buffer (yy_scan_string (self->code));
762836
char *res = code_lex (self, sc_context);

tests/actions.at

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,46 @@ AT_PARSER_CHECK([input], 0,
115115
AT_CLEANUP
116116

117117

118+
## ------------------------- ##
119+
## Useless default actions. ##
120+
## ------------------------- ##
121+
122+
AT_SETUP([Useless default actions])
123+
124+
AT_BISON_OPTION_PUSHDEFS
125+
AT_DATA_GRAMMAR([[input.y]],
126+
[[%union {
127+
int ival;
128+
int ival2;
129+
}
130+
%type <ival> expr term fact
131+
%type <ival2> "number"
132+
%%
133+
expr: expr '+' term { $$ = $1; } // No warning: too many symbols.
134+
expr: term { $$ = $1; }
135+
term: term '*' fact { $$ = $1; } | fact { $$ = $1 ; }
136+
// No warning: types differ.
137+
fact: "number" { $$ = $1; }
138+
// No warning: there is a midrule action.
139+
fact: <ival>{ $$ = 42; } { $$ = $1; }
140+
;
141+
%%
142+
]])
143+
AT_BISON_OPTION_POPDEFS
144+
145+
AT_BISON_CHECK([-Wuseless-action -fcaret input.y], [], [],
146+
[[input.y:17.12-23: warning: useless explicit action [-Wuseless-action]
147+
17 | expr: term { $$ = $1; }
148+
| ^~~~~~~~~~~~
149+
input.y:18.41-57: warning: useless explicit action [-Wuseless-action]
150+
18 | term: term '*' fact { $$ = $1; } | fact { $$ = $1 ; }
151+
| ^~~~~~~~~~~~~~~~~
152+
input.y: warning: fix-its can be applied. Rerun with option '--update'. [-Wother]
153+
]])
154+
AT_CLEANUP
155+
156+
157+
118158
## ----------------------- ##
119159
## Implicitly empty rule. ##
120160
## ----------------------- ##

0 commit comments

Comments
 (0)