[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 3/5] tests: check $$'s destruction with variant, YYERROR, and no
From: |
Akim Demaille |
Subject: |
[PATCH 3/5] tests: check $$'s destruction with variant, YYERROR, and no error recovery |
Date: |
Fri, 15 Nov 2013 10:19:06 +0100 |
When variant are enabled, the yylhs variable (the left-hand side of
the rule being reduced, i.e. $$ and @$) is explicitly destroyed when
YYERROR is called. This is because before running the user code, $$
is initialized, so that the user can properly use it.
However, when quitting yyparse, yylhs is also reclaimed by the C++
compiler: the variable goes out of scope.
This was not detected by the test suite because (i) the Object tracker
was too weak, and (ii) the problem does not show when there is error
recovery.
Reported by Paolo Simone Gasparello.
<http://lists.gnu.org/archive/html/bug-bison/2013-10/msg00003.html>
* tests/c++.at (Exception safety): Improve the objects logger to make
sure that we never destroy twice an object.
Also track copy-constructors.
Use a set instead of a list.
Display the logs before running the function body, this is more
useful in case of failure.
Generalize to track with and without error recovery.
---
THANKS | 1 +
tests/c++.at | 58 +++++++++++++++++++++++++++++++++++++---------------------
2 files changed, 38 insertions(+), 21 deletions(-)
diff --git a/THANKS b/THANKS
index 9b7a896..ebadb44 100644
--- a/THANKS
+++ b/THANKS
@@ -96,6 +96,7 @@ Odd Arild Olsen address@hidden
Oleg Smolsky address@hidden
Oleksii Taran address@hidden
Paolo Bonzini address@hidden
+Paolo Simone Gasparello address@hidden
Pascal Bart address@hidden
Paul Eggert address@hidden
Paul Hilfinger address@hidden
diff --git a/tests/c++.at b/tests/c++.at
index 14a001a..355e624 100644
--- a/tests/c++.at
+++ b/tests/c++.at
@@ -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])
--
1.8.4.2
- [PATCH 0/5] {maint} fix variants when YYERROR is used, Akim Demaille, 2013/11/15
- [PATCH 3/5] tests: check $$'s destruction with variant, YYERROR, and no error recovery,
Akim Demaille <=
- [PATCH 4/5] lalr1.cc: fix the support of YYERROR with variants, Akim Demaille, 2013/11/15
- [PATCH 1/5] skeletons: use better names when computing a "goto", Akim Demaille, 2013/11/15
- [PATCH 5/5] lalr1.cc: formatting changes, Akim Demaille, 2013/11/15
- [PATCH 2/5] tests: simplify useless obfuscation, Akim Demaille, 2013/11/15