X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/04816a6f3203968479591ebbe1886537674fa110..66c209cf435b5bfc5cf982d8df9cc3ef05b4546b:/data/variant.hh?ds=sidebyside diff --git a/data/variant.hh b/data/variant.hh index 4317abaf..91548d84 100644 --- a/data/variant.hh +++ b/data/variant.hh @@ -1,6 +1,6 @@ # C++ skeleton for Bison -# Copyright (C) 2002-2012 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 @@ -72,7 +72,6 @@ m4_map([ b4_symbol_tag_comment], [$@])dnl # The needed includes for variants support. m4_define([b4_variant_includes], [b4_parse_assert_if([[#include ]])[ -#include // abort #ifndef YYASSERT # include # define YYASSERT assert @@ -95,126 +94,125 @@ m4_define([b4_variant_define], typedef variant self_type; /// Empty construction. - inline variant ()]b4_parse_assert_if([ - : built (false) - , tname (YY_NULL)])[ + : tname (YY_NULL)])[ {} - /// Instantiate a \a T in here. + /// Construct and fill. template - inline T& + variant (const T& t)]b4_parse_assert_if([ + : tname (typeid (T).name ())])[ + { + YYASSERT (sizeof (T) <= S); + new (buffer.raw) T (t); + } + + /// Destruction, allowed only if empty. + ~variant () + {]b4_parse_assert_if([ + YYASSERT (!tname); + ])[} + + /// Instantiate an empty \a T in here. + template + T& build () {]b4_parse_assert_if([ - //YYASSERT (!built); - //YYASSERT (!tname); + 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([ - //YYASSERT (!built); - //YYASSERT (!tname); + 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) - , tname (typeid (T).name ())])[ - { - YYASSERT (sizeof (T) <= S); - new (buffer.raw) T (t); - } - /// Accessor to a built \a T. template - inline T& + T& as () {]b4_parse_assert_if([ - YYASSERT (built); YYASSERT (tname == typeid (T).name ()); YYASSERT (sizeof (T) <= S);])[ - return reinterpret_cast (buffer.raw); + { + void *dummy = buffer.raw; + return *static_cast (dummy); + } } /// Const accessor to a built \a T (for %printer). template - inline const T& + const T& as () const {]b4_parse_assert_if([ - YYASSERT (built); YYASSERT (tname == typeid (T).name ()); YYASSERT (sizeof (T) <= S);])[ - return reinterpret_cast (buffer.raw); + { + const void *dummy = buffer.raw; + return *static_cast (dummy); + } } /// Swap the content with \a other, of same type. - /// Both variants must be built beforehand. + /// + /// 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 - swap (variant& other) + void + swap (self_type& other) {]b4_parse_assert_if([ - YYASSERT (built); - YYASSERT (other.built); + YYASSERT (tname); 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 (self_type& other) + {]b4_parse_assert_if([ + YYASSERT (!tname);])[ build(); swap(other); other.destroy(); } /// Copy the content of \a other to this. - /// Destroys \a other. template - inline void - copy (const variant& other) + void + copy (const self_type& other) { build (other.as ()); } /// Destroy the stored \a T. template - inline void + void destroy () { as ().~T ();]b4_parse_assert_if([ - built = false; tname = YY_NULL;])[ } + private: /// Prohibit blind copies. - private: - self_type& operator=(const self_type&) - { - abort (); - } + self_type& operator=(const self_type&); + variant (const self_type&); - variant (const self_type&) - { - abort (); - } - - private: /// A buffer large enough to store any of the semantic values. /// Long double is chosen as it has the strongest alignment /// constraints. @@ -223,10 +221,9 @@ m4_define([b4_variant_define], long double align_me; char raw[S]; } buffer;]b4_parse_assert_if([ - /// Whether something is contained. - bool built; - /// If defined, the name of the stored type. - const char* tname;])[ + + /// Whether the content is built: if defined, the name of the stored type. + const char *tname;])[ }; ]]) @@ -313,11 +310,39 @@ b4_join(b4_symbol_if([$1], [has_type], return symbol_type (b4_join([token::b4_symbol([$1], [id])], b4_symbol_if([$1], [has_type], [v]), b4_locations_if([l]))); + } ])])]) +# b4_basic_symbol_constructor_declare +# ---------------------------------- +# Generate a constructor declaration for basic_symbol from given type. +m4_define([b4_basic_symbol_constructor_declare], +[[ + basic_symbol (]b4_join( + [typename Base::kind_type t], + b4_symbol_if([$1], [has_type], const b4_symbol([$1], [type])[ v]), + b4_locations_if([const location_type& l]))[); +]]) + +# b4_basic_symbol_constructor_define +# ---------------------------------- +# Generate a constructor implementation for basic_symbol from given type. +m4_define([b4_basic_symbol_constructor_define], +[[ + template + ]b4_parser_class_name[::basic_symbol::basic_symbol (]b4_join( + [typename Base::kind_type t], + b4_symbol_if([$1], [has_type], const b4_symbol([$1], [type])[ v]), + b4_locations_if([const location_type& l]))[) + : Base (t) + , value (]b4_symbol_if([$1], [has_type], [v])[)]b4_locations_if([ + , location (l)])[ + {} +]]) + # b4_symbol_constructor_define # ---------------------------- # Define the overloaded versions of make_symbol for all the value types.