Avoid memory leaks by not invoking longjmp in yyreportAmbiguity.

* tests/glr-regression.at (Leaked semantic values when reporting
ambiguity): New test case.
* data/glr.c (yyreportAmbiguity): Invoke yyyerror directly and return
yyabort rather than invoking yyFail, which invokes longjmp.  Remove the
now unnecessary yystackp parameter.
(yyresolveValue): Return yyreportAmbiguity's result.  Now the necessary
destructors can be called.

* tests/glr-regression.at: Don't invoke bison with `-t' unnecessarily
in existing testcases.
This commit is contained in:
Joel E. Denny
2006-03-02 06:18:09 +00:00
parent 520181ab91
commit 35ee866a32
3 changed files with 120 additions and 15 deletions

View File

@@ -1,10 +1,24 @@
2006-03-02 Joel E. Denny <jdenny@ces.clemson.edu>
Avoid memory leaks by not invoking longjmp in yyreportAmbiguity.
* tests/glr-regression.at (Leaked semantic values when reporting
ambiguity): New test case.
* data/glr.c (yyreportAmbiguity): Invoke yyyerror directly and return
yyabort rather than invoking yyFail, which invokes longjmp. Remove the
now unnecessary yystackp parameter.
(yyresolveValue): Return yyreportAmbiguity's result. Now the necessary
destructors can be called.
* tests/glr-regression.at: Don't invoke bison with `-t' unnecessarily
in existing testcases.
2006-03-02 Joel E. Denny <jdenny@ces.clemson.edu>
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
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

View File

@@ -1783,12 +1783,9 @@ yyreportTree (yySemanticOption* yyx, int yyindent)
}
#endif
static void yyreportAmbiguity (yySemanticOption* yyx0, yySemanticOption* yyx1,
yyGLRStack* yystackp]b4_pure_formals[)
__attribute__ ((__noreturn__));
/*ARGSUSED*/ static void
yyreportAmbiguity (yySemanticOption* yyx0, yySemanticOption* yyx1,
yyGLRStack* yystackp]b4_pure_formals[)
/*ARGSUSED*/ static YYRESULTTAG
yyreportAmbiguity (yySemanticOption* yyx0,
yySemanticOption* yyx1]b4_pure_formals[)
{
YYUSE (yyx0);
YYUSE (yyx1);
@@ -1801,7 +1798,9 @@ yyreportAmbiguity (yySemanticOption* yyx0, yySemanticOption* yyx1,
yyreportTree (yyx1, 2);
YYFPRINTF (stderr, "\n");
#endif
yyFail (yystackp][]b4_pure_args[, YY_("syntax is ambiguous"));
yyerror (]b4_yyerror_args[YY_("syntax is ambiguous"));
return yyabort;
}
@@ -1838,7 +1837,7 @@ yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp]b4_user_formals[)
switch (yypreference (yybest, yyp))
{
case 0:
yyreportAmbiguity (yybest, yyp, yystackp]b4_pure_args[);
return yyreportAmbiguity (yybest, yyp]b4_pure_args[);
break;
case 1:
yymerge = yytrue;

View File

@@ -864,7 +864,7 @@ main (void)
}
]])
AT_CHECK([[bison -t -o glr-regr10.c glr-regr10.y]], 0, [],
AT_CHECK([[bison -o glr-regr10.c glr-regr10.y]], 0, [],
[glr-regr10.y: conflicts: 1 reduce/reduce
])
AT_COMPILE([glr-regr10])
@@ -930,7 +930,7 @@ main (void)
}
]])
AT_CHECK([[bison -t -o glr-regr11.c glr-regr11.y]], 0, [],
AT_CHECK([[bison -o glr-regr11.c glr-regr11.y]], 0, [],
[glr-regr11.y: conflicts: 1 reduce/reduce
])
AT_COMPILE([glr-regr11])
@@ -1059,7 +1059,7 @@ main (void)
}
]])
AT_CHECK([[bison -t -o glr-regr12.c glr-regr12.y]], 0, [],
AT_CHECK([[bison -o glr-regr12.c glr-regr12.y]], 0, [],
[glr-regr12.y: conflicts: 1 shift/reduce, 1 reduce/reduce
])
AT_COMPILE([glr-regr12])
@@ -1186,7 +1186,7 @@ main (void)
}
]])
AT_CHECK([[bison -t -o glr-regr13.c glr-regr13.y]], 0, [], [])
AT_CHECK([[bison -o glr-regr13.c glr-regr13.y]], 0, [], [])
AT_COMPILE([glr-regr13])
AT_CHECK([[./glr-regr13]], 0,
@@ -1399,7 +1399,7 @@ main (void)
}
]])
AT_CHECK([[bison -t -o glr-regr14.c glr-regr14.y]], 0, [],
AT_CHECK([[bison -o glr-regr14.c glr-regr14.y]], 0, [],
[glr-regr14.y: conflicts: 3 reduce/reduce
])
AT_COMPILE([glr-regr14])
@@ -1420,3 +1420,95 @@ start <- merge 'c' stack_explosion:
], [])
AT_CLEANUP
## ------------------------------------------------------------------------- ##
## Leaked semantic values when reporting ambiguity. ##
## ------------------------------------------------------------------------- ##
AT_SETUP([Leaked semantic values when reporting ambiguity])
AT_DATA_GRAMMAR([glr-regr15.y],
[[
%glr-parser
%union { int dummy; }
%type <dummy> parent_rhs_before
%destructor { parent_rhs_before_value = 0; } parent_rhs_before
%{
# include <stdlib.h>
static void yyerror (char const *);
static int yylex (void);
static int parent_rhs_before_value = 0;
# define USE(val)
%}
%%
start:
alt1 %dprec 1
| alt2 %dprec 2
;
/* This stack must be merged into the other stacks *last* (added at the
beginning of the semantic options list) so that yyparse will choose to clean
it up rather than the tree for which some semantic actions have been
performed. Thus, if yyreportAmbiguity longjmp's to yyparse, the values from
those other trees are not cleaned up. */
alt1: ;
alt2:
parent_rhs_before ambiguity {
USE ($1);
parent_rhs_before_value = 0;
}
;
parent_rhs_before:
{
USE ($$);
parent_rhs_before_value = 1;
}
;
ambiguity: ambiguity1 | ambiguity2 ;
ambiguity1: ;
ambiguity2: ;
%%
static void
yyerror (char const *msg)
{
fprintf (stderr, "%s\n", msg);
}
static int
yylex (void)
{
return 0;
}
int
main (void)
{
int exit_status = yyparse () != 1;
if (parent_rhs_before_value)
{
fprintf (stderr, "`parent_rhs_before' destructor not called.\n");
exit_status = 1;
}
return exit_status;
}
]])
AT_CHECK([[bison -o glr-regr15.c glr-regr15.y]], 0, [],
[glr-regr15.y: conflicts: 2 reduce/reduce
])
AT_COMPILE([glr-regr15])
AT_CHECK([[./glr-regr15]], 0, [],
[syntax is ambiguous
])
AT_CLEANUP