X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/7d424de14c0385012d328642bec6874c8e6cef17..26f95f5f356ca003d125a5c5285a09a0564e3bd9:/data/variant.hh diff --git a/data/variant.hh b/data/variant.hh index 832b9672..da0d2a39 100644 --- a/data/variant.hh +++ b/data/variant.hh @@ -1,7 +1,6 @@ # C++ skeleton for Bison -# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, -# 2010 Free Software Foundation, Inc. +# Copyright (C) 2002-2013 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -52,13 +51,6 @@ m4_define([_b4_char_sizeof_dummy], dummy[]_b4_char_sizeof_counter]) -# b4_char_sizeof_(SYMBOL-NUM) -# --------------------------- -# A comment describing this symbol. -m4_define([b4_char_sizeof_], -[ // b4_symbol([$1], [tag]) -]) - # b4_char_sizeof(SYMBOL-NUMS) # --------------------------- # To be mapped on the list of type names to produce: @@ -70,108 +62,161 @@ m4_define([b4_char_sizeof_], m4_define([b4_char_sizeof], [b4_symbol_if([$1], [has_type], [ -m4_map([b4_char_sizeof_], [$@])dnl +m4_map([ b4_symbol_tag_comment], [$@])dnl char _b4_char_sizeof_dummy@{sizeof([b4_symbol([$1], [type])])@}; ])]) +# 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. + /// Construct and fill. + template + variant (const T& t)]b4_parse_assert_if([ + : built (true) + , tname (typeid (T).name ())])[ + { + YYASSERT (sizeof (T) <= S); + new (buffer.raw) T (t); + } + + /// Destruction, allowed only if empty. + ~variant () + {]b4_parse_assert_if([ + YYASSERT (!built); + ])[} + + /// Instantiate an empty \a T in here. template - inline T& + 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; } /// Instantiate a \a T in here from \a t. template - inline T& + T& build (const T& t) {]b4_parse_assert_if([ - assert(!built); - built = true;])[ - return *new (buffer.raw) T(t); - } - - /// Construct and fill. - template - inline - variant (const T& t)]b4_parse_assert_if([ - : built (true)])[ - { - 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); } /// Accessor to a built \a T. template - inline T& + 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). template - inline const T& + 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. + /// + /// Both variants must be built beforehand, because swapping the actual + /// data requires reading it (with as()), and this is not possible on + /// unconstructed variants: it would require some dynamic testing, which + /// should not be the variant's responsability. + /// Swapping between built and (possibly) non-built is done with + /// variant::move (). template - inline void + void swap (variant& other) - { + {]b4_parse_assert_if([ + YYASSERT (built); + YYASSERT (other.built); + YYASSERT (tname == other.tname);])[ std::swap (as(), other.as()); } - /// Assign the content of \a other to this. + /// Move the content of \a other to this. + /// /// Destroys \a other. template - inline void - build (variant& other) - { + void + move (variant& other) + {]b4_parse_assert_if([ + YYASSERT (! built);])[ build(); swap(other); other.destroy(); } + /// Copy the content of \a other to this. + template + void + copy (const variant& other) + { + build (other.as ()); + } + /// Destroy the stored \a T. template - inline void + void destroy () { - as().~T();]b4_parse_assert_if([ - built = false;])[ + as ().~T ();]b4_parse_assert_if([ + built = false; + tname = YY_NULL;])[ } + private: + /// Prohibit blind copies. + self_type& operator=(const self_type&); + variant (const self_type&); + /// A buffer large enough to store any of the semantic values. /// Long double is chosen as it has the strongest alignment /// constraints. @@ -179,7 +224,12 @@ m4_define([b4_variant_define], { long double align_me; char raw[S]; - } buffer; + } buffer;]b4_parse_assert_if([ + + /// Whether the content is built. + bool built; + /// If defined, the name of the stored type. + const char* tname;])[ }; ]]) @@ -198,7 +248,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. @@ -234,7 +285,7 @@ m4_define([b4_symbol_constructor_declare_], [ static inline symbol_type make_[]b4_symbol_([$1], [id]) (dnl -b4_args(b4_symbol_if([$1], [has_type], +b4_join(b4_symbol_if([$1], [has_type], [const b4_symbol([$1], [type])& v]), b4_locations_if([const location_type& l]))); @@ -258,16 +309,17 @@ m4_define([b4_symbol_constructor_define_], [b4_symbol_if([$1], [is_token], [b4_symbol_if([$1], [has_id], [ b4_parser_class_name::symbol_type b4_parser_class_name::make_[]b4_symbol_([$1], [id]) (dnl -b4_args(b4_symbol_if([$1], [has_type], +b4_join(b4_symbol_if([$1], [has_type], [const b4_symbol([$1], [type])& v]), - b4_locations_if([const location_type& l]))) + b4_locations_if([const location_type& l])))[ { - return symbol_type (b4_args([token::b4_symbol([$1], [id])], - b4_symbol_if([$1], [has_type], [v]), - b4_locations_if([l]))); + symbol_type res (token::]b4_symbol([$1], [id])[]b4_locations_if([, l])[); + ]b4_symbol_if([$1], [has_type], [res.value.build (v);])[ + // ]b4_locations_if([res.location = l;])[ + return res; } -])])]) +]])])]) # b4_symbol_constructor_define