For this code:
struct O { int &&j; }; O o1(0);
The generated AST for the initializer of o1 is:
VarDecl 0x62100006ab08 <array.cpp:119:3, col:9> col:5 o1 'O':'O' parenlistinit `-ExprWithCleanups 0x62100006b250 <col:7, col:9> 'O':'O' `-CXXParenListInitExpr 0x62100006b210 <col:7, col:9> 'O':'O' `-MaterializeTemporaryExpr 0x62100006b1f0 <col:8> 'int' xvalue `-IntegerLiteral 0x62100006abd0 <col:8> 'int' 0
Before this patch, we create a local temporary variable for the MaterializeTemporaryExpr and destroy it again when destroying the EvalEmitter we create to interpret the initializer. However, since O::j is a reference, this reference now points to a local variable that doesn't exist anymore.
I've run into this issue a few times before but always postponed working on it. Does this make sense? The only downside I see is that we might be creating more global variables.
Should we be looking at the TLS kind of the extended declaration? (CheckCompleteVariableDeclaration() is using VarDecl::getTLSKind() == VarDecl::TLS_Static)
Would something along these lines work instead?