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