#12016 closed Bugs (fixed)
x3::symbols moves result and therefore removes it from the symbol_parser itself
Reported by: | UsYer | Owned by: | Joel de Guzman |
---|---|---|---|
Milestone: | To Be Determined | Component: | spirit |
Version: | Boost 1.60.0 | Severity: | Regression |
Keywords: | spirit, x3, symbols | Cc: |
Description
So, I ran into strange behaviour with boost::spirit::x3 as supplied in boost 1.59:
I defined a 'dynamic' symbol table via:
struct instructions : x3::symbols<OpCode> { instructions() { name("instructions"); } void set_instruction_set(const std::unordered_map<std::string, OpCode>& instruction_set) { for (const auto& var : instruction_set) { add(var.first, var.second); } } } instructions_parser;
OpCode is defined as :
struct OpCode { std::string mnemonic; std::vector<...> variants;// actual type in vector<> not important. };
now, with the symbol table embedded in the neccessary rules, when parsing an input string like
mov r2 r1 mov r1 @80
the resulting ast only contains the first mov
with its operands.
The second mov is missing but the operands are correctly parsed.
This may look as followed, when printing the resulting AST:
mov r2 r1 r1 @80
With the debugger I located the source of the error in symbols.hpp in symbol_parser::parse():
template <typename Iterator, typename Context, typename Attribute> bool parse(Iterator& first, Iterator const& last , Context const& context, unused_type, Attribute& attr) const { x3::skip_over(first, last, context); if (value_type* val_ptr = lookup->find(first, last, get_case_compare<Encoding>(context))) { x3::traits::move_to(*val_ptr, attr); //<- the error originates from here return true; } return false; }
with move_to beeing:
template <typename T> inline void move_to(T& src, T& dest) { if (boost::addressof(src) != boost::addressof(dest)) dest = std::move(src); }
As you can see, the src which is my OpCode instance added in the symbol_parser is moved. This means after the first call its empty again and that's why only the first instructions appears. It's, simply put, moved out of the symbol table.
''Live example (shows the bug is also present in 1.60)'' provided by cv_and_he @stackoverflow
Temporary Workaround:
By declaring the template parameter as const one can suppress move semantics. The copy-ctor is then called.
I.E.:
x3::symbols<const OpCode>
Change History (6)
comment:1 by , 7 years ago
Keywords: | spirit x3 symbols added |
---|
comment:2 by , 7 years ago
comment:3 by , 7 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:4 by , 7 years ago
Excellent report.
It strikes me that the const-ness of the value seems to be _the_ way to indicate a parser's result value is not to be moved from.
(This seems to be by design? It seems a bit odd that the library would not strictly perfectly forward all temporaries and only move from known rvalues)
I suggested a patch based on const mapped values https://github.com/boostorg/spirit/pull/174
comment:6 by , 7 years ago
I agree! Excellent report! I beat sehe to a fix, but thanks a lot sehe, I really appreciate it. You rock! Esp. on the spirit list and stack-exchange.
PS> Sometimes I try to post a solution to stack-exchange, but then it says I do not have enough credibility points :-)
Fixed in develop branch. Please confirm! Thanks for the report!