HI @sasha, thanks!! that worked.
Could someone add those suppprt for std::unique_ptr , that seems very useful feature? thanks min On Thu, Aug 18, 2016 at 4:19 PM, Sasha Unknown <[email protected]> wrote: > Some time ago I workaround that issue with the following DIRTY HACK: > > --- file.hh > +++ file.hh > @@ -178 +178 @@ > - return *new (yyas_<T> ()) T (t); > + return *new (yyas_<T> ()) T (std::move((T&)t)); > > I'm not sure about stability of this "solution", probably it contains UB > -- but it "worked" enough to test my prototype. > > > On 18.08.16 22:16, Min Wang wrote: > >> HI >> >> Also >> >> http://lists.gnu.org/archive/html/bug-bison/2015-01/msg00066.html >> >> seems indicated bison does not support std::unique_ptr as a semantic >> values >> >> >> min >> >> >> >> >> On Thu, Aug 18, 2016 at 3:05 PM, Min Wang <[email protected]> wrote: >> >> HI >>> @kaz. thanks. I will check the %union later >>> >>> I'like to use the smart pointers ( std::unique_ptr) , but somehow I got >>> some compiler errors. >>> >>> here are some details: >>> e.g: >>> >>> using PROG_PTR = std::unique_ptr<PROG>; >>> .... >>> >>> >>> %type <PROG_PTR> PROG >>> >>> %type <ListExp_PTR> ListExp >>> >>> %type <Exp_PTR> Exp >>> >>> ... >>> >>> >>> PROG : ListExp { >>> std::reverse( $1->begin(), $1->end() ); >>> // store the result to filter_driver.prog >>> driver.store_ast( new Json_Filter( std::move($1) ) ); >>> } >>> ; >>> >>> ListExp : Exp { >>> ListExp_PTR tmp( new ListExp() ) ; >>> tmp->push_back( std::move($1) ); >>> std::swap( $$, tmp ); >>> } >>> >>> //some classes >>> >>> class PROG : public Visitable >>> >>> { >>> >>> public: >>> >>> virtual ~PROG() {}; >>> >>> >>> >>> }; >>> >>> // real one here >>> >>> using ListExp_PTR = std::unique_ptr<ListExp>; >>> >>> >>> >>> class Json_Filter : public PROG >>> >>> { >>> >>> public: >>> >>> ListExp_PTR listexp_; >>> >>> >>> >>> Json_Filter(ListExp_PTR p1) : listexp_( std::move(p1) ) {} >>> >>> ~Json_Filter() {} >>> >>> >>> >>> }; >>> >>> // should not inherit vector here, put here just for testing now. >>> class ListExp : public Visitable, public std::vector<Exp_PTR> >>> >>> { >>> >>> public: >>> >>> }; >>> >>> >>> >>> but I got those errors: >>> .... >>> >>> In file included from filter_parser.cpp:46:0: >>> >>> filter_parser.hh: In instantiation of ‘T& brc_filter::variant<S>::build( >>> const >>> T&) [with T = std::unique_ptr<ListExp>; long unsigned int S = 8ul]’: >>> filter_parser.hh:241:12: required from ‘void >>> brc_filter::variant<S>::copy(const self_type&) [with T = >>> std::unique_ptr<ListExp>; long unsigned int S = 8ul; >>> brc_filter::variant<S>::self_type = brc_filter::variant<8ul>]’ >>> filter_parser.cpp:353:46: required from here >>> >>> filter_parser.hh:184:37: error: use of deleted function >>> ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) >>> [with _Tp = ListExp; _Dp = std::default_delete<ListExp>]’ >>> return *new (yyas_<T> ()) T (t); >>> >>> ^ >>> >>> In file included from /usr/include/c++/4.9/memory:81:0, >>> >>> from syntax.hh:6, >>> >>> from filter_parser.yy:46, >>> >>> from filter_parser.cpp:46: >>> >>> /usr/include/c++/4.9/bits/unique_ptr.h:356:7: note: declared here >>> >>> unique_ptr(const unique_ptr&) = delete; >>> >>> .... >>> >>> the filter_parser.hh:184 is: >>> >>> /// Instantiate a \a T in here from \a t. >>> >>> template <typename T> >>> >>> T& >>> >>> build (const T& t) >>> >>> { >>> >>> YYASSERT (!yytypeid_); >>> >>> YYASSERT (sizeof (T) <= S); >>> >>> yytypeid_ = & typeid (T); >>> >>> return *new (yyas_<T> ()) T (t); >>> >>> } >>> >>> >>> seems the build function somehow is not right? >>> >>> >>> thanks >>> >>> >>> min >>> >>> On Thu, Aug 18, 2016 at 1:12 PM, Kaz Kylheku <[email protected]> wrote: >>> >>> On 18.08.2016 08:36, Min Wang wrote: >>>> >>>> HI >>>>> >>>>> In bison 3.0.4, the %destructor seems to be called even in the normal >>>>> parse >>>>> >>>>> In your example program you are using "Variants" rather >>>> than %union. That's a very special C++-specific Bison feature. >>>> >>>> It seems that there is no reason to use %destructor if you're >>>> using variants. If any of the variants are pointers, they can >>>> just be smart pointers; they don't have to be low level pointers. >>>> >>>> Can you confirm whether %destructor is still called in the >>>> normal parse if instead of: >>>> >>>> %type <PROG*> PROG >>>> %type <ListExp*> ListExp >>>> >>>> you use >>>> >>>> %union { >>>> PROG *PROG; >>>> ListExp *ListExp; >>>> } >>>> >>>> That is to say, is this a issue specific to variants, or does it >>>> affect C++ parsers regardless of whether %union or variants >>>> are used? >>>> >>>> If under %union, %destructor is correctly called only during >>>> error recovery (the issue is absent) then just use %union, >>>> since all your semantic value types are pointers. Then be sure >>>> you have all the right delete calls in your grammar actions. >>>> >>>> If you use variants, it seems you can side-step the issue >>>> by not using pointers. If the values are smart pointers, >>>> then there is no problem, because a rule like: >>>> >>>> foo : bar { $$ = $1; } >>>> >>>> will handle the transfer from $1 to $$ using the smart pointer >>>> assignment operator, allowing $1 to then be safely destroyed >>>> by its destructor. >>>> >>>> It does seem that you have discovered at least this bug, >>>> or deviation from documented behavior: when plain pointer types >>>> are used in variant declarations in a C++ parser, and %destructor >>>> is used to free them in all circumstances. >>>> >>>> So for instance, suppose that we use the type <char *>, >>>> and we have a %destructor which calls free. In a C parser, >>>> we might just have this: >>>> >>>> foo : bar { $$ = $1; } /* transfer ownership of pointer */ >>>> >>>> But under C++ Bison with variants, we must do: >>>> >>>> foo : bar { $$ = strdup($1); } /* $1 %destructor will kick in */ >>>> >>>> Or perhaps this will work: >>>> >>>> foo : bar { $$ = $1; >>>> $1 = NULL; } /* Spare $1 from jaws of %destructor */ >>>> >>>> >>>> >>>> >>>> >>> -- >>> http://www.comrite.com >>> >>> >>> >>> >>> >> > > -- http://www.comrite.com
