[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 6/6] tests: check that using variants is exception safe
From: |
Akim Demaille |
Subject: |
[PATCH 6/6] tests: check that using variants is exception safe |
Date: |
Mon, 28 Jan 2013 16:34:17 +0100 |
* tests/local.at: (Slightly) improve the regexp by escaping '.'
when it denotes a point.
(AT_VARIANT_IF): New.
* tests/c++.at (Exception Safety): Run it for variants too.
---
tests/c++.at | 85 +++++++++++++++++++++++++++++++++++++++-------------------
tests/local.at | 11 +++++---
2 files changed, 64 insertions(+), 32 deletions(-)
diff --git a/tests/c++.at b/tests/c++.at
index 21f567f..b72954a 100644
--- a/tests/c++.at
+++ b/tests/c++.at
@@ -589,15 +589,19 @@ AT_CLEANUP
## Exception safety. ##
## ------------------ ##
-AT_SETUP([[Exception safety]])
+# AT_TEST([BISON-DIRECTIVES])
+# ---------------------------
+# Check that no object is leaked when exceptions are thrown.
+m4_pushdef([AT_TEST],
+[AT_SETUP([[Exception safety $1]])
-AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc"])
+AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" $1])
AT_DATA_GRAMMAR([[input.yy]],
[[%skeleton "lalr1.cc"
%debug
%error-verbose
-
+$1
%code requires
{
#include <cassert>
@@ -648,6 +652,13 @@ AT_DATA_GRAMMAR([[input.yy]],
log (this, "Object::Object");
}
+ Object ()
+ : val ('?')
+ {
+ instances.push_back(this);
+ log (this, "Object::Object");
+ }
+
~Object ()
{
instances.remove(this);
@@ -666,17 +677,21 @@ AT_DATA_GRAMMAR([[input.yy]],
static char const *input;
}
-%union
+]AT_VARIANT_IF([[
+%printer
{
- Object *obj;
-}
+ yyo << &$$ << " '" << $$.val << '\'';
+ if ($$.val == 'p')
+ throw std::runtime_error ("printer");
+} <Object>;
-%initial-action
+%token <Object> 'a' 'E' 'e' 'p' 'R' 's' 'T'
+%type <Object> list item
+]], [[
+%union
{
- if (strchr (input, 'i'))
- throw std::runtime_error ("initial-action");
+ Object *obj;
}
-
%destructor { delete $$; } <obj>;
%printer
{
@@ -687,27 +702,35 @@ AT_DATA_GRAMMAR([[input.yy]],
%token <obj> 'a' 'E' 'e' 'p' 'R' 's' 'T'
%type <obj> list item
+]])[
+
+%initial-action
+{
+ if (strchr (input, 'i'))
+ throw std::runtime_error ("initial-action");
+}
%%
-start: list { delete $1; };
+start: list {]AT_VARIANT_IF([], [ delete $][1]; )[};
list:
- item { $$ = $1; }
-| item list { $$ = $1; delete $2; } // Right recursion to load the stack.
+ item { $][$ = $][1; }
+ // Right recursion to load the stack.
+| item list { $][$ = $][1; ]AT_VARIANT_IF([], [delete $][2]; )[}
;
item:
- 'a' { $$ = $1; }
-| 'e' { YYUSE ($$); YYUSE($1); error ("syntax error"); }
+ 'a' { $$][ = $][1; }
+| 'e' { YYUSE ($][$); YYUSE($][1); error ("syntax error"); }
// Not just 'E', otherwise we reduce when 'E' is the lookahead, and
// then the stack is emptied, defeating the point of the test.
-| 'E' 'a' { YYUSE($1); $$ = $2; }
-| 'R' { $$ = YY_NULL; delete $1; YYERROR; }
-| 'p' { $$ = $1; }
-| 's' { $$ = $1; throw std::runtime_error ("reduction"); }
-| 'T' { $$ = YY_NULL; delete $1; YYABORT; }
-| error { $$ = YY_NULL; yyerrok; }
+| 'E' 'a' { YYUSE($][1); $][$ = $][2; }
+| 'R' { $][$ = YY_NULL; ]AT_VARIANT_IF([], [delete $][1]; )[YYERROR; }
+| 'p' { $][$ = $][1; }
+| 's' { $][$ = $][1; throw std::runtime_error ("reduction"); }
+| 'T' { $][$ = YY_NULL; ]AT_VARIANT_IF([], [delete $][1]; )[YYABORT; }
+| error { $][$ = YY_NULL; yyerrok; }
;
%%
@@ -724,13 +747,13 @@ yylex (yy::parser::semantic_type *lvalp)
// 'T': call YYABORT in the action
switch (int res = *input++)
{
- case 'l':
- throw std::runtime_error ("yylex");
- default:
- lvalp->obj = new Object (res);
- // Fall through.
- case 0:
- return res;
+ case 'l':
+ throw std::runtime_error ("yylex");
+ default:
+ lvalp]AT_VARIANT_IF([->build (res)], [->obj = new Object (res)])[;
+ // Fall through.
+ case 0:
+ return res;
}
}
@@ -815,6 +838,12 @@ AT_PARSER_CHECK([[./input aaaaR]], [[0]])
AT_BISON_OPTION_POPDEFS
AT_CLEANUP
+])
+
+AT_TEST
+AT_TEST([%define api.value.type variant])
+
+m4_popdef([AT_TEST])
## ------------------------------------ ##
## C++ GLR parser identifier shadowing ##
diff --git a/tests/local.at b/tests/local.at
index 103887d..74eea7e 100644
--- a/tests/local.at
+++ b/tests/local.at
@@ -186,10 +186,12 @@ m4_pushdef([AT_NAME_PREFIX],
[m4_bregexp([$3], [\(%define
api\.\(namespace\|prefix\)\|%name-prefix\) "\([^""]*\)"], [\3])],
[yy])])
m4_pushdef([AT_TOKEN_CTOR_IF],
-[m4_bmatch([$3], [%define api.token.constructor], [$1], [$2])])
+[m4_bmatch([$3], [%define api\.token\.constructor], [$1], [$2])])
m4_pushdef([AT_TOKEN_PREFIX],
-[m4_bmatch([$3], [%define api.token.prefix ".*"],
- [m4_bregexp([$3], [%define api.token.prefix "\(.*\)"], [\1])])])
+[m4_bmatch([$3], [%define api\.token\.prefix ".*"],
+ [m4_bregexp([$3], [%define api\.token\.prefix "\(.*\)"], [\1])])])
+m4_pushdef([AT_VARIANT_IF],
+[m4_bmatch([$3], [%define api\.value\.type "?variant"?], [$1], [$2])])
m4_pushdef([AT_API_prefix],
[m4_bmatch([$3], [%define api\.prefix ".*"],
[m4_bregexp([$3], [%define api\.prefix "\([^""]*\)"], [\1])],
@@ -203,7 +205,7 @@ m4_pushdef([AT_API_PREFIX],
m4_pushdef([AT_YYERROR_ARG_LOC_IF],
[AT_LOCATION_IF([AT_PURE_IF([m4_bmatch([$3],
m4_quote(m4_join([\|],
- [%define api.pure
"?full"?],
+ [%define api\.pure
"?full"?],
[%glr-parser],
[%parse-param],
[%skeleton
"?glr.c"?])),
@@ -288,6 +290,7 @@ m4_popdef([AT_YYERROR_SEES_LOC_IF])
m4_popdef([AT_YYERROR_ARG_LOC_IF])
m4_popdef([AT_API_PREFIX])
m4_popdef([AT_API_prefix])
+m4_popdef([AT_VARIANT_IF])
m4_popdef([AT_TOKEN_PREFIX])
m4_popdef([AT_TOKEN_CTOR_IF])
m4_popdef([AT_NAME_PREFIX])
--
1.8.1.1
- [PATCH 0/6] {master} c++: variant overhaul, Akim Demaille, 2013/01/28
- [PATCH 3/6] tests: enable support for --debug, Akim Demaille, 2013/01/28
- [PATCH 2/6] c++: revamp the support for variants, Akim Demaille, 2013/01/28
- [PATCH 4/6] c++: remove now-useless operators, Akim Demaille, 2013/01/28
- [PATCH 5/6] tests: remove useless %defines, Akim Demaille, 2013/01/28
- [PATCH 6/6] tests: check that using variants is exception safe,
Akim Demaille <=
- [PATCH 1/6] c++: formatting and comment changes, Akim Demaille, 2013/01/28