[cfe-dev] Ownership of Stmts and Exprs, and destroying them

Howard Hinnant hhinnant at apple.com
Sun Nov 23 08:33:44 PST 2008


On Nov 23, 2008, at 8:25 AM, Doug Gregor wrote:

> On Sun, Nov 23, 2008 at 2:54 AM, Chris Lattner <clattner at apple.com>  
> wrote:
>>
>> On Nov 22, 2008, at 3:36 PM, Sebastian Redl wrote:
>>> Is this correct? Because I want to clean this up. I want to make the
>>> Sema routines (and later the parser, too) not leak. So I need to  
>>> know
>>> exactly how this works.
>>
>> This would be great.  Probably the first place to start is to use
>> audit the parser for places where early exits cause parsed stmts to  
>> be
>> leaked.  Once that is done, start going through sema.  The pattern we
>> want to use in Sema for statements is using OwningPtr to hold  
>> incoming
>> arguments.  For example, ActOnBinOp should look like:
>>
>>                                    ExprTy *LHS, ExprTy *RHS) {
>>  BinaryOperator::Opcode Opc = ConvertTokenKindToBinaryOpcode(Kind);
>>  OwningPtr<Expr> lhs = (Expr *)LHS, rhs = (Expr*)RHS;
>
> This is too late. We want the arguments to the ActOnBinOp to be some
> kind of smart pointer that provides transfer-of-ownership semantics
> (basically, a C++'0x move_ptr) and knows how to delete expressions
> properly (via Action::DestroyExpr). Similarly for ExprResult and
> friends. That way, the type system enforces our ownership model
> (transfer into Sema for the parameters of ActOn*, transfer out of Sema
> on return), and we're safe from early exits.

If it helps, here's a C++03 emulation of the C++0X std::unique_ptr  
(what Doug refers to as move_ptr):

http://home.twcny.rr.com/hinnant/cpp_extensions/unique_ptr_03.html

You can set its "deleter" to call Action::DestroyExpr.  It might look  
something like:


                           unique_ptr<ExprTy, CallActionDestroyExpr>  
lhs,
                           unique_ptr<ExprTy, CallActionDestroyExpr>  
rhs) {
  BinaryOperator::Opcode Opc = ConvertTokenKindToBinaryOpcode(Kind);
  ...

CallActionDestroyExpr will need to be a function pointer or functor  
that accepts a ExprTy*.  It can be stateful (hold a this for a member  
function pointer).  If stateful, that state can be supplied in the  
unique_ptr constructor, and will be transferred from copy to copy  
along with pointer ownership.

If we need a unique_ptr that isn't dependent on boost, I can supply  
that (it would require parts of <type_traits> and something to replace  
boost::compressed_pair).  I haven't tested the link above in several  
years.  I know it used to work but you know how software decays.  The  
unique_ptr<T[N]> specialization (which you don't need anyway) is no  
longer part of the working draft.

For a quick unique_ptr tutorial, think of this as like auto_ptr except  
that you can supply a second templated de-allocator, just like  
containers and their allocators.  It has release() and get() just like  
auto_ptr.  It has unique ownership semantics just like auto_ptr.

-Howard




More information about the cfe-dev mailing list