<div dir="ltr">Looks like a bug to me, probably template instantiation for the initializer is stripping this node out and we're failing to recreate it when redoing the initialization in the instantiation.<div><br></div><div>But I wonder whether we should just ditch the CXXBindTemporaryExpr node entirely. The purpose of marking where a temporary is created that needs a cleanup is handled much better by looking for CXXMaterializeTemporaryExprs (since they also track whether the temporary was lifetime-extended), and it doesn't seem like an imposition to ask clients to work out for themselves whether the type of the temporary needs destruction.</div><div><br></div><div>This would require us to start creating CXXMaterializeTemporaryExprs in C++98 for cases like "A().n", where we currently avoid doing so because the language rules say that expression is an rvalue, which in turn means (carefully) extending the C++11 xvalue rules to C++98 mode. But that seems feasible -- the hardest part is likely going to be avoiding using the term "xvalue" in C++98 diagnostics :)<br><div class="gmail_extra"><br><div class="gmail_quote">On 27 March 2018 at 13:43, Artem Dergachev via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hmm, i understand why field 'a' being public is relevant. That's because it turns B into an aggregate.<br>
<br>
But i still don't understand why templating/un-templating foo() makes a difference.<div class="HOEnZb"><div class="h5"><br>
<br>
On 3/26/18 8:01 PM, Artem Dergachev wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Sorry, accidentally sent two concatenated emails. The corrected email should be:<br>
<br>
On 3/26/18 7:58 PM, Artem Dergachev wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I've a C++ AST question.<br>
<br>
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).<br>
<br>
The code looks like this and compiles under -std=c++14:<br>
<br>
```<br>
class A {<br>
public:<br>
  ~A();<br>
};<br>
<br>
class B {<br>
  A a;<br>
};<br>
<br>
template <typename T> void foo(T) {<br>
  B i;<br>
  i = {};<br>
}<br>
<br>
int main() {<br>
  foo(1);<br>
  return 0;<br>
}<br>
```<br>
<br>
AST for foo():<br>
<br>
<br>
```<br>
|-FunctionTemplateDecl 0x7fd5a8800f50 <line:10:1, line:13:1> line:10:28 foo<br>
| |-TemplateTypeParmDecl 0x7fd5a8800ce8 <col:11, col:20> col:20 referenced typename depth 0 index 0 T<br>
| |-FunctionDecl 0x7fd5a8800eb0 <col:23, line:13:1> line:10:28 foo 'void (T)'<br>
| | |-ParmVarDecl 0x7fd5a8800db0 <col:32> col:33 'T'<br>
| | `-CompoundStmt 0x7fd5a8801740 <col:35, line:13:1><br>
| |   |-DeclStmt 0x7fd5a8801320 <line:11:3, col:6><br>
| |   | `-VarDecl 0x7fd5a8800ff8 <col:3, col:5> col:5 referenced i 'B' callinit<br>
| |   |   `-CXXConstructExpr 0x7fd5a88012f0 <col:5> 'B' 'void () noexcept'<br>
| |   `-ExprWithCleanups 0x7fd5a8801728 <line:12:3, col:8> 'B' lvalue<br>
| |     `-CXXOperatorCallExpr 0x7fd5a88016e0 <col:3, col:8> 'B' lvalue<br>
| |       |-ImplicitCastExpr 0x7fd5a88016c8 <col:5> 'B &(*)(B &&) noexcept' <FunctionToPointerDecay><br>
| |       | `-DeclRefExpr 0x7fd5a8801648 <col:5> 'B &(B &&) noexcept' lvalue CXXMethod 0x7fd5a785de28 'operator=' 'B &(B &&) noexcept'<br>
| |       |-DeclRefExpr 0x7fd5a8801338 <col:3> 'B' lvalue Var 0x7fd5a8800ff8 'i' 'B'<br>
| |       `-MaterializeTemporaryExpr 0x7fd5a88015b0 <col:7, col:8> 'B' xvalue<br>
| |         `-CXXBindTemporaryExpr 0x7fd5a8801590 <col:7, col:8> 'B' (CXXTemporary 0x7fd5a8801588)<br>
| |           `-CXXConstructExpr 0x7fd5a8801558 <col:7, col:8> 'B' 'void () noexcept' list zeroing<br>
| `-FunctionDecl 0x7fd5a8801b10 <line:10:23, line:13:1> line:10:28 used foo 'void (int)'<br>
|   |-TemplateArgument type 'int'<br>
|   |-ParmVarDecl 0x7fd5a8801a08 <col:32> col:33 'int':'int'<br>
|   `-CompoundStmt 0x7fd5a8802e28 <col:35, line:13:1><br>
|     |-DeclStmt 0x7fd5a88029f8 <line:11:3, col:6><br>
|     | `-VarDecl 0x7fd5a8802958 <col:3, col:5> col:5 used i 'B' callinit<br>
|     |   `-CXXConstructExpr 0x7fd5a88029b8 <col:5> 'B' 'void () noexcept'<br>
|     `-ExprWithCleanups 0x7fd5a8802e10 <line:12:3, col:8> 'B' lvalue<br>
|       `-CXXOperatorCallExpr 0x7fd5a8802dc8 <col:3, col:8> 'B' lvalue<br>
|         |-ImplicitCastExpr 0x7fd5a8802db0 <col:5> 'B &(*)(B &&) noexcept' <FunctionToPointerDecay><br>
|         | `-DeclRefExpr 0x7fd5a8802d88 <col:5> 'B &(B &&) noexcept' lvalue CXXMethod 0x7fd5a785de28 'operator=' 'B &(B &&) noexcept'<br>
|         |-DeclRefExpr 0x7fd5a8802d48 <col:3> 'B' lvalue Var 0x7fd5a8802958 'i' 'B'<br>
|         `-MaterializeTemporaryExpr 0x7fd5a8802d70 <col:7, col:8> 'B' xvalue<br>
|           `-CXXConstructExpr 0x7fd5a8801558 <col:7, col:8> 'B' 'void () noexcept' list zeroing<br>
```<br>
<br>
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.<br>
<br>
However, if i replace "template <typename T> void foo(T)" with "void foo(int)" (to which it should resolve anyway), CXXBindTemporaryExpr would be present.<br>
<br>
Moreover, if instead of unrolling the template i simply add "public:" before "A a;", the mysterious CXXBindTemporaryExpr would also be present.<br>
<br>
WHY :)<br>
</blockquote>
<br>
</blockquote>
<br>
______________________________<wbr>_________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a><br>
</div></div></blockquote></div><br></div></div></div>