This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rGd2ea8ae5d43e: [clang][Interp] Implement logical and/or operators (authored by tbaeder).
Changed prior to commit: https://reviews.llvm.org/D140809?vs=485784&id=492323#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D140809/new/ https://reviews.llvm.org/D140809 Files: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeExprGen.h clang/test/AST/Interp/cond.cpp
Index: clang/test/AST/Interp/cond.cpp =================================================================== --- clang/test/AST/Interp/cond.cpp +++ clang/test/AST/Interp/cond.cpp @@ -9,3 +9,29 @@ return a - b; } } + +constexpr int dontCallMe(unsigned m) { + if (m == 0) return 0; + return dontCallMe(m - 2); +} + +// Can't call this because it will run into infinite recursion. +constexpr int assertNotReached() { + return dontCallMe(3); +} + +static_assert(true || true, ""); +static_assert(true || false, ""); +static_assert(false || true, ""); +static_assert(!(false || false), ""); + +static_assert(true || assertNotReached(), ""); +static_assert(true || true || true || false, ""); + +static_assert(true && true, ""); +static_assert(!(true && false), ""); +static_assert(!(false && true), ""); +static_assert(!(false && false), ""); + +static_assert(!(false && assertNotReached()), ""); +static_assert(!(true && true && true && false), ""); Index: clang/lib/AST/Interp/ByteCodeExprGen.h =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.h +++ clang/lib/AST/Interp/ByteCodeExprGen.h @@ -61,6 +61,7 @@ bool VisitFloatingLiteral(const FloatingLiteral *E); bool VisitParenExpr(const ParenExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); + bool VisitLogicalBinOp(const BinaryOperator *E); bool VisitPointerArithBinOp(const BinaryOperator *E); bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E); bool VisitCallExpr(const CallExpr *E); Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -187,6 +187,10 @@ template <class Emitter> bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) { + // Need short-circuiting for these. + if (BO->isLogicalOp()) + return this->VisitLogicalBinOp(BO); + const Expr *LHS = BO->getLHS(); const Expr *RHS = BO->getRHS(); @@ -270,8 +274,9 @@ return Discard(this->emitShr(*LT, *RT, BO)); case BO_Xor: return Discard(this->emitBitXor(*T, BO)); - case BO_LAnd: case BO_LOr: + case BO_LAnd: + llvm_unreachable("Already handled earlier"); default: return this->bail(BO); } @@ -329,6 +334,65 @@ return this->bail(E); } +template <class Emitter> +bool ByteCodeExprGen<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) { + assert(E->isLogicalOp()); + BinaryOperatorKind Op = E->getOpcode(); + const Expr *LHS = E->getLHS(); + const Expr *RHS = E->getRHS(); + + if (Op == BO_LOr) { + // Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE. + LabelTy LabelTrue = this->getLabel(); + LabelTy LabelEnd = this->getLabel(); + + if (!this->visit(LHS)) + return false; + if (!this->jumpTrue(LabelTrue)) + return false; + + if (!this->visit(RHS)) + return false; + if (!this->jump(LabelEnd)) + return false; + + this->emitLabel(LabelTrue); + this->emitConstBool(true, E); + this->fallthrough(LabelEnd); + this->emitLabel(LabelEnd); + + if (DiscardResult) + return this->emitPopBool(E); + + return true; + } + + // Logical AND. + // Visit LHS. Only visit RHS if LHS was TRUE. + LabelTy LabelFalse = this->getLabel(); + LabelTy LabelEnd = this->getLabel(); + + if (!this->visit(LHS)) + return false; + if (!this->jumpFalse(LabelFalse)) + return false; + + if (!this->visit(RHS)) + return false; + if (!this->jump(LabelEnd)) + return false; + + this->emitLabel(LabelFalse); + this->emitConstBool(false, E); + this->fallthrough(LabelEnd); + this->emitLabel(LabelEnd); + + if (DiscardResult) + return this->emitPopBool(E); + + return true; +} + template <class Emitter> bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { std::optional<PrimType> T = classify(E);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits