[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