[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: bison 3.0.4 %destructor is c++ mode seems to be called even in the n
From: |
Min Wang |
Subject: |
Re: bison 3.0.4 %destructor is c++ mode seems to be called even in the normal parse |
Date: |
Thu, 18 Aug 2016 15:16:47 -0400 |
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 <address@hidden> 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 <address@hidden> 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