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' 0Before 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?
bool EmitGlobalTemp = E->getStorageDuration() == SD_Static; if (!EmitGlobalTemp) { if (const LifetimeExtendedTemporaryDecl *LETD = E->getLifetimeExtendedTemporaryDecl()) { if (const auto *VD = dyn_cast_if_present<VarDecl>(LETD->getExtendingDecl()) { EmitGlobalTemp= VD->getTLSKind() == VarDecl::TLS_Static; } } }