[clang] 77aaf46 - [clang][Interp] Implement ConditionalOperators

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 14 04:28:45 PDT 2022


Author: Timm Bäder
Date: 2022-10-14T13:16:10+02:00
New Revision: 77aaf469a7ae5af26a8fe92ed9d548404831d3ed

URL: https://github.com/llvm/llvm-project/commit/77aaf469a7ae5af26a8fe92ed9d548404831d3ed
DIFF: https://github.com/llvm/llvm-project/commit/77aaf469a7ae5af26a8fe92ed9d548404831d3ed.diff

LOG: [clang][Interp] Implement ConditionalOperators

Differential Revision: https://reviews.llvm.org/D134801

Added: 
    

Modified: 
    clang/lib/AST/Interp/ByteCodeExprGen.cpp
    clang/lib/AST/Interp/ByteCodeExprGen.h
    clang/test/AST/Interp/literals.cpp
    clang/test/SemaCXX/constexpr-factorial.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 107fd77c974d6..2a25380df6072 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -347,6 +347,37 @@ bool ByteCodeExprGen<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
   return this->visit(E->getSourceExpr());
 }
 
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitAbstractConditionalOperator(
+    const AbstractConditionalOperator *E) {
+  const Expr *Condition = E->getCond();
+  const Expr *TrueExpr = E->getTrueExpr();
+  const Expr *FalseExpr = E->getFalseExpr();
+
+  LabelTy LabelEnd = this->getLabel();   // Label after the operator.
+  LabelTy LabelFalse = this->getLabel(); // Label for the false expr.
+
+  if (!this->visit(Condition))
+    return false;
+  if (!this->jumpFalse(LabelFalse))
+    return false;
+
+  if (!this->visit(TrueExpr))
+    return false;
+  if (!this->jump(LabelEnd))
+    return false;
+
+  this->emitLabel(LabelFalse);
+
+  if (!this->visit(FalseExpr))
+    return false;
+
+  this->fallthrough(LabelEnd);
+  this->emitLabel(LabelEnd);
+
+  return true;
+}
+
 template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
   OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true);
   return this->Visit(E);

diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 32ff72aa36fb8..5e5bbbd6948aa 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -88,6 +88,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
   bool VisitMemberExpr(const MemberExpr *E);
   bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E);
   bool VisitOpaqueValueExpr(const OpaqueValueExpr *E);
+  bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E);
 
 protected:
   bool visitExpr(const Expr *E) override;

diff  --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index cc868266e4a28..f11107c0efb76 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -210,3 +210,54 @@ namespace div {
                                    // expected-note {{value 2147483648 is outside the range}} \
 
 };
+
+namespace cond {
+  constexpr bool isEven(int n) {
+    return n % 2 == 0 ? true : false;
+  }
+  static_assert(isEven(2), "");
+  static_assert(!isEven(3), "");
+  static_assert(isEven(100), "");
+
+  constexpr int M = 5 ? 10 : 20;
+  static_assert(M == 10, "");
+
+  static_assert(5 ? 13 : 16 == 13, "");
+  static_assert(0 ? 13 : 16 == 16, "");
+
+  static_assert(number ?: -15 == number, "");
+  static_assert(0 ?: 100 == 100 , "");
+
+#if __cplusplus >= 201402L
+  constexpr int N = 20;
+  constexpr int foo() {
+    int m = N > 0 ? 5 : 10;
+
+    return m == 5 ? isEven(m) : true;
+  }
+  static_assert(foo() == false, "");
+
+  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);
+  }
+
+  constexpr int testCond() {
+    return true ? 5 : assertNotReached();
+  }
+
+  constexpr int testCond2() {
+    return false ? assertNotReached() : 10;
+  }
+
+  static_assert(testCond() == 5, "");
+  static_assert(testCond2() == 10, "");
+
+#endif
+
+};

diff  --git a/clang/test/SemaCXX/constexpr-factorial.cpp b/clang/test/SemaCXX/constexpr-factorial.cpp
index b6cdde59d3fa2..3f9928bb20ea7 100644
--- a/clang/test/SemaCXX/constexpr-factorial.cpp
+++ b/clang/test/SemaCXX/constexpr-factorial.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fexperimental-new-constant-interpreter %s
 
 constexpr unsigned oddfac(unsigned n) {
   return n == 1 ? 1 : n * oddfac(n-2);


        


More information about the cfe-commits mailing list