Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [cdt-dev] bindings for CPPASTNewExpression

Resolving T in new T to a constructor is problematic. Consider the following example:

class A {
A() {}

typedef A B;

void foo(void* p);

void test() {
foo(new B);

Select "new B" and extract local variable. The result is:

void test() {
A* b = new B;

instead of expected

void test() {
B* b = new B;

Constructor call expressions without 'new' are handled better:

class A {
A() {}

typedef A B;

void foo(A p);

void test() {


void test() {
B b = B();

I think we should follow the option #1 despite of the fact that it may break some existing code that depends on resolving "new T" to a ctor call. Formally this is not an API change since IASTName.resolveBinding does not make a promise of what kind of binding the name resolves to.


On Mon, Jan 21, 2013 at 1:30 AM, Nathan Ridge <zeratul976@xxxxxxxxxxx> wrote:


A CPPASTNewExpression (an _expression_ of the form "new T" or "new T(args)"
or "new T{args}") currently has two bindings associated with it if T is
of class type:

1) The name "T" resolves to (via resolveBinding()) the constructor that
   is called in the _expression_. I'll refer to this as the "explicit

2) The CPPASTNewExpression is an IASTImplicitNameOwner, and it has an
   implicit name that also resolves to the constructor that is called
   in the _expression_. I'll refer to this as the "implicit binding".

It seems like unnecessary duplication to me to have the explicit binding
and the implicit binding be the same thing. What's worse is that the two
bindings don't always agree, because they are computed by two slightly
different pieces of code (the explicit binding is computed in
CPPSemantics.postResolution(), in the bit of code after the call to
convertClassToConstructor(); the implicit binding is computed in
CPPSemantics.findImplicitlyCalledConstructor()), even though they are
meant to refer to the same thing.

I would like to remove this duplication. I can see 3 possible ways to
do it:

1) Change the explicit binding to be the CPPClassType representing T,
   and only have the implicit binding be the constructor.

   This would be consistent with how we handle expressions of the form
   "T(args)" or "T{args}", without the "new" (see this [1] recent
   Unfortunately, a lot of tests rely on the explicit binding being
   the constructor. They would all have to be updated if we do this.

   Also, I wonder whether this would be considered a breaking API
   change, since we are changing the behaviour of the public API
   IASTName.resolveBinding() in some cases?

2) Keep the explicit binding as the constructor, and get rid of the
   implicit binding altogether.

   As far as I can see, the only thing that uses the implicit
   binding is some code in CPPVariableReadWriteFlags, which can
   easily be changed to use the explicit binding instead.

   The generation of the implicit binding was added recently (1
   month ago), so it hasn't appeared in a release, so removing it
   wouldn't be an API change.

3) Keep both bindings as the constructor, just refactor things
   so that the same code is used to find both.

   This would be appropriate if for some reason we need to keep
   both bindings and have both of them be the constructor.

Which approach do you think is best? I am happy to implement
any one of them.



cdt-dev mailing list

Back to the top