1616#include " PrimType.h"
1717#include " Program.h"
1818#include " clang/AST/Attr.h"
19+ #include " llvm/Support/SaveAndRestore.h"
1920
2021using namespace clang ;
2122using namespace clang ::interp;
@@ -2500,17 +2501,18 @@ bool Compiler<Emitter>::VisitAbstractConditionalOperator(
25002501 const Expr *TrueExpr = E->getTrueExpr ();
25012502 const Expr *FalseExpr = E->getFalseExpr ();
25022503
2503- auto visitChildExpr = [&](const Expr *E) -> bool {
2504- LocalScope<Emitter> S (this );
2505- if (!this ->delegate (E))
2506- return false ;
2507- return S.destroyLocals ();
2508- };
2504+ // The TrueExpr and FalseExpr of a conditional operator do _not_ create a
2505+ // scope, which means the local variables created within them unconditionally
2506+ // always exist. However, we need to later differentiate which branch was
2507+ // taken and only destroy the varibles of the active branch. This is what the
2508+ // "enabled" flags on local variables are used for.
2509+ llvm::SaveAndRestore LAAA (this ->VarScope ->LocalsAlwaysEnabled ,
2510+ /* NewValue=*/ false );
25092511
25102512 if (std::optional<bool > BoolValue = getBoolValue (Condition)) {
25112513 if (*BoolValue)
2512- return visitChildExpr (TrueExpr);
2513- return visitChildExpr (FalseExpr);
2514+ return this -> delegate (TrueExpr);
2515+ return this -> delegate (FalseExpr);
25142516 }
25152517
25162518 bool IsBcpCall = false ;
@@ -2542,13 +2544,15 @@ bool Compiler<Emitter>::VisitAbstractConditionalOperator(
25422544
25432545 if (!this ->jumpFalse (LabelFalse))
25442546 return false ;
2545- if (!visitChildExpr (TrueExpr))
2547+ if (!this -> delegate (TrueExpr))
25462548 return false ;
2549+
25472550 if (!this ->jump (LabelEnd))
25482551 return false ;
25492552 this ->emitLabel (LabelFalse);
2550- if (!visitChildExpr (FalseExpr))
2553+ if (!this -> delegate (FalseExpr))
25512554 return false ;
2555+
25522556 this ->fallthrough (LabelEnd);
25532557 this ->emitLabel (LabelEnd);
25542558
@@ -2955,10 +2959,15 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
29552959 bool IsVolatile = SubExpr->getType ().isVolatileQualified ();
29562960 unsigned LocalIndex = allocateLocalPrimitive (
29572961 E, *SubExprT, IsConst, IsVolatile, E->getExtendingDecl ());
2962+ if (!this ->VarScope ->LocalsAlwaysEnabled &&
2963+ !this ->emitEnableLocal (LocalIndex, E))
2964+ return false ;
2965+
29582966 if (!this ->visit (SubExpr))
29592967 return false ;
29602968 if (!this ->emitSetLocal (*SubExprT, LocalIndex, E))
29612969 return false ;
2970+
29622971 return this ->emitGetPtrLocal (LocalIndex, E);
29632972 }
29642973
@@ -2968,6 +2977,11 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
29682977 if (UnsignedOrNone LocalIndex =
29692978 allocateLocal (E, Inner->getType (), E->getExtendingDecl ())) {
29702979 InitLinkScope<Emitter> ILS (this , InitLink::Temp (*LocalIndex));
2980+
2981+ if (!this ->VarScope ->LocalsAlwaysEnabled &&
2982+ !this ->emitEnableLocal (*LocalIndex, E))
2983+ return false ;
2984+
29712985 if (!this ->emitGetPtrLocal (*LocalIndex, E))
29722986 return false ;
29732987 return this ->visitInitializer (SubExpr) && this ->emitFinishInit (E);
0 commit comments