mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-13 22:33:03 +00:00
Don't leak semantic values for parent RHS when a user action cuts the
parser, and clean up related code a bit. * tests/glr-regression.at (Leaked merged semantic value if user action cuts parse) Rename to... (Leaked semantic values if user action cuts parse) ... this. Add check for leaked parent RHS values. * data/glr.c (yydestroyGLRState): In debugging output, distinguish between an unresolved state (non-empty chain of semantic options) and an incomplete one (signaled by an empty chain). (yyresolveStates): Document the interface. Move all manipulation of an successfully or unsuccessfully resolved yyGLRState to... (yyresolveValue): ... here so that yyresolveValue always leaves a yyGLRState with consistent data and thus is easier to understand. Remove the yyvalp and yylocp parameters since they are always just taken from the yys parameter. When reporting a discarded merged value in debugging output, note that it is incompletely merged. Document the interface. (yyresolveAction): If resolving any of the RHS states fails, destroy them all rather than leaking them. Thus, as long as user actions are written to clean up the RHS correctly, yyresolveAction always cleans up the RHS of a semantic option. Document the interface.
This commit is contained in:
@@ -941,34 +941,75 @@ AT_CLEANUP
|
||||
|
||||
|
||||
## ------------------------------------------------------------------------- ##
|
||||
## Leaked merged semantic value if user action cuts parse. ##
|
||||
## Leaked semantic values if user action cuts parse. ##
|
||||
## ------------------------------------------------------------------------- ##
|
||||
|
||||
AT_SETUP([Leaked merged semantic value if user action cuts parse])
|
||||
AT_SETUP([Leaked semantic values if user action cuts parse])
|
||||
|
||||
AT_DATA_GRAMMAR([glr-regr12.y],
|
||||
[[
|
||||
%glr-parser
|
||||
%union { int dummy; }
|
||||
%type <dummy> start
|
||||
%destructor { has_value = 0; } start
|
||||
%token PARENT_RHS_AFTER
|
||||
%type <dummy> parent_rhs_before merged PARENT_RHS_AFTER
|
||||
%destructor { parent_rhs_before_value = 0; } parent_rhs_before
|
||||
%destructor { merged_value = 0; } merged
|
||||
%destructor { parent_rhs_after_value = 0; } PARENT_RHS_AFTER
|
||||
|
||||
%{
|
||||
# include <stdlib.h>
|
||||
static int merge (YYSTYPE, YYSTYPE);
|
||||
static void yyerror (char const *);
|
||||
static int yylex (void);
|
||||
static int has_value = 0;
|
||||
static int parent_rhs_before_value = 0;
|
||||
static int merged_value = 0;
|
||||
static int parent_rhs_after_value = 0;
|
||||
# define USE(val)
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
start:
|
||||
%merge<merge> { has_value = 1; USE ($$); }
|
||||
| %merge<merge> { USE ($$); YYACCEPT; }
|
||||
alt1 %dprec 1
|
||||
| alt2 %dprec 2
|
||||
;
|
||||
|
||||
alt1:
|
||||
PARENT_RHS_AFTER {
|
||||
USE ($1);
|
||||
parent_rhs_after_value = 0;
|
||||
}
|
||||
;
|
||||
|
||||
alt2:
|
||||
parent_rhs_before merged PARENT_RHS_AFTER {
|
||||
USE (($1, $2, $3));
|
||||
parent_rhs_before_value = 0;
|
||||
merged_value = 0;
|
||||
parent_rhs_after_value = 0;
|
||||
}
|
||||
;
|
||||
|
||||
parent_rhs_before:
|
||||
{
|
||||
USE ($$);
|
||||
parent_rhs_before_value = 1;
|
||||
}
|
||||
;
|
||||
|
||||
merged:
|
||||
%merge<merge> {
|
||||
USE ($$);
|
||||
merged_value = 1;
|
||||
}
|
||||
| cut %merge<merge> {
|
||||
USE ($$);
|
||||
merged_value = 1;
|
||||
}
|
||||
;
|
||||
|
||||
cut: { YYACCEPT; } ;
|
||||
|
||||
%%
|
||||
|
||||
static int
|
||||
@@ -988,24 +1029,38 @@ yyerror (char const *msg)
|
||||
static int
|
||||
yylex (void)
|
||||
{
|
||||
return 0;
|
||||
static int const input[] = { PARENT_RHS_AFTER, 0 };
|
||||
static const int *inputp = input;
|
||||
if (*inputp == PARENT_RHS_AFTER)
|
||||
parent_rhs_after_value = 1;
|
||||
return *inputp++;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
int exit_status = yyparse ();
|
||||
if (has_value)
|
||||
if (parent_rhs_before_value)
|
||||
{
|
||||
fprintf (stderr, "Destructor not called.\n");
|
||||
return 1;
|
||||
fprintf (stderr, "`parent_rhs_before' destructor not called.\n");
|
||||
exit_status = 1;
|
||||
}
|
||||
if (merged_value)
|
||||
{
|
||||
fprintf (stderr, "`merged' destructor not called.\n");
|
||||
exit_status = 1;
|
||||
}
|
||||
if (parent_rhs_after_value)
|
||||
{
|
||||
fprintf (stderr, "`PARENT_RHS_AFTER' destructor not called.\n");
|
||||
exit_status = 1;
|
||||
}
|
||||
return exit_status;
|
||||
}
|
||||
]])
|
||||
|
||||
AT_CHECK([[bison -t -o glr-regr12.c glr-regr12.y]], 0, [],
|
||||
[glr-regr12.y: conflicts: 1 reduce/reduce
|
||||
[glr-regr12.y: conflicts: 1 shift/reduce, 1 reduce/reduce
|
||||
])
|
||||
AT_COMPILE([glr-regr12])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user