[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:05:08 -0400 |
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