Bison 3.1.90 has a flaw in it handling of its stack. Found while testing on Vcsn.
commit 3967e46a2dd3f6fea34a468b1d6207747b3f1832 Author: Akim Demaille <[email protected]> Date: Thu Oct 18 07:07:32 2018 +0200 lalr1.cc: fix stack symbol move In some casing, once we moved a stack symbol, we forget to mark the source stack symbol as emptied. As a consequence, it may be destroyed a second time. This happens when the stack has to be resized. * data/lalr1.cc (stack_symbol_type::stack_symbol_type): Record that the source was emptied. (stack_symbol_type::operator=): Likewise. * tests/c++.at (C++ Variant-based Symbols Unit Tests): Force the stack to be resized. Check its content. diff --git a/data/lalr1.cc b/data/lalr1.cc index cb8d6069..f80476db 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -602,6 +602,10 @@ m4_if(b4_prefix, [yy], [], {]b4_variant_if([ b4_symbol_variant([that.type_get ()], [value], [YY_MOVE_OR_COPY], [YY_MOVE (that.value)])])[ +#if defined __cplusplus && 201103L <= __cplusplus + // that is emptied. + that.state = empty_state; +#endif } ]b4_parser_class_name[::stack_symbol_type::stack_symbol_type (state_type s, YY_MOVE_REF (symbol_type) that) @@ -622,6 +626,8 @@ m4_if(b4_prefix, [yy], [], [value], [move], [YY_MOVE (that.value)])], [[value = YY_MOVE (that.value);]])[]b4_locations_if([ location = YY_MOVE (that.location);])[ + // that is emptied. + that.state = empty_state; return *this; } #endif diff --git a/tests/c++.at b/tests/c++.at index 2ce7b294..68167d09 100644 --- a/tests/c++.at +++ b/tests/c++.at @@ -162,19 +162,27 @@ int main() std::cerr << ss.value.as<int>() << '\n'; } - // pushing on the stack. + // Pushing on the stack. + // Sufficiently many so that it will be resized. + // Probably 3 times (starting at 200). { parser::stack_type st; - for (int i = 0; i < 100; ++i) + const int mucho = 1700; + for (int i = 0; i < mucho; ++i) { #if defined __cplusplus && 201103L <= __cplusplus - st.push(parser::stack_symbol_type{1, parser::make_INT(123)}); + st.push(parser::stack_symbol_type{1, parser::make_INT (i)}); #else - parser::symbol_type s = parser::make_INT(123); - parser::stack_symbol_type ss(1, s); - st.push(ss); + parser::symbol_type s = parser::make_INT (i); + parser::stack_symbol_type ss (1, s); + st.push (ss); #endif } + for (int i = mucho - 1; 0 <= i; --i) + { + assert (st[0].value.as<int>() == i); + st.pop (); + } } } ]])
