From: Akim Demaille Date: Thu, 20 Sep 2012 09:43:19 +0000 (+0200) Subject: lalr1.cc: check exception safety. X-Git-Tag: v2.6.90~87 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cff926615f1ae4441f60ebeb2992a2d221da910f;p=platform%2Fupstream%2Fbison.git lalr1.cc: check exception safety. * tests/c++.at (Exception safety): New. --- diff --git a/tests/c++.at b/tests/c++.at index c44a2a5..304a72d 100644 --- a/tests/c++.at +++ b/tests/c++.at @@ -181,3 +181,144 @@ AT_CHECK_NAMESPACE([[foo[3]::bar::baz]], [[-]]) AT_CHECK_NAMESPACE([[foo::bar,baz]], [[-]]) AT_CHECK_NAMESPACE([[foo::bar::(baz]], [[-]]) AT_CLEANUP + + +## ------------------ ## +## Exception safety. ## +## ------------------ ## + +AT_SETUP([[Exception safety]]) + +AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"]) + +AT_DATA_GRAMMAR([[input.yy]], +[[%skeleton "lalr1.cc" +%defines // FIXME: Mandated in 2.6. +%debug + +%code requires +{ + #include // size_t and getenv. + #include + + int debug = 0; + + struct Object + { + static size_t counter; + + Object () + { + ++counter; + if (debug) + std::cerr << "Object::Object() => counter == " << counter << std::endl; + } + + ~Object () + { + --counter; + if (debug) + std::cerr << "Object::~Object() => counter == " << counter << std::endl; + } + }; +} + +%code +{ + #include + #include + int yylex (yy::parser::semantic_type *); + size_t Object::counter = 0; + static char const *input; +} + +%union +{ + Object* obj; +} + +%destructor { delete $$; } ; +%printer { yyo << "counter == " << $$->counter; } ; + +%token 'a' 's' +%type list item + +%% + +start: list { delete $1; }; + +list: + item { $$ = $1; } +| item list { $$ = $1; delete $2; } /* Right recursion to load the stack. */ +; + +item: + 'a' + { + std::swap ($$, $1); + } +| 's' + { + std::swap ($$, $1); + throw std::runtime_error ("invalid expression"); + } + +%% + +int +yylex (yy::parser::semantic_type *lvalp) +{ + // 'l': lexical exception, 's': syntactic exception. + switch (int res = *input++) + { + case 'l': + throw std::runtime_error ("invalid character"); + default: + lvalp->obj = new Object; + // Fall through. + case 0: + return res; + } +} + +]AT_YYERROR_DEFINE[ + +int +main (int argc, const char *argv[]) +{ + assert (argc == 2); + input = argv[1]; + yy::parser parser; + debug = !!getenv ("YYDEBUG"); + parser.set_debug_level (debug); + int res = 2; + try + { + res = parser.parse (); + } + catch (const std::exception& e) + { + std::cerr << "exception caught: " << e.what () << std::endl; + } + catch (...) + { + std::cerr << "unknown exception caught" << std::endl; + } + assert (Object::counter == 0); + return res; +} +]]) +AT_BISON_CHECK([[-o input.cc input.yy]]) +AT_COMPILE_CXX([[input]]) + +AT_PARSER_CHECK([[./input aaaas]], [[2]], [[]], +[[exception caught: invalid expression +]]) + +AT_PARSER_CHECK([[./input aaaal]], [[2]], [[]], +[[exception caught: invalid character +]]) + +AT_BISON_OPTION_POPDEFS + +AT_CLEANUP