[cfe-dev] A disappearing CXXBindTemporaryExpr.
Artem Dergachev via cfe-dev
cfe-dev at lists.llvm.org
Mon Mar 26 20:01:45 PDT 2018
Sorry, accidentally sent two concatenated emails. The corrected email
should be:
On 3/26/18 7:58 PM, Artem Dergachev wrote:
> I've a C++ AST question.
>
> I've got a piece of code that doesn't contain CXXBindTemporaryExpr in
> its AST, but would have contained it if only i explicitly unwrapped a
> template that contains it *or* changed a field visibility in a certain
> class from private to public. I want to understand if it's intentional
> and if so what's the language feature that provides such behavior. A
> few hours of debugging Sema didn't quite help me (but i'm not super
> good with it).
>
> The code looks like this and compiles under -std=c++14:
>
> ```
> class A {
> public:
> ~A();
> };
>
> class B {
> A a;
> };
>
> template <typename T> void foo(T) {
> B i;
> i = {};
> }
>
> int main() {
> foo(1);
> return 0;
> }
> ```
>
> AST for foo():
>
>
> ```
> |-FunctionTemplateDecl 0x7fd5a8800f50 <line:10:1, line:13:1>
> line:10:28 foo
> | |-TemplateTypeParmDecl 0x7fd5a8800ce8 <col:11, col:20> col:20
> referenced typename depth 0 index 0 T
> | |-FunctionDecl 0x7fd5a8800eb0 <col:23, line:13:1> line:10:28 foo
> 'void (T)'
> | | |-ParmVarDecl 0x7fd5a8800db0 <col:32> col:33 'T'
> | | `-CompoundStmt 0x7fd5a8801740 <col:35, line:13:1>
> | | |-DeclStmt 0x7fd5a8801320 <line:11:3, col:6>
> | | | `-VarDecl 0x7fd5a8800ff8 <col:3, col:5> col:5 referenced i 'B'
> callinit
> | | | `-CXXConstructExpr 0x7fd5a88012f0 <col:5> 'B' 'void ()
> noexcept'
> | | `-ExprWithCleanups 0x7fd5a8801728 <line:12:3, col:8> 'B' lvalue
> | | `-CXXOperatorCallExpr 0x7fd5a88016e0 <col:3, col:8> 'B' lvalue
> | | |-ImplicitCastExpr 0x7fd5a88016c8 <col:5> 'B &(*)(B &&)
> noexcept' <FunctionToPointerDecay>
> | | | `-DeclRefExpr 0x7fd5a8801648 <col:5> 'B &(B &&) noexcept'
> lvalue CXXMethod 0x7fd5a785de28 'operator=' 'B &(B &&) noexcept'
> | | |-DeclRefExpr 0x7fd5a8801338 <col:3> 'B' lvalue Var
> 0x7fd5a8800ff8 'i' 'B'
> | | `-MaterializeTemporaryExpr 0x7fd5a88015b0 <col:7, col:8> 'B'
> xvalue
> | | `-CXXBindTemporaryExpr 0x7fd5a8801590 <col:7, col:8> 'B'
> (CXXTemporary 0x7fd5a8801588)
> | | `-CXXConstructExpr 0x7fd5a8801558 <col:7, col:8> 'B'
> 'void () noexcept' list zeroing
> | `-FunctionDecl 0x7fd5a8801b10 <line:10:23, line:13:1> line:10:28
> used foo 'void (int)'
> | |-TemplateArgument type 'int'
> | |-ParmVarDecl 0x7fd5a8801a08 <col:32> col:33 'int':'int'
> | `-CompoundStmt 0x7fd5a8802e28 <col:35, line:13:1>
> | |-DeclStmt 0x7fd5a88029f8 <line:11:3, col:6>
> | | `-VarDecl 0x7fd5a8802958 <col:3, col:5> col:5 used i 'B' callinit
> | | `-CXXConstructExpr 0x7fd5a88029b8 <col:5> 'B' 'void ()
> noexcept'
> | `-ExprWithCleanups 0x7fd5a8802e10 <line:12:3, col:8> 'B' lvalue
> | `-CXXOperatorCallExpr 0x7fd5a8802dc8 <col:3, col:8> 'B' lvalue
> | |-ImplicitCastExpr 0x7fd5a8802db0 <col:5> 'B &(*)(B &&)
> noexcept' <FunctionToPointerDecay>
> | | `-DeclRefExpr 0x7fd5a8802d88 <col:5> 'B &(B &&) noexcept'
> lvalue CXXMethod 0x7fd5a785de28 'operator=' 'B &(B &&) noexcept'
> | |-DeclRefExpr 0x7fd5a8802d48 <col:3> 'B' lvalue Var
> 0x7fd5a8802958 'i' 'B'
> | `-MaterializeTemporaryExpr 0x7fd5a8802d70 <col:7, col:8> 'B'
> xvalue
> | `-CXXConstructExpr 0x7fd5a8801558 <col:7, col:8> 'B' 'void
> () noexcept' list zeroing
> ```
>
> As you see, there's a CXXBindTemporaryExpr in the template, but it's
> not there in the instantiation. I expected the CXXBindTemporaryExpr to
> be there whenever the object has a non-trivial destructor, but in this
> case it's suddenly missing.
>
> However, if i replace "template <typename T> void foo(T)" with "void
> foo(int)" (to which it should resolve anyway), CXXBindTemporaryExpr
> would be present.
>
> Moreover, if instead of unrolling the template i simply add "public:"
> before "A a;", the mysterious CXXBindTemporaryExpr would also be present.
>
> WHY :)
More information about the cfe-dev
mailing list