]> git.saurik.com Git - bison.git/commitdiff
variant: more assertions
authorAkim Demaille <akim@lrde.epita.fr>
Wed, 19 Dec 2012 09:09:07 +0000 (10:09 +0100)
committerAkim Demaille <akim@lrde.epita.fr>
Wed, 19 Dec 2012 10:30:22 +0000 (11:30 +0100)
Equip variants with more checking code.  Provide a means to request
includes.

* data/variant.hh (b4_variant_includes): New.
* data/lalr1.cc: Use it.
* data/variant.hh (variant::built): Define at the end, as a private member.
(variant::tname): New.
Somewhat makes "built" useless, but let's keep both for a start, in
case using "typeinfo" is considered unacceptable in some environments.
Fix some formatting issues.

data/lalr1.cc
data/variant.hh

index 7b2aef2d85f82b6150f77dd490bd42047c4e9e36..0209925d5c057d890d5103e7a1047d5315dca6c1 100644 (file)
@@ -139,6 +139,7 @@ m4_define([b4_shared_declarations],
 # include <string>]b4_defines_if([[
 # include "stack.hh"
 ]b4_bison_locations_if([[# include "location.hh"]])])[
+]b4_variant_if([b4_variant_includes])[
 
 ]b4_YYDEBUG_define[
 
index 65f0026e9ca174de2378446247af79fb4be6f7e1..684f9e35bda0a64f9087ae58b074b08b231df78e 100644 (file)
@@ -74,26 +74,37 @@ m4_map([b4_char_sizeof_], [$@])dnl
 ])])
 
 
+# b4_variant_includes
+# -------------------
+# The needed includes for variants support.
+m4_define([b4_variant_includes],
+[b4_parse_assert_if([[#include <typeinfo>]])[
+#ifndef YYASSERT
+# include <cassert>
+# define YYASSERT assert
+#endif
+]])
+
 # b4_variant_define
 # -----------------
 # Define "variant".
 m4_define([b4_variant_define],
-[[
-  /// A char[S] buffer to store and retrieve objects.
+[[  /// A char[S] buffer to store and retrieve objects.
   ///
   /// Sort of a variant, but does not keep track of the nature
   /// of the stored data, since that knowledge is available
   /// via the current state.
   template <size_t S>
   struct variant
-  {]b4_parse_assert_if([
-    /// Whether something is contained.
-    bool built;
-])[
+  {
+    /// Type of *this.
+    typedef variant<S> self_type;
+
     /// Empty construction.
     inline
     variant ()]b4_parse_assert_if([
-      : built (false)])[
+      : built (false)
+      , tname (YY_NULL)])[
     {}
 
     /// Instantiate a \a T in here.
@@ -101,8 +112,11 @@ m4_define([b4_variant_define],
     inline T&
     build ()
     {]b4_parse_assert_if([
-      assert (!built);
-      built = true;])[
+      YYASSERT (!built);
+      YYASSERT (!tname);
+      YYASSERT (sizeof (T) <= S);
+      built = true;
+      tname = typeid (T).name ();])[
       return *new (buffer.raw) T;
     }
 
@@ -111,18 +125,23 @@ m4_define([b4_variant_define],
     inline T&
     build (const T& t)
     {]b4_parse_assert_if([
-      assert(!built);
-      built = true;])[
-      return *new (buffer.raw) T(t);
+      YYASSERT (!built);
+      YYASSERT (!tname);
+      YYASSERT (sizeof (T) <= S);
+      built = true;
+      tname = typeid (T).name ();])[
+      return *new (buffer.raw) T (t);
     }
 
     /// Construct and fill.
     template <typename T>
     inline
     variant (const T& t)]b4_parse_assert_if([
-      : built (true)])[
+      : built (true)
+      , tname (typeid (T).name ())])[
     {
-      new (buffer.raw) T(t);
+      YYASSERT (sizeof (T) <= S);
+      new (buffer.raw) T (t);
     }
 
     /// Accessor to a built \a T.
@@ -130,8 +149,10 @@ m4_define([b4_variant_define],
     inline T&
     as ()
     {]b4_parse_assert_if([
-      assert (built);])[
-      return reinterpret_cast<T&>(buffer.raw);
+      YYASSERT (built);
+      YYASSERT (tname == typeid (T).name ());
+      YYASSERT (sizeof (T) <= S);])[
+      return reinterpret_cast<T&> (buffer.raw);
     }
 
     /// Const accessor to a built \a T (for %printer).
@@ -139,16 +160,21 @@ m4_define([b4_variant_define],
     inline const T&
     as () const
     {]b4_parse_assert_if([
-      assert(built);])[
-      return reinterpret_cast<const T&>(buffer.raw);
+      YYASSERT (built);
+      YYASSERT (tname == typeid (T).name ());
+      YYASSERT (sizeof (T) <= S);])[
+      return reinterpret_cast<const T&> (buffer.raw);
     }
 
-    /// Swap the content with \a other.
+    /// Swap the content with \a other, of same type.
     template <typename T>
     inline void
     swap (variant<S>& other)
-    {
-      std::swap (as<T>(), other.as<T>());
+    {]b4_parse_assert_if([
+      YYASSERT (tname == other.tname);])[
+      std::swap (as<T>(), other.as<T>());]b4_parse_assert_if([
+      std::swap (built, other.built);
+      std::swap (tname, other.tname);])[
     }
 
     /// Assign the content of \a other to this.
@@ -167,10 +193,12 @@ m4_define([b4_variant_define],
     inline void
     destroy ()
     {
-      as<T>().~T();]b4_parse_assert_if([
-      built = false;])[
+      as<T> ().~T ();]b4_parse_assert_if([
+      built = false;
+      tname = YY_NULL;])[
     }
 
+  private:
     /// A buffer large enough to store any of the semantic values.
     /// Long double is chosen as it has the strongest alignment
     /// constraints.
@@ -178,7 +206,11 @@ m4_define([b4_variant_define],
     {
       long double align_me;
       char raw[S];
-    } buffer;
+    } buffer;]b4_parse_assert_if([
+    /// Whether something is contained.
+    bool built;
+    /// If defined, the name of the stored type.
+    const char* tname;])[
   };
 ]])
 
@@ -197,7 +229,8 @@ m4_define([b4_semantic_type_declare],
     {]b4_type_foreach([b4_char_sizeof])[};
 
     /// Symbol semantic values.
-    typedef variant<sizeof(union_type)> semantic_type;])
+    typedef variant<sizeof(union_type)> semantic_type;dnl
+])
 
 
 # How the semantic value is extracted when using variants.