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 +bool ByteCodeExprGen::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 bool ByteCodeExprGen::discard(const Expr *E) { OptionScope Scope(this, /*NewDiscardResult=*/true); return this->Visit(E); 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/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);