[cfe-dev] Constructors vs Copy Constructors in Clang

Douglas Gregor dgregor at apple.com
Fri Sep 17 11:36:30 PDT 2010


On Sep 17, 2010, at 10:22 AM, Jim Goodnow II wrote:

> At 08:04 AM 9/17/2010, Douglas Gregor wrote:
> 
>> On Sep 17, 2010, at 2:30 AM, Jim Goodnow II wrote:
>> 
>> > Hi,
>> >
>> > One of the things that I'm seeing in several places is where
>> > VarDecl::getInit() is returning an Expr that is CXXConstructExpr when
>> > a class variable is declared. However, the logic that follows the
>> > getInit() call usually assumes that if a non-NULL value is returned,
>> > there is a value being assigned. In the case of a constructor, that's
>> > sort of true but not completely unless it is a copy constructor.
>> 
>> It need not always be a copy constructor. Any constructor could occur there. A CXXConstructExpr occurs anywhere that we're performing initialization by constructor.
> 
> Yes, I am aware of that. The problem is distinguishing between:
> 
> foo f;
> foo f1 = f;
> 
> Both declarations will return a CXXConstructExpr from getInit(), but the code I am finding is assuming that there is an assignment happening which is not the case in the first declaration

The AST for the first will be a CXXConstructExpr that calls the default constructor.
The AST for the second will be a CXXConstructExpr calls the copy constructor, with f as its argument.

>> > So,
>> > a question of philosophy:
>> >
>> > Should getInit() return NULL when the constructor is not a copy
>> > constructor to support the logic in most cases? This might break or
>> > require a rework of things that do handle getInit() correctly like
>> > CodeGen and require a different call to get a non-copy constructor initializer.
>> >
>> > Or should the calls to getInit() be qualified by an additional call
>> > to an 'isCopyConstructor()' function where appropriate?
>> 
>> 
>> Why do you consider copy constructors to be special? They are elidable in some cases (and CXXConstructExpr tells us when the construction can be elided), but they aren't the only kinds of constructors that are elidable (C++0x allows move constructors to be elided, too). Static analysis need not treat them as special, unless for some reason that improves results.
>> 
>>        - Doug
> 
> Again, I'm looking at code in the static analyzer and other places that is assuming an assignment is taking place because getInit() is not returning a NULL. My question is how to distinguish between the two examples I gave before? One way is to check the result for a constructor and then look at the constructor and see if it is a copy constructor or not. So,
> 
> if (Expr *Init = D->getInit()) {
> 
> becomes
> 
> Expr *Init = D->getInit();
> if (Init && (!isa<CXXConstructExpr>(Init) ||
>                    dyn_cast<CXXConstructExpr>(Init)->getConstructor()->isCopyConstructor())) {


Why are you trying to treat the copy constructor as special here? In both cases the static analyzer needs to model a call to the constructor. If you're planning to treat a call to the copy constructor as a "copy" (in some semantic sense), then you'll want to recognize any CXXConstructExpr/CXXTemporaryObjectExpr expressions that calls the copy constructor as being a "copy", not just ones that show up when initializing variables.

	- Doug



More information about the cfe-dev mailing list