Also warn about non-used mid-rule values.

* src/symlist.h, src/symlist.c (symbol_list): Add a mid_rule
member.
(symbol_list_new): Adjust.
* src/reader.c (symbol_typed_p): New.
(grammar_rule_check): Use it.
(grammar_midrule_action): Bind a mid-rule LHS to its rule.
Check its rule.
* tests/input.at (AT_CHECK_UNUSED_VALUES): New.
Use it.
* tests/actions.at (Exotic Dollars): Adjust.
This commit is contained in:
Akim Demaille
2006-01-04 09:18:37 +00:00
parent 378f4bd846
commit 8486615972
7 changed files with 115 additions and 42 deletions

View File

@@ -1,3 +1,17 @@
2006-01-04 Akim Demaille <akim@epita.fr>
Also warn about non-used mid-rule values.
* src/symlist.h, src/symlist.c (symbol_list): Add a mid_rule
member.
(symbol_list_new): Adjust.
* src/reader.c (symbol_typed_p): New.
(grammar_rule_check): Use it.
(grammar_midrule_action): Bind a mid-rule LHS to its rule.
Check its rule.
* tests/input.at (AT_CHECK_UNUSED_VALUES): New.
Use it.
* tests/actions.at (Exotic Dollars): Adjust.
2006-01-04 Akim Demaille <akim@epita.fr> 2006-01-04 Akim Demaille <akim@epita.fr>
* src/reader.c (grammar_midrule_action): If $$ is set in a * src/reader.c (grammar_midrule_action): If $$ is set in a

11
NEWS
View File

@@ -26,6 +26,17 @@ Changes in version 2.1a:
| exp "+" exp { $$ = $1; (void) $3; } | exp "+" exp { $$ = $1; (void) $3; }
; ;
If there are mid-rule actions, the warning is issued if no action
uses it. The following triggers no warning: $1 and $3 are used.
exp: exp { push ($1); } '+' exp { push ($3); sum (); };
Mid-rule actions that use $$ cause the corresponding value to be
set, therefore the following action must use it. The following rule
triggers a warning about $2.
exp: '1' { $$ = 1; } '+' exp { $$ = $1 + $4; };
The warning is intended to help catching lost values and memory leaks. The warning is intended to help catching lost values and memory leaks.
If a value is ignored, its associated memory typically is not reclaimed. If a value is ignored, its associated memory typically is not reclaimed.

View File

@@ -210,6 +210,20 @@ grammar_current_rule_begin (symbol *lhs, location loc)
} }
/*-----------------------------------------------------------------.
| A symbol is typed if it has a declared %type, or if it is a |
| mid-rule symbol (i.e., the generated LHS replacing a mid-rule |
| action) that was assigned to, as in `exp: { $$ = 1; } { $$ = $1; |
| }'. |
`-----------------------------------------------------------------*/
static bool
symbol_typed_p (const symbol_list *s)
{
return (s->sym->type_name
|| s->mid_rule && s->mid_rule->used);
}
/*----------------------------------------------------------------. /*----------------------------------------------------------------.
| Check that the rule R is properly defined. For instance, there | | Check that the rule R is properly defined. For instance, there |
| should be no type clash on the default action. | | should be no type clash on the default action. |
@@ -251,7 +265,7 @@ grammar_rule_check (const symbol_list *r)
int n = 0; int n = 0;
for (; l && l->sym; l = l->next, ++n) for (; l && l->sym; l = l->next, ++n)
if (! (l->used if (! (l->used
|| !l->sym->type_name || !symbol_typed_p (l)
/* The default action, $$ = $1, `uses' both. */ /* The default action, $$ = $1, `uses' both. */
|| (!r->action && (n == 0 || n == 1)))) || (!r->action && (n == 0 || n == 1))))
{ {
@@ -318,14 +332,16 @@ grammar_midrule_action (void)
grammar = midrule; grammar = midrule;
/* End the dummy's rule. */ /* End the dummy's rule. */
previous_rule_end = symbol_list_new (NULL, dummy_location); midrule->next = symbol_list_new (NULL, dummy_location);
previous_rule_end->next = current_rule; grammar_rule_check (midrule);
midrule->next->next = current_rule;
midrule->next = previous_rule_end; previous_rule_end = midrule->next;
/* Insert the dummy nonterminal replacing the midrule action into /* Insert the dummy nonterminal replacing the midrule action into
the current rule. */ the current rule. Bind it to its dedicated rule. */
grammar_current_rule_symbol_append (dummy, dummy_location); grammar_current_rule_symbol_append (dummy, dummy_location);
grammar_end->mid_rule = midrule;
} }
/* Set the precedence symbol of the current rule to PRECSYM. */ /* Set the precedence symbol of the current rule to PRECSYM. */

View File

@@ -1,6 +1,6 @@
/* Lists of symbols for Bison /* Lists of symbols for Bison
Copyright (C) 2002, 2005 Free Software Foundation, Inc. Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler. This file is part of Bison, the GNU Compiler Compiler.
@@ -38,6 +38,8 @@ symbol_list_new (symbol *sym, location loc)
res->sym = sym; res->sym = sym;
res->location = loc; res->location = loc;
res->mid_rule = NULL;
res->action = NULL; res->action = NULL;
res->used = false; res->used = false;

View File

@@ -32,6 +32,10 @@ typedef struct symbol_list
symbol *sym; symbol *sym;
location location; location location;
/* If this symbol is the generated lhs for a mid-rule, a pointer to
that mid-rule. */
struct symbol_list *mid_rule;
/* The action is attached to the LHS of a rule. */ /* The action is attached to the LHS of a rule. */
const char *action; const char *action;
location action_location; location action_location;

View File

@@ -113,6 +113,7 @@ AT_DATA_GRAMMAR([[input.y]],
exp: a_1 a_2 { $<val>$ = 3; } { $<val>$ = $<val>3 + 1; } a_5 exp: a_1 a_2 { $<val>$ = 3; } { $<val>$ = $<val>3 + 1; } a_5
sum_of_the_five_previous_values sum_of_the_five_previous_values
{ {
USE (($1, $2, $<foo>3, $<foo>4, $5));
printf ("%d\n", $6); printf ("%d\n", $6);
} }
; ;
@@ -146,11 +147,7 @@ main (void)
} }
]]) ]])
AT_CHECK([bison -d -v -o input.c input.y], 0, [], AT_CHECK([bison -d -v -o input.c input.y], 0)
[input.y:30.6-34.5: warning: unused value: $1
input.y:30.6-34.5: warning: unused value: $2
input.y:30.6-34.5: warning: unused value: $5
])
AT_COMPILE([input]) AT_COMPILE([input])
AT_PARSER_CHECK([./input], 0, AT_PARSER_CHECK([./input], 0,
[[15 [[15

View File

@@ -86,51 +86,80 @@ AT_CLEANUP
## Unused values. ## ## Unused values. ##
## --------------- ## ## --------------- ##
AT_SETUP([Unused values]) m4_define([AT_CHECK_UNUSED_VALUES],
[AT_SETUP([Unused values])
AT_DATA([input.y], AT_DATA([input.y],
[[%token <integer> INT [[%token <integer> INT
%type <integer> exp %type <integer> exp
%% %%
exp: exp:
INT { } INT { } INT { } $1
/* Ideally we would like to complain also about $2 and $4 here, but | INT
it's hard to implement. */
| INT { $$ } INT { $$ } INT { }
| INT { $1 } INT { } INT { }
| INT { } INT { $1 } INT { }
| INT { } INT { } INT { $1 }
| INT { } INT { } INT { $$ = $1 + $3 + $5; }
; ;
]]) ]])
AT_CHECK([bison input.y], [], [], AT_CHECK([bison input.y], [], [],
[[input.y:5.3-25: warning: unset value: $$ [[$2]])
AT_CLEANUP
])
AT_CHECK_UNUSED_VALUES([INT { } INT { } INT { }],
[input.y:5.3-25: warning: unset value: $$
input.y:5.3-25: warning: unused value: $1 input.y:5.3-25: warning: unused value: $1
input.y:5.3-25: warning: unused value: $3 input.y:5.3-25: warning: unused value: $3
input.y:5.3-25: warning: unused value: $5 input.y:5.3-25: warning: unused value: $5
input.y:8.3-31: warning: unset value: $$ ])
input.y:8.3-31: warning: unused value: $1
input.y:8.3-31: warning: unused value: $3 AT_CHECK_UNUSED_VALUES([INT { $1 } INT { } INT { }],
input.y:8.3-31: warning: unused value: $5 [input.y:5.3-28: warning: unset value: $$
input.y:9.3-28: warning: unset value: $$ input.y:5.3-28: warning: unused value: $3
input.y:9.3-28: warning: unused value: $3 input.y:5.3-28: warning: unused value: $5
input.y:9.3-28: warning: unused value: $5 ])
input.y:10.3-28: warning: unset value: $$
input.y:10.3-28: warning: unused value: $3 AT_CHECK_UNUSED_VALUES([INT { } INT { $1 } INT { }],
input.y:10.3-28: warning: unused value: $5 [input.y:5.3-28: warning: unset value: $$
input.y:11.3-29: warning: unset value: $$ input.y:5.3-28: warning: unused value: $3
input.y:11.3-29: warning: unused value: $3 input.y:5.3-28: warning: unused value: $5
input.y:11.3-29: warning: unused value: $5 ])
input.y: conflicts: 1 reduce/reduce
input.y:8.7-12: warning: rule never reduced because of conflicts: @3: /* empty */ AT_CHECK_UNUSED_VALUES([INT { } INT { } INT { $1 }],
input.y:9.7-12: warning: rule never reduced because of conflicts: @5: /* empty */ [input.y:5.3-29: warning: unset value: $$
input.y:10.7-9: warning: rule never reduced because of conflicts: @7: /* empty */ input.y:5.3-29: warning: unused value: $3
input.y:11.7-9: warning: rule never reduced because of conflicts: @9: /* empty */ input.y:5.3-29: warning: unused value: $5
input.y:12.7-9: warning: rule never reduced because of conflicts: @11: /* empty */ ])
]])
AT_CHECK_UNUSED_VALUES([INT { } INT { } INT { $$ = $1 + $3 + $5; }])
# Checking mid-rule values.
AT_CHECK_UNUSED_VALUES([INT { $$ } INT { $$ } INT { }],
[input.y:5.3-31: warning: unset value: $$
input.y:5.3-31: warning: unused value: $1
input.y:5.3-31: warning: unused value: $2
input.y:5.3-31: warning: unused value: $3
input.y:5.3-31: warning: unused value: $4
input.y:5.3-31: warning: unused value: $5
])
AT_CHECK_UNUSED_VALUES([INT { $$ } INT { $$ = $2 } INT { }],
[input.y:5.3-36: warning: unset value: $$
input.y:5.3-36: warning: unused value: $1
input.y:5.3-36: warning: unused value: $3
input.y:5.3-36: warning: unused value: $4
input.y:5.3-36: warning: unused value: $5
])
# AT_CHECK_UNUSED_VALUES([INT { $$ } { $$ = $2 } { }],
# [input.y:5.3-36: warning: unset value: $$
# input.y:5.3-36: warning: unused value: $1
# input.y:5.3-36: warning: unused value: $3
# input.y:5.3-36: warning: unused value: $4
# input.y:5.3-36: warning: unused value: $5
# ])
AT_CHECK_UNUSED_VALUES([INT { $$ = $1 } INT { $$ = $2 + $3 } INT { $$ = $4 + $5 }])
AT_CLEANUP
## ---------------------- ## ## ---------------------- ##