From 35f70d169f6bc2a00b0ffca8bfd388516c4af70f Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Wed, 19 Dec 2012 10:09:07 +0100 Subject: [PATCH] variant: more assertions 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 | 1 + data/variant.hh | 83 ++++++++++++++++++++++++++++++++++--------------- 2 files changed, 59 insertions(+), 25 deletions(-) diff --git a/data/lalr1.cc b/data/lalr1.cc index 7b2aef2d..0209925d 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -139,6 +139,7 @@ m4_define([b4_shared_declarations], # include ]b4_defines_if([[ # include "stack.hh" ]b4_bison_locations_if([[# include "location.hh"]])])[ +]b4_variant_if([b4_variant_includes])[ ]b4_YYDEBUG_define[ diff --git a/data/variant.hh b/data/variant.hh index 65f0026e..684f9e35 100644 --- a/data/variant.hh +++ b/data/variant.hh @@ -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 ]])[ +#ifndef YYASSERT +# include +# 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 struct variant - {]b4_parse_assert_if([ - /// Whether something is contained. - bool built; -])[ + { + /// Type of *this. + typedef variant 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 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(buffer.raw); + YYASSERT (built); + YYASSERT (tname == typeid (T).name ()); + YYASSERT (sizeof (T) <= S);])[ + return reinterpret_cast (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(buffer.raw); + YYASSERT (built); + YYASSERT (tname == typeid (T).name ()); + YYASSERT (sizeof (T) <= S);])[ + return reinterpret_cast (buffer.raw); } - /// Swap the content with \a other. + /// Swap the content with \a other, of same type. template inline void swap (variant& other) - { - std::swap (as(), other.as()); + {]b4_parse_assert_if([ + YYASSERT (tname == other.tname);])[ + std::swap (as(), other.as());]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();]b4_parse_assert_if([ - built = false;])[ + as ().~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 semantic_type;]) + typedef variant semantic_type;dnl +]) # How the semantic value is extracted when using variants. -- 2.45.2