aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2025-03-08 18:29:19 +0100
committerGitHub <noreply@github.com>2025-03-08 18:29:19 +0100
commite4fe22a8bd1853331d4811546ac038252baee79d (patch)
tree2d4eb0a7884afe3fa8d99de87036cf13a23b25da
parenta22a646eaa33492cc3318aa44b433992741b1996 (diff)
downloadllvm-e4fe22a8bd1853331d4811546ac038252baee79d.zip
llvm-e4fe22a8bd1853331d4811546ac038252baee79d.tar.gz
llvm-e4fe22a8bd1853331d4811546ac038252baee79d.tar.bz2
[clang][bytecode][NFC] Check conditional op condition for ConstantExprs (#130425)
Same thing we now do in if statements. Check the condition of a conditional operator for a statically known true/false value.
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp48
1 files changed, 29 insertions, 19 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index d192b8b..9a52dd4 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -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:
@@ -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.
@@ -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);
@@ -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);