@@ -25,6 +25,16 @@ using APSInt = llvm::APSInt;
25
25
namespace clang {
26
26
namespace interp {
27
27
28
+ static std::optional<bool > getBoolValue (const Expr *E) {
29
+ if (const auto *CE = dyn_cast_if_present<ConstantExpr>(E);
30
+ CE && CE->hasAPValueResult () &&
31
+ CE->getResultAPValueKind () == APValue::ValueKind::Int) {
32
+ return CE->getResultAsAPSInt ().getBoolValue ();
33
+ }
34
+
35
+ return std::nullopt;
36
+ }
37
+
28
38
// / Scope used to handle temporaries in toplevel variable declarations.
29
39
template <class Emitter > class DeclScope final : public LocalScope<Emitter> {
30
40
public:
@@ -2286,6 +2296,19 @@ bool Compiler<Emitter>::VisitAbstractConditionalOperator(
2286
2296
const Expr *TrueExpr = E->getTrueExpr ();
2287
2297
const Expr *FalseExpr = E->getFalseExpr ();
2288
2298
2299
+ auto visitChildExpr = [&](const Expr *E) -> bool {
2300
+ LocalScope<Emitter> S (this );
2301
+ if (!this ->delegate (E))
2302
+ return false ;
2303
+ return S.destroyLocals ();
2304
+ };
2305
+
2306
+ if (std::optional<bool > BoolValue = getBoolValue (Condition)) {
2307
+ if (BoolValue)
2308
+ return visitChildExpr (TrueExpr);
2309
+ return visitChildExpr (FalseExpr);
2310
+ }
2311
+
2289
2312
LabelTy LabelEnd = this ->getLabel (); // Label after the operator.
2290
2313
LabelTy LabelFalse = this ->getLabel (); // Label for the false expr.
2291
2314
@@ -2295,26 +2318,16 @@ bool Compiler<Emitter>::VisitAbstractConditionalOperator(
2295
2318
if (!this ->jumpFalse (LabelFalse))
2296
2319
return false ;
2297
2320
2298
- {
2299
- LocalScope<Emitter> S (this );
2300
- if (!this ->delegate (TrueExpr))
2301
- return false ;
2302
- if (!S.destroyLocals ())
2303
- return false ;
2304
- }
2321
+ if (!visitChildExpr (TrueExpr))
2322
+ return false ;
2305
2323
2306
2324
if (!this ->jump (LabelEnd))
2307
2325
return false ;
2308
2326
2309
2327
this ->emitLabel (LabelFalse);
2310
2328
2311
- {
2312
- LocalScope<Emitter> S (this );
2313
- if (!this ->delegate (FalseExpr))
2314
- return false ;
2315
- if (!S.destroyLocals ())
2316
- return false ;
2317
- }
2329
+ if (!visitChildExpr (FalseExpr))
2330
+ return false ;
2318
2331
2319
2332
this ->fallthrough (LabelEnd);
2320
2333
this ->emitLabel (LabelEnd);
@@ -5207,11 +5220,8 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
5207
5220
// stataically known to be either true or false. We could look at more cases
5208
5221
// here, but I think all the ones that actually happen are using a
5209
5222
// ConstantExpr.
5210
- if (const auto *CE = dyn_cast_if_present<ConstantExpr>(IS->getCond ());
5211
- CE && CE->hasAPValueResult () &&
5212
- CE->getResultAPValueKind () == APValue::ValueKind::Int) {
5213
- APSInt Value = CE->getResultAsAPSInt ();
5214
- if (Value.getBoolValue ())
5223
+ if (std::optional<bool > BoolValue = getBoolValue (IS->getCond ())) {
5224
+ if (*BoolValue)
5215
5225
return visitChildStmt (IS->getThen ());
5216
5226
else if (const Stmt *Else = IS->getElse ())
5217
5227
return visitChildStmt (Else);
0 commit comments