]> git.saurik.com Git - bison.git/blobdiff - tests/c++.at
tests: check $$'s destruction with variant, YYERROR, and no error recovery
[bison.git] / tests / c++.at
index 14a001a4dd3ed76efeacfe34ae5d31fa5280c09e..355e6247fbbfe37ab83f858dcb7c047f28e1afed 100644 (file)
@@ -649,14 +649,18 @@ AT_CLEANUP
 ## Exception safety.  ##
 ## ------------------ ##
 
-# AT_TEST([BISON-DIRECTIVES])
-# ---------------------------
+# AT_TEST([BISON-DIRECTIVES = ''], [WITH-RECOVERY = "with"])
+# ----------------------------------------------------------
 # Check that no object is leaked when exceptions are thrown.
+# WITH-RECOVERY = "with" or "without".
 m4_pushdef([AT_TEST],
-[AT_SETUP([[Exception safety $1]])
+[AT_SETUP([[Exception safety $2 error recovery $1]])
 
 AT_SKIP_IF_EXCEPTION_SUPPORT_IS_POOR
 
+m4_if([$1], [], [],
+      [m4_if([$2], [without], [AT_XFAIL_IF([true])])])
+
 AT_BISON_OPTION_PUSHDEFS([%skeleton "lalr1.cc" $1])
 
 AT_DATA_GRAMMAR([[input.yy]],
@@ -669,43 +673,53 @@ $1
   #include <cassert>
   #include <cstdlib> // size_t and getenv.
   #include <iostream>
-  #include <list>
+  #include <set>
 
   bool debug = false;
 
-  /// A class that counts its number of instances.
+  /// A class that tracks its instances.
   struct Object
   {
     char val;
 
-    Object (char v)
-      : val (v)
+    Object ()
+      : val ('?')
     {
-      Object::instances.push_back(this);
       log (this, "Object::Object");
+      Object::instances.insert (this);
     }
 
-    Object ()
-      : val ('?')
+    Object (const Object& that)
+      : val (that.val)
     {
-      Object::instances.push_back(this);
       log (this, "Object::Object");
+      Object::instances.insert (this);
     }
 
-    Object& operator= (char v)
+    Object (char v)
+      : val (v)
     {
-      val = v;
-      return *this;
+      log (this, "Object::Object");
+      Object::instances.insert (this);
     }
 
     ~Object ()
     {
-      Object::instances.remove (this);
       log (this, "Object::~Object");
+      objects::const_iterator i = instances.find (this);
+      // Make sure this object is alive.
+      assert (i != instances.end ());
+      Object::instances.erase (i);
+    }
+
+    Object& operator= (char v)
+    {
+      val = v;
+      return *this;
     }
 
     // Static part.
-    typedef std::list<const Object*> objects;
+    typedef std::set<const Object*> objects;
     static objects instances;
 
     static bool
@@ -800,7 +814,8 @@ item:
 | 'p'     { $$ = $][1; }
 | 's'     { $$ = $][1; throw std::runtime_error ("reduction"); }
 | 'T'     { ]AT_VARIANT_IF([], [$$ = YY_NULLPTR; delete $][1]; )[YYABORT; }
-| error   { ]AT_VARIANT_IF([], [$][$ = YY_NULLPTR; ])[yyerrok; }
+]m4_if([$2], [with],
+[[| error   { $$ = ]AT_VARIANT_IF([], [new ])[Object ('R'); yyerrok; }]])[
 ;
 %%
 
@@ -903,16 +918,17 @@ AT_PARSER_CHECK([[./input aaaaE]], [[2]], [[]],
 
 AT_PARSER_CHECK([[./input aaaaT]], [[1]])
 
-# There is error-recovery, so exit success.
-AT_PARSER_CHECK([[./input aaaaR]], [[0]])
+AT_PARSER_CHECK([[./input aaaaR]], [m4_if([$2], [with], [0], [1])])
 
 AT_BISON_OPTION_POPDEFS
 
 AT_CLEANUP
 ])
 
-AT_TEST
-AT_TEST([%define api.value.type variant])
+AT_TEST([], [with])
+AT_TEST([], [without])
+AT_TEST([%define api.value.type variant], [with])
+AT_TEST([%define api.value.type variant], [without])
 
 m4_popdef([AT_TEST])