[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