bug-bison
[Top][All Lists]
Advanced

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









reply via email to

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