Hi The manual states that user-defined %destructors are called only on a specific list of discarded symbols:
| “Discarded symbols” are the following: | | • stacked symbols popped during the first phase of error recovery, | • incoming terminals during the second phase of error recovery, | • the current lookahead and the entire stack (except the current | right-hand side symbols) when the parser returns immediately, and | • the current lookahead and the entire stack (including the current | right-hand side symbols) when the C++ parser (‘lalr1.cc’) catches | an exception in ‘parse’, | • the start symbol, when the parser succeeds. However it seems that this list is augmented to include all stacked symbols when C++ variants are used. That looks wrong to me. Is this really intended? Context: I'm trying to convert a union-based C++ parser to variant-based one. I used to do something like: | %language "C++" | // [...] | %union | { | std::string* str; | const spot::fnode* ltl; | unsigned num; | } | | %destructor { delete $$; } <str> | %destructor { $$->destroy(); } <ltl> | // [...] | %token <str> rule1 rule2... | %token <ltl> rule3 rule4... | %token <num> rule5 rule6... and I'm now changing that code to read | %language "C++" | %define api.value.type variant | // [...] | %destructor { $$->destroy(); } <const spot::fnode*> | // [...] | %token <std::string> rule1 rule2... | %token <const spot::fnode*> rule3 rule4... | %token <num> rule5 rule6... I'm happy that I do not have to deal with the memory management of strings anymore. However this fnode* object is still something I want to handle using a pointer (because of the pecular way I construct it). Unfortunately, my new variant-based parser fails because of many extra and unexpected calls to the above destroy() method. Everytime the parser pops a basic_symbol from its stack as part of a normal reduce operation, it calls ~basic_symbol() which in turns calls basic_symbol::clear() which unexpectedly calls the used defined destructor :-( During reduce operations, I was expecting to see the standard destructors of the types being used in the variant to be called (so popping a basic_symbol that contains a std::string calls std::string::~string(), and popping a basic_symbol that contains a pointer or unsigned does nothing), but not the user-defined %destructors (as per the documentation). Alexandre