lalr1.cc: check (and fix) %initial-action exception safety

* data/lalr1.cc: Check size > 1, rather than size != 1, when cleaning
the stack, as at the beginning, size is 0.
* tests/c++.at (Exception safety): Check exception safety in
%initial-action.
This commit is contained in:
Akim Demaille
2012-09-25 11:17:55 +02:00
parent 7e1fabbeae
commit a26424642b
2 changed files with 21 additions and 7 deletions

View File

@@ -828,7 +828,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
/* Do not reclaim the symbols of the rule which action triggered /* Do not reclaim the symbols of the rule which action triggered
this YYABORT or YYACCEPT. */ this YYABORT or YYACCEPT. */
yypop_ (yylen); yypop_ (yylen);
while (yystate_stack_.height () != 1) while (1 < yystate_stack_.height ())
{ {
yydestruct_ ("Cleanup: popping", yydestruct_ ("Cleanup: popping",
yystos_[yystate_stack_[0]], yystos_[yystate_stack_[0]],
@@ -852,7 +852,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))[;
&yylloc); &yylloc);
} }
while (yystate_stack_.height () != 1) while (1 < yystate_stack_.height ())
{ {
yydestruct_ ("Cleanup: popping", yydestruct_ ("Cleanup: popping",
yystos_[yystate_stack_[0]], yystos_[yystate_stack_[0]],

View File

@@ -226,6 +226,7 @@ AT_DATA_GRAMMAR([[input.yy]],
%code %code
{ {
#include <cassert> #include <cassert>
#include <cstring> // strchr
#include <stdexcept> #include <stdexcept>
int yylex (yy::parser::semantic_type *); int yylex (yy::parser::semantic_type *);
size_t Object::counter = 0; size_t Object::counter = 0;
@@ -237,6 +238,12 @@ AT_DATA_GRAMMAR([[input.yy]],
Object* obj; Object* obj;
} }
%initial-action
{
if (strchr (input, 'i'))
throw std::runtime_error ("initial-action");
}
%destructor { delete $$; } <obj>; %destructor { delete $$; } <obj>;
%printer { yyo << "counter == " << $$->counter; } <obj>; %printer { yyo << "counter == " << $$->counter; } <obj>;
@@ -260,7 +267,7 @@ item:
| 's' | 's'
{ {
std::swap ($$, $1); std::swap ($$, $1);
throw std::runtime_error ("invalid expression"); throw std::runtime_error ("reduction");
} }
%% %%
@@ -268,11 +275,14 @@ item:
int int
yylex (yy::parser::semantic_type *lvalp) yylex (yy::parser::semantic_type *lvalp)
{ {
// 'l': lexical exception, 's': syntactic exception. // 'a': no error.
// 'i': initial action throws.
// 'l': yylex throws.
// 's': reduction throws.
switch (int res = *input++) switch (int res = *input++)
{ {
case 'l': case 'l':
throw std::runtime_error ("invalid character"); throw std::runtime_error ("yylex");
default: default:
lvalp->obj = new Object; lvalp->obj = new Object;
// Fall through. // Fall through.
@@ -312,11 +322,15 @@ AT_BISON_CHECK([[-o input.cc input.yy]])
AT_COMPILE_CXX([[input]]) AT_COMPILE_CXX([[input]])
AT_PARSER_CHECK([[./input aaaas]], [[2]], [[]], AT_PARSER_CHECK([[./input aaaas]], [[2]], [[]],
[[exception caught: invalid expression [[exception caught: reduction
]]) ]])
AT_PARSER_CHECK([[./input aaaal]], [[2]], [[]], AT_PARSER_CHECK([[./input aaaal]], [[2]], [[]],
[[exception caught: invalid character [[exception caught: yylex
]])
AT_PARSER_CHECK([[./input i]], [[2]], [[]],
[[exception caught: initial-action
]]) ]])
AT_BISON_OPTION_POPDEFS AT_BISON_OPTION_POPDEFS