[cfe-dev] injecting a member function

Eric Niebler eric at boostpro.com
Fri Feb 18 00:25:11 PST 2011

On 2/18/2011 2:58 PM, John McCall wrote:
> On Feb 17, 2011, at 11:16 PM, Eric Niebler wrote:
>> For my work on MS and Borland properties, I need to be able transform
>> post-inc and post-dec expressions like "obj.prop++" into some equivalent
>> expression that uses getter and setter methods. (Prefix ops are simple
>> because they don't require the creation of a temporary to store the
>> result of the expression.)
>> I'm thinking of approaching the problem like this: "obj.prop++" is
>> replaced with "obj.__builtin_postinc_Obj_Prop()", where that member is
>> generated on-demand and injected in the Obj class. The member would
>> essentially be:
>>  PropTy Obj::__builtin_postinc_Obj_Prop() {
>>    PropTy tmp = this->getProp();
>>    this->setProp(tmp + 1);
>>    return tmp;
>>  }
>> Two questions:
>> 1) Is this the correct approach? Or is there a simpler/easier way?
>> 2) Is there any precedent in clang for this? I'm looking for code I can
>> crib from, or routines I could reuse.
> I think you want to make some sort of PropertyAccessOperator
> expression.  It would work basically like BinaryConditionalOperator

Thanks, John. Do you mean "ConditionalOperator" (which is ternary)?

> does, which is to say, it would bind the result of an expression
> (the base of the property) to an OpaqueValueExpr, then perform
> an arbitrary expression using that.  For source fidelity, it would also
> preserve the original member expression (and RHS, where applicable).

Regarding that, we abandoned our earlier plan to save original
expressions directly in the AST via a RewrittenExpr node. It broke to
much code that was explicitly testing nodes for their StmtClass.
Instead, the AST contains the rewritten expression, and the original
expression is stored in a map in the ASTContext, where it's available to
anybody who's interested. (The mapping is preserved by the AST
serialization code.)

For performance sake, we added a bit to Expr to note that a given node
was the result of a rewrite and that the original expression can be
found elsewhere.

> As a more concrete example, "obj.prop++" would look something like this:
>   (PropertyAccessOperator int
>     # The original operand, for source fidelity
>     (MemberExpr int lvalue property
>       (DeclRefExpr "obj" Obj lvalue))
>     # The opaque value expression
>     (OpaqueValueExpr 0xabcdef Obj lvalue)

I'm not 100% clear what the purpose of this OpaqueValueExpr is, but
maybe it will become clear when I study the code. Is it a temporary that
is storing the result of obj.getProp()? Shouldn't that be represented in
the AST somehow?

>     # The expression whose result the OpaqueValueExpr will be bound to
>     (DeclRefExpr "obj" Obj lvalue)
>     # The expression to evaluate, expressed in terms of the OVE
>     (CXXMemberCallExpr void
>       (MemberExpr void(int) .setBase
>         (OpaqueValueExpr 0xabcdef Obj lvalue))
>       (CXXMemberCallExpr int
>         (MemberExpr PropTy() .getBase
>           (OpaqueValueExpr 0xabcdef Obj lvalue)))))

I don't yet have a mental model of what this AST represents. I'll go off
and study ConditionalOperator and maybe it'll become clear.

> Hmm.  Unfortunately, I'm not sure how to indicate what the result of the
> operation should be.

Heh, that's kinda the problem I'm trying to solve. :-P

Eric Niebler
BoostPro Computing

More information about the cfe-dev mailing list