mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 04:13:03 +00:00
lalr1.cc: check (and fix) %printer exception safety
* tests/c++.at (Exception safety): Let the parser support the --debug option. On 'p', throw an exception from the %printer. * data/lalr1.cc (yyparse): Do not display the values we discard, as it uses %printer, which might have thrown the exception.
This commit is contained in:
@@ -227,6 +227,7 @@ b4_user_stype
|
||||
|
||||
/// \brief Reclaim the memory associated to a symbol.
|
||||
/// \param yymsg Why this token is reclaimed.
|
||||
/// If null, do not display the symbol, just free it.
|
||||
/// \param yytype The symbol type.
|
||||
/// \param yyvaluep Its semantic value.
|
||||
/// \param yylocationp Its location.
|
||||
@@ -446,7 +447,8 @@ do { \
|
||||
YYUSE (yymsg);
|
||||
YYUSE (yyvaluep);
|
||||
|
||||
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
|
||||
if (yymsg)
|
||||
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
|
||||
|
||||
switch (yytype)
|
||||
{
|
||||
@@ -841,20 +843,22 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
YYCDEBUG << "Exception caught" << std::endl;
|
||||
YYCDEBUG << "Exception caught: cleaning lookahead and stack"
|
||||
<< std::endl;
|
||||
// Do not try to display the values of the reclaimed symbols,
|
||||
// as their printer might throw an exception.
|
||||
if (yychar != yyempty_)
|
||||
{
|
||||
/* Make sure we have latest lookahead translation. See
|
||||
comments at user semantic actions for why this is
|
||||
necessary. */
|
||||
yytoken = yytranslate_ (yychar);
|
||||
yydestruct_ ("Cleanup: discarding lookahead", yytoken, &yylval,
|
||||
&yylloc);
|
||||
yydestruct_ (YY_NULL, yytoken, &yylval, &yylloc);
|
||||
}
|
||||
|
||||
while (1 < yystate_stack_.height ())
|
||||
{
|
||||
yydestruct_ ("Cleanup: popping",
|
||||
yydestruct_ (YY_NULL,
|
||||
yystos_[yystate_stack_[0]],
|
||||
&yysemantic_stack_[0],
|
||||
&yylocation_stack_[0]);
|
||||
|
||||
47
tests/c++.at
47
tests/c++.at
@@ -203,11 +203,14 @@ AT_DATA_GRAMMAR([[input.yy]],
|
||||
|
||||
int debug = 0;
|
||||
|
||||
/// A class that counts its number of instances.
|
||||
struct Object
|
||||
{
|
||||
static size_t counter;
|
||||
int val;
|
||||
|
||||
Object ()
|
||||
Object (int v)
|
||||
: val (v)
|
||||
{
|
||||
++counter;
|
||||
if (debug)
|
||||
@@ -245,9 +248,14 @@ AT_DATA_GRAMMAR([[input.yy]],
|
||||
}
|
||||
|
||||
%destructor { delete $$; } <obj>;
|
||||
%printer { yyo << "counter == " << $$->counter; } <obj>;
|
||||
%printer
|
||||
{
|
||||
yyo << "counter == " << $$->counter;
|
||||
if ($$->val == 'p')
|
||||
throw std::runtime_error ("printer");
|
||||
} <obj>;
|
||||
|
||||
%token <obj> 'a' 's'
|
||||
%token <obj> 'a' 'p' 's'
|
||||
%type <obj> list item
|
||||
|
||||
%%
|
||||
@@ -256,14 +264,12 @@ start: list { delete $1; };
|
||||
|
||||
list:
|
||||
item { $$ = $1; }
|
||||
| item list { $$ = $1; delete $2; } /* Right recursion to load the stack. */
|
||||
| item list { $$ = $1; delete $2; } // Right recursion to load the stack.
|
||||
;
|
||||
|
||||
item:
|
||||
'a'
|
||||
{
|
||||
std::swap ($$, $1);
|
||||
}
|
||||
'a' { std::swap ($$, $1); }
|
||||
| 'p' { std::swap ($$, $1); }
|
||||
| 's'
|
||||
{
|
||||
std::swap ($$, $1);
|
||||
@@ -284,7 +290,7 @@ yylex (yy::parser::semantic_type *lvalp)
|
||||
case 'l':
|
||||
throw std::runtime_error ("yylex");
|
||||
default:
|
||||
lvalp->obj = new Object;
|
||||
lvalp->obj = new Object (res);
|
||||
// Fall through.
|
||||
case 0:
|
||||
return res;
|
||||
@@ -296,10 +302,22 @@ yylex (yy::parser::semantic_type *lvalp)
|
||||
int
|
||||
main (int argc, const char *argv[])
|
||||
{
|
||||
assert (argc == 2);
|
||||
input = argv[1];
|
||||
switch (argc)
|
||||
{
|
||||
case 2:
|
||||
input = argv[1];
|
||||
break;
|
||||
case 3:
|
||||
assert (!strcmp (argv[1], "--debug"));
|
||||
debug = 1;
|
||||
input = argv[2];
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
yy::parser parser;
|
||||
debug = !!getenv ("YYDEBUG");
|
||||
debug |= !!getenv ("YYDEBUG");
|
||||
parser.set_debug_level (debug);
|
||||
int res = 2;
|
||||
try
|
||||
@@ -333,6 +351,11 @@ AT_PARSER_CHECK([[./input i]], [[2]], [[]],
|
||||
[[exception caught: initial-action
|
||||
]])
|
||||
|
||||
AT_PARSER_CHECK([[./input aaaap]])
|
||||
|
||||
AT_PARSER_CHECK([[./input --debug aaaap]], [[2]], [[]], [[stderr]])
|
||||
AT_PARSER_CHECK([[grep '^exception caught: printer$' stderr]], [], [ignore])
|
||||
|
||||
AT_BISON_OPTION_POPDEFS
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
Reference in New Issue
Block a user