[Top][All Lists]

[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: Sasha Unknown
Subject: Re: bison 3.0.4 %destructor is c++ mode seems to be called even in the normal parse
Date: Thu, 18 Aug 2016 23:19:14 +0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0

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:



seems indicated bison does not support std::unique_ptr as a semantic values


On Thu, Aug 18, 2016 at 3:05 PM, Min Wang <address@hidden> wrote:

@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:

using PROG_PTR = std::unique_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



     virtual ~PROG() {};


// real one here

using ListExp_PTR = std::unique_ptr<ListExp>;

class Json_Filter : public PROG



   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>




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>


     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?



On Thu, Aug 18, 2016 at 1:12 PM, Kaz Kylheku <address@hidden> wrote:

On 18.08.2016 08:36, Min Wang wrote:


In bison 3.0.4, the  %destructor seems to be called even in the normal

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 */


reply via email to

[Prev in Thread] Current Thread [Next in Thread]