[Boost-bugs] [Boost C++ Libraries] #12016: x3::symbols moves result and therefore removes it from the symbol_parser itself

Subject: [Boost-bugs] [Boost C++ Libraries] #12016: x3::symbols moves result and therefore removes it from the symbol_parser itself
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2016-02-23 21:53:14


#12016: x3::symbols moves result and therefore removes it from the symbol_parser
itself
------------------------------+------------------------
 Reporter: UsYer | Owner: djowel
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: spirit
  Version: Boost 1.60.0 | Severity: Regression
 Keywords: |
------------------------------+------------------------
 So, I ran into strange behaviour with boost::spirit::x3 as supplied in
 boost 1.59:

 {{{
 #!div
 I defined a 'dynamic' symbol table via:
   {{{#!c++
    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;
   }}}
 }}}

 {{{
 #!div
 ''OpCode'' is defined as :
   {{{#!c++
     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

 {{{
 #!div

   {{{#!asm
     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:

 {{{
 #!div

   {{{#!asm
     mov r2 r1
         r1 @80
   }}}
 }}}

 {{{
 #!div
 With the debugger I located the source of the error in symbols.hpp in
 ''symbol_parser::parse()'':
   {{{#!c++:
     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;
         }

   }}}
 }}}

 {{{
 #!div
 with ''move_to'' beeing:
   {{{#!c++:
     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.

 [http://melpon.org/wandbox/permlink/XxPCnmWExNkmsmP2 '''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.

 {{{
 #!div
 I.E.:
   {{{#!c++:
  x3::symbols<const OpCode>
 }}}
 }}}

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/12016>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:19 UTC