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

Enea Zaffanella zaffanella at cs.unipr.it
Sat Feb 27 00:06:06 PST 2010


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?

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 would be grateful if someone either confirm my doubts or show to me 
where is the gap in my reasoning.

Regards,
Enea Zaffanella.




More information about the cfe-dev mailing list