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: 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 17:59:56 -0400

HI

@sasha, thanks!!  that worked.

Could someone add those suppprt for std::unique_ptr , that seems very
useful feature?



thanks


min



On Thu, Aug 18, 2016 at 4:19 PM, Sasha Unknown <address@hidden> wrote:

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


-- 
http://www.comrite.com


reply via email to

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