mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
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.
This commit is contained in:
@@ -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[
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user