@@ -25,6 +25,16 @@ using APSInt = llvm::APSInt;
2525namespace clang {
2626namespace interp {
2727
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+
2838// / Scope used to handle temporaries in toplevel variable declarations.
2939template <class Emitter > class DeclScope final : public LocalScope<Emitter> {
3040public:
@@ -2286,39 +2296,49 @@ bool Compiler<Emitter>::VisitAbstractConditionalOperator(
22862296 const Expr *TrueExpr = E->getTrueExpr ();
22872297 const Expr *FalseExpr = E->getFalseExpr ();
22882298
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+
2312+ bool IsBcpCall = false ;
2313+ if (const auto *CE = dyn_cast<CallExpr>(Condition->IgnoreParenCasts ());
2314+ CE && CE->getBuiltinCallee () == Builtin::BI__builtin_constant_p) {
2315+ IsBcpCall = true ;
2316+ }
2317+
22892318 LabelTy LabelEnd = this ->getLabel (); // Label after the operator.
22902319 LabelTy LabelFalse = this ->getLabel (); // Label for the false expr.
22912320
2321+ if (IsBcpCall) {
2322+ if (!this ->emitStartSpeculation (E))
2323+ return false ;
2324+ }
2325+
22922326 if (!this ->visitBool (Condition))
22932327 return false ;
2294-
22952328 if (!this ->jumpFalse (LabelFalse))
22962329 return false ;
2297-
2298- {
2299- LocalScope<Emitter> S (this );
2300- if (!this ->delegate (TrueExpr))
2301- return false ;
2302- if (!S.destroyLocals ())
2303- return false ;
2304- }
2305-
2330+ if (!visitChildExpr (TrueExpr))
2331+ return false ;
23062332 if (!this ->jump (LabelEnd))
23072333 return false ;
2308-
23092334 this ->emitLabel (LabelFalse);
2310-
2311- {
2312- LocalScope<Emitter> S (this );
2313- if (!this ->delegate (FalseExpr))
2314- return false ;
2315- if (!S.destroyLocals ())
2316- return false ;
2317- }
2318-
2335+ if (!visitChildExpr (FalseExpr))
2336+ return false ;
23192337 this ->fallthrough (LabelEnd);
23202338 this ->emitLabel (LabelEnd);
23212339
2340+ if (IsBcpCall)
2341+ return this ->emitEndSpeculation (E);
23222342 return true ;
23232343}
23242344
@@ -4681,6 +4701,28 @@ bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
46814701template <class Emitter >
46824702bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
46834703 unsigned BuiltinID) {
4704+
4705+ if (BuiltinID == Builtin::BI__builtin_constant_p) {
4706+ // Void argument is always invalid and harder to handle later.
4707+ if (E->getArg (0 )->getType ()->isVoidType ()) {
4708+ if (DiscardResult)
4709+ return true ;
4710+ return this ->emitConst (0 , E);
4711+ }
4712+
4713+ if (!this ->emitStartSpeculation (E))
4714+ return false ;
4715+ LabelTy EndLabel = this ->getLabel ();
4716+ if (!this ->speculate (E, EndLabel))
4717+ return false ;
4718+ this ->fallthrough (EndLabel);
4719+ if (!this ->emitEndSpeculation (E))
4720+ return false ;
4721+ if (DiscardResult)
4722+ return this ->emitPop (classifyPrim (E), E);
4723+ return true ;
4724+ }
4725+
46844726 const Function *Func = getFunction (E->getDirectCallee ());
46854727 if (!Func)
46864728 return false ;
@@ -5185,11 +5227,8 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
51855227 // stataically known to be either true or false. We could look at more cases
51865228 // here, but I think all the ones that actually happen are using a
51875229 // ConstantExpr.
5188- if (const auto *CE = dyn_cast_if_present<ConstantExpr>(IS->getCond ());
5189- CE && CE->hasAPValueResult () &&
5190- CE->getResultAPValueKind () == APValue::ValueKind::Int) {
5191- APSInt Value = CE->getResultAsAPSInt ();
5192- if (Value.getBoolValue ())
5230+ if (std::optional<bool > BoolValue = getBoolValue (IS->getCond ())) {
5231+ if (*BoolValue)
51935232 return visitChildStmt (IS->getThen ());
51945233 else if (const Stmt *Else = IS->getElse ())
51955234 return visitChildStmt (Else);
0 commit comments