[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 4/9] lalr1.cc: check exception safety.
From: |
Akim Demaille |
Subject: |
[PATCH 4/9] lalr1.cc: check exception safety. |
Date: |
Tue, 2 Oct 2012 19:11:09 +0200 |
* tests/c++.at (Exception safety): New.
---
tests/c++.at | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 141 insertions(+)
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 <cstdlib> // size_t and getenv.
+ #include <iostream>
+
+ 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 <cassert>
+ #include <stdexcept>
+ int yylex (yy::parser::semantic_type *);
+ size_t Object::counter = 0;
+ static char const *input;
+}
+
+%union
+{
+ Object* obj;
+}
+
+%destructor { delete $$; } <obj>;
+%printer { yyo << "counter == " << $$->counter; } <obj>;
+
+%token <obj> 'a' 's'
+%type <obj> 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
--
1.7.12.2
- [PATCH 0/9] {maint} lalr1.cc: exception safety, Akim Demaille, 2012/10/02
- [PATCH 4/9] lalr1.cc: check exception safety.,
Akim Demaille <=
- [PATCH 7/9] lalr1.cc: check (and fix) %printer exception safety, Akim Demaille, 2012/10/02
- [PATCH 6/9] lalr1.cc: check (and fix) %initial-action exception safety, Akim Demaille, 2012/10/02
- [PATCH 1/9] tests: minor improvements, Akim Demaille, 2012/10/02
- [PATCH 8/9] lalr1.cc: check exception safety of yyerror, Akim Demaille, 2012/10/02
- [PATCH 5/9] lalr1.cc: fix exception safety, Akim Demaille, 2012/10/02
- [PATCH 2/9] lalr1.cc: don't leave macros define to nothing, Akim Demaille, 2012/10/02
- [PATCH 3/9] lalr1.cc: indentation fixes., Akim Demaille, 2012/10/02
- [PATCH 9/9] lalr1.cc: document exception safety, Akim Demaille, 2012/10/02
- Re: [PATCH 0/9] {maint} lalr1.cc: exception safety, Akim Demaille, 2012/10/03