glr2.cc: add sanity checks in glr_stack_item

We obviously have broken pointer arithmetics that hands us
glr_stack_items that are not glr_stack_items.  Have a simple check for
this, to have earlier failures.

* data/skeletons/glr2.cc (glr_stack_item::check_): New.
Use it.
(glr_stack_item::contents): Avoid the useless struct.
Fix minor stylistic issues.
This commit is contained in:
Akim Demaille
2020-12-06 16:21:29 +01:00
parent 42fe808292
commit 2313f891bd

View File

@@ -1155,7 +1155,8 @@ class glr_stack_item
{ {
public: public:
glr_stack_item (bool state = true) glr_stack_item (bool state = true)
: is_state_ (state) : is_state_ (state)]b4_parse_assert_if([[
, magic_ (MAGIC)]])[
{ {
if (is_state_) if (is_state_)
new (&raw_) glr_state; new (&raw_) glr_state;
@@ -1163,21 +1164,26 @@ public:
new (&raw_) semantic_option; new (&raw_) semantic_option;
} }
glr_stack_item(const glr_stack_item& other) YY_NOEXCEPT YY_NOTHROW glr_stack_item (const glr_stack_item& other) YY_NOEXCEPT YY_NOTHROW
: is_state_(other.is_state_) : is_state_ (other.is_state_)]b4_parse_assert_if([[
{ , magic_ (0xDEAD1ACC)]])[
std::memcpy(raw_, other.raw_, union_size); {]b4_parse_assert_if([[
other.check_ ();]])[
std::memcpy (raw_, other.raw_, union_size);
} }
glr_stack_item& operator=(glr_stack_item other) glr_stack_item& operator= (glr_stack_item other)
{ {]b4_parse_assert_if([[
std::swap(is_state_, other.is_state_); check_ ();
std::swap(raw_, other.raw_); other.check_ ();]])[
std::swap (is_state_, other.is_state_);
std::swap (raw_, other.raw_);
return *this; return *this;
} }
~glr_stack_item() ~glr_stack_item ()
{ {]b4_parse_assert_if([[
check_ ();]])[
if (is_state()) if (is_state())
getState().~glr_state(); getState().~glr_state();
else else
@@ -1185,44 +1191,48 @@ public:
} }
glr_state& getState () glr_state& getState ()
{ {]b4_parse_assert_if([[
check_ ();]])[
YYDASSERT (is_state ()); YYDASSERT (is_state ());
void *yyp = raw_; void *yyp = raw_;
return *static_cast<glr_state*> (yyp); return *static_cast<glr_state*> (yyp);
} }
const glr_state& getState () const const glr_state& getState () const
{ {]b4_parse_assert_if([[
YYDASSERT (is_state()); check_ ();]])[
YYDASSERT (is_state ());
const void *yyp = raw_; const void *yyp = raw_;
return *static_cast<const glr_state*> (yyp); return *static_cast<const glr_state*> (yyp);
} }
semantic_option& getOption () semantic_option& getOption ()
{ {]b4_parse_assert_if([[
check_ ();]])[
YYDASSERT (!is_state ()); YYDASSERT (!is_state ());
void *yyp = raw_; void *yyp = raw_;
return *static_cast<semantic_option*> (yyp); return *static_cast<semantic_option*> (yyp);
} }
const semantic_option& getOption () const const semantic_option& getOption () const
{ {]b4_parse_assert_if([[
check_ ();]])[
YYDASSERT (!is_state ()); YYDASSERT (!is_state ());
const void *yyp = raw_; const void *yyp = raw_;
return *static_cast<const semantic_option*> (yyp); return *static_cast<const semantic_option*> (yyp);
} }
bool is_state () const bool is_state () const
{ {]b4_parse_assert_if([[
check_ ();]])[
return is_state_; return is_state_;
} }
private: private:
/// The possible contents of raw_. Since they have constructors, they cannot /// The possible contents of raw_. Since they have constructors, they cannot
/// be directly included in the union. /// be directly included in the union.
struct contents { union contents
union { {
char yystate[sizeof(glr_state)]; char yystate[sizeof (glr_state)];
char yyoption[sizeof(semantic_option)]; char yyoption[sizeof (semantic_option)];
};
}; };
enum { union_size = sizeof(contents) }; enum { union_size = sizeof (contents) };
union { union {
/// Strongest alignment constraints. /// Strongest alignment constraints.
long double yyalign_me; long double yyalign_me;
@@ -1231,6 +1241,17 @@ public:
}; };
/** Type tag for the union. */ /** Type tag for the union. */
bool is_state_; bool is_state_;
]b4_parse_assert_if([[
// Check invariants.
void check_ () const
{
YYASSERT (this->magic_ == MAGIC);
YYASSERT (this->is_state_ == false || this->is_state_ == true);
}
// A magic number to check our pointer arithmetics is sane.
enum { MAGIC = 0xDEAD1ACC };
const unsigned int magic_;]])[
}; };
glr_state* glr_state::pred () glr_state* glr_state::pred ()
@@ -1272,7 +1293,9 @@ std::ptrdiff_t semantic_option::indexIn(glr_stack_item* array) {
} }
glr_state* semantic_option::state() { glr_state* semantic_option::state() {
YY_IGNORE_NULL_DEREFERENCE_BEGIN
return yystate ? &(asItem(this) - yystate)->getState() : YY_NULLPTR; return yystate ? &(asItem(this) - yystate)->getState() : YY_NULLPTR;
YY_IGNORE_NULL_DEREFERENCE_END
} }
const glr_state* semantic_option::state() const { const glr_state* semantic_option::state() const {