]> git.saurik.com Git - bison.git/commitdiff
tests: check that using variants is exception safe
authorAkim Demaille <akim@lrde.epita.fr>
Mon, 28 Jan 2013 15:05:09 +0000 (16:05 +0100)
committerAkim Demaille <akim@lrde.epita.fr>
Mon, 28 Jan 2013 15:07:51 +0000 (16:07 +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
tests/local.at

index 21f567f91f863dcc7241aae321bfacd377d42545..b72954a2332dca43726c780e850188adf093daf1 100644 (file)
@@ -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  ##
index 103887d0350973b52adf5a8a3b75b175cc657cec..74eea7e621eb6a55214d2661208277699dee6db8 100644 (file)
@@ -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])