tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafik.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Implement visiting `ConditionalOperator`s.

This also makes it possible to enable the first existing test case with the new 
constant interpreter. Although I'm not sure if I should actually do that, I 
quite enjoy just running `ninja check-clang-ast-interp` and run all the 
relevant tests in under 2 seconds.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134801

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

Index: clang/test/SemaCXX/constexpr-factorial.cpp
===================================================================
--- clang/test/SemaCXX/constexpr-factorial.cpp
+++ 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);
Index: clang/test/AST/Interp/literals.cpp
===================================================================
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -183,3 +183,51 @@
   constexpr long unsigned RHS = 3;
   static_assert(LHS / RHS == 4, "");
 };
+
+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, "");
+
+#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
+
+};
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -87,6 +87,7 @@
   bool VisitMemberExpr(const MemberExpr *E);
   bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E);
   bool VisitOpaqueValueExpr(const OpaqueValueExpr *E);
+  bool VisitConditionalOperator(const ConditionalOperator *E);
 
 protected:
   bool visitExpr(const Expr *E) override;
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -344,6 +344,37 @@
   return this->visit(E->getSourceExpr());
 }
 
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitConditionalOperator(
+    const ConditionalOperator *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);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to