[cfe-dev] Doubts about constructor calls (and functional casts).

John McCall rjmccall at apple.com
Fri Mar 12 10:55:44 PST 2010


On Feb 27, 2010, at 12:06 AM, Enea Zaffanella wrote:

> Hello.
> 
> I am a bit confused regarding the AST that is generated by clang++ when 
> handling implicit/explicit calls to constructors. I would be grateful if 
> someone would clarify a few points by going through the following examples.
> 
> 
> Let us consider the following struct definition:
> ==============
> struct S {
>   S(int);
> };
> ==============
> which is dumped by clang++ as follows (no surprise here):
> ==============
> struct S {
> public:
>     struct S;
>     S(int);
>     inline S(struct S const &);
>     inline struct S &operator=(struct S const &);
>     inline void ~S();
> };
> =============
> 
> 
> If I construct an S object using direct initialization
>     S s1(1);
> I get the following (which is what I am expecting):
> =============
>   (DeclStmt 0x1d5eba0 <line:6:3, col:10>
>     0x1d5ea60 "struct S s1 =
>       (CXXConstructExpr 0x1d5eb30 <col:5, col:8> 'struct S''void (int)'
>         (IntegerLiteral 0x1d5eac0 <col:8> 'int' 1))"
> =============
> 
> 
> If I now try with this variant
>      S s2 = 2;
> I get the following ... again, this is more or less what I was expecting:
> =============
>   (DeclStmt 0x1d5f1c0 <line:7:3, col:11>
>     0x1d5f000 "struct S s2 =
>       (CXXConstructExpr 0x1d5f150 <col:5, col:10> 'struct S''void 
> (struct S const &)' elidable
>         (ImplicitCastExpr 0x1d5f110 <col:10> 'struct S' 
> <ConstructorConversion>
>           (CXXConstructExpr 0x1d5f0a0 <col:10> 'struct S''void (int)'
>             (IntegerLiteral 0x1d5f060 <col:10> 'int' 2))))"
> =============
> I guess that the implicit cast between the two constructor calls is 
> meant to convert the plain S type into a "const S&" type, so that it can 
> be passed as an argument to the (elidable) copy constructor.
> Am I correct?
> 
> 
> But then I get to the following case
>     S s3 = S(3);
> for which I get the following AST:
> =============
>   (DeclStmt 0x1d5f430 <line:8:3, col:14>
>     0x1d5f1f0 "struct S s3 =
>       (ImplicitCastExpr 0x1d5f3f0 <col:10, col:13> 'struct S' 
> <ConstructorConversion>
>         (CXXConstructExpr 0x1d5f380 <col:10, col:13> 'struct S''void 
> (struct S const &)' elidable
>           (ImplicitCastExpr 0x1d5f340 <col:10, col:13> 'struct S const' 
> <NoOp>
>             (CXXFunctionalCastExpr 0x1d5f300 <col:10, col:13> 'struct 
> S' functional cast to struct S
>               (CXXConstructExpr 0x1d5f290 <col:10, col:12> 'struct 
> S''void (int)'
>                 (IntegerLiteral 0x1d5f250 <col:12> 'int' 3))))))"
> =============
> 
> Here there are two things that I do not understand.
> 
> First, I cannot see why the result of the inner CXXConstructorExpr call 
> should be fed to a CXXFunctionalCastExpr. I may agree that the 
> initializer of s3 is a functional cast expression ... but then I would 
> expect that the argument of this functional cast is the integer literal, 
> not the struct S object returned by the constructor.
> In other words, to my eyes, the presence of the functional cast should 
> exclude the presence of the inner constructor call, or vice versa.
> Is my reasoning missing some important point?

This is a strange representation, and it looks even stranger when the functional cast is actually invoking a user-defined conversion.  CodeGen aggressively elides the constructor calls (in most cases; I don't enough about that corner of the standard to know if it's missing legal elisions), so it's just an internal-representation issue rather than also being a performance issue.  Still, it's not a good representation, and if the elision optimization is disabled (which is a supported configuration, I think) it might mean we make too many copies.

> Second, I cannot see why the result of the external (elidable) copy 
> constructor call is (again) implicitly cast before being used as an 
> initializer for s3. There seems to be no reason for such an implicit 
> cast and, as a matter of fact, such a cast was not used in the previous 
> example (when initializing s2).

I don't understand this either.

John.



More information about the cfe-dev mailing list