variants: prohibit simple copies

The "variant" structure provides a means to store, in a typeless way,
C++ objects.  Manipulating it without provide the type of the stored
content is doomed to failure.  So provide a means to copy in a type
safe way, and prohibit typeless assignments.

* data/c++.m4 (symbol_type::move): New.
* data/lalr1.cc: Use it.
* data/variant.hh (b4_variant_define): Provide variant::copy.
Let variant::operator= abort.
We cannot undefine it, yet, as it is still uses by the implicit
assigment in symbols, which must also be disabled.
This commit is contained in:
Akim Demaille
2012-12-19 10:18:03 +01:00
parent 35f70d169f
commit 7be08dfbe7
3 changed files with 35 additions and 4 deletions

View File

@@ -185,6 +185,9 @@ m4_define([b4_public_types_declare],
/// Default constructor. /// Default constructor.
inline symbol_type (); inline symbol_type ();
/// Destructive move, \a s is emptied.
inline void move (symbol_type& s);
/// Constructor for tokens with semantic value. /// Constructor for tokens with semantic value.
inline symbol_type (]b4_join([token_type t], inline symbol_type (]b4_join([token_type t],
[const semantic_type& v], [const semantic_type& v],
@@ -294,6 +297,16 @@ m4_define([b4_public_types_define],
{ {
} }
inline
void
]b4_parser_class_name[::symbol_type::move (symbol_type& s)
{
]b4_variant_if([b4_symbol_variant([[s.type]], [value], [build], [s.value])],
[value = s.value;])[
type = s.type;]b4_locations_if([
location = s.location;])[
}
inline inline
int int
]b4_parser_class_name[::symbol_type::type_get_ () const ]b4_parser_class_name[::symbol_type::type_get_ () const

View File

@@ -721,10 +721,11 @@ b4_dollar_popdef])[]dnl
try try
{ {
]b4_token_ctor_if( ]b4_token_ctor_if(
[ yyla = b4_function_call([yylex], [symbol_type], [ symbol_type yylookahead = b4_function_call([yylex], [symbol_type],
m4_ifdef([b4_lex_param], b4_lex_param));], m4_ifdef([b4_lex_param], b4_lex_param));
[ yyla.type = yytranslate_ (b4_function_call([yylex], [int], yyla.move(yylookahead);],
[b4_api_PREFIX[STYPE*], [&yyla.value]][]dnl [ yyla.type = yytranslate_ (b4_function_call([yylex], [int],
[b4_api_PREFIX[STYPE*], [&yyla.value]][]dnl
b4_locations_if([, [[location*], [&yyla.location]]])dnl b4_locations_if([, [[location*], [&yyla.location]]])dnl
m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[ m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[
} }

View File

@@ -79,6 +79,7 @@ m4_map([b4_char_sizeof_], [$@])dnl
# The needed includes for variants support. # The needed includes for variants support.
m4_define([b4_variant_includes], m4_define([b4_variant_includes],
[b4_parse_assert_if([[#include <typeinfo>]])[ [b4_parse_assert_if([[#include <typeinfo>]])[
#include <cstdlib> // abort
#ifndef YYASSERT #ifndef YYASSERT
# include <cassert> # include <cassert>
# define YYASSERT assert # define YYASSERT assert
@@ -188,6 +189,15 @@ m4_define([b4_variant_define],
other.destroy<T>(); other.destroy<T>();
} }
/// Copy the content of \a other to this.
/// Destroys \a other.
template <typename T>
inline void
copy (const variant<S>& other)
{
build<T> (other.as<T> ());
}
/// Destroy the stored \a T. /// Destroy the stored \a T.
template <typename T> template <typename T>
inline void inline void
@@ -198,6 +208,13 @@ m4_define([b4_variant_define],
tname = YY_NULL;])[ tname = YY_NULL;])[
} }
/// Prohibit blind copies.
// private:
self_type& operator=(const self_type&)
{
abort ();
}
private: private:
/// A buffer large enough to store any of the semantic values. /// A buffer large enough to store any of the semantic values.
/// Long double is chosen as it has the strongest alignment /// Long double is chosen as it has the strongest alignment