Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 29 additions & 19 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ using APSInt = llvm::APSInt;
namespace clang {
namespace interp {

static std::optional<bool> getBoolValue(const Expr *E) {
if (const auto *CE = dyn_cast_if_present<ConstantExpr>(E);
CE && CE->hasAPValueResult() &&
CE->getResultAPValueKind() == APValue::ValueKind::Int) {
return CE->getResultAsAPSInt().getBoolValue();
}

return std::nullopt;
}

/// Scope used to handle temporaries in toplevel variable declarations.
template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
public:
Expand Down Expand Up @@ -2286,6 +2296,19 @@ bool Compiler<Emitter>::VisitAbstractConditionalOperator(
const Expr *TrueExpr = E->getTrueExpr();
const Expr *FalseExpr = E->getFalseExpr();

auto visitChildExpr = [&](const Expr *E) -> bool {
LocalScope<Emitter> S(this);
if (!this->delegate(E))
return false;
return S.destroyLocals();
};

if (std::optional<bool> BoolValue = getBoolValue(Condition)) {
if (BoolValue)
return visitChildExpr(TrueExpr);
return visitChildExpr(FalseExpr);
}

LabelTy LabelEnd = this->getLabel(); // Label after the operator.
LabelTy LabelFalse = this->getLabel(); // Label for the false expr.

Expand All @@ -2295,26 +2318,16 @@ bool Compiler<Emitter>::VisitAbstractConditionalOperator(
if (!this->jumpFalse(LabelFalse))
return false;

{
LocalScope<Emitter> S(this);
if (!this->delegate(TrueExpr))
return false;
if (!S.destroyLocals())
return false;
}
if (!visitChildExpr(TrueExpr))
return false;

if (!this->jump(LabelEnd))
return false;

this->emitLabel(LabelFalse);

{
LocalScope<Emitter> S(this);
if (!this->delegate(FalseExpr))
return false;
if (!S.destroyLocals())
return false;
}
if (!visitChildExpr(FalseExpr))
return false;

this->fallthrough(LabelEnd);
this->emitLabel(LabelEnd);
Expand Down Expand Up @@ -5207,11 +5220,8 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
// stataically known to be either true or false. We could look at more cases
// here, but I think all the ones that actually happen are using a
// ConstantExpr.
if (const auto *CE = dyn_cast_if_present<ConstantExpr>(IS->getCond());
CE && CE->hasAPValueResult() &&
CE->getResultAPValueKind() == APValue::ValueKind::Int) {
APSInt Value = CE->getResultAsAPSInt();
if (Value.getBoolValue())
if (std::optional<bool> BoolValue = getBoolValue(IS->getCond())) {
if (*BoolValue)
return visitChildStmt(IS->getThen());
else if (const Stmt *Else = IS->getElse())
return visitChildStmt(Else);
Expand Down