Index: clang/lib/AST/Interp/ByteCodeExprGen.h =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.h +++ clang/lib/AST/Interp/ByteCodeExprGen.h @@ -196,6 +196,10 @@ return this->emitPopPtr(I); } + using ExprVisitorFunc = std::function; + bool visitConditional(const AbstractConditionalOperator *E, + ExprVisitorFunc VisitFunc); + /// Creates a local primitive value. unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsMutable, bool IsExtended = false); Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -589,32 +589,8 @@ template bool ByteCodeExprGen::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; + return this->visitConditional( + E, [&](const Expr *Ex) { return this->visit(Ex); }); } template @@ -930,6 +906,39 @@ } } +template +bool ByteCodeExprGen::visitConditional( + const AbstractConditionalOperator *E, ExprVisitorFunc VisitFunc) { + + 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. + + Condition->dump(); + if (!this->visit(Condition)) + return false; + if (!this->jumpFalse(LabelFalse)) + return false; + + if (!VisitFunc(TrueExpr)) + return false; + if (!this->jump(LabelEnd)) + return false; + + this->emitLabel(LabelFalse); + + if (!VisitFunc(FalseExpr)) + return false; + + this->fallthrough(LabelEnd); + this->emitLabel(LabelEnd); + + return true; +} + template bool ByteCodeExprGen::visitZeroInitializer(PrimType T, const Expr *E) { switch (T) { @@ -1420,6 +1429,10 @@ return this->visitInitializer(CE->getSubExpr()); } else if (const auto *CE = dyn_cast(Initializer)) { return this->visitInitializer(CE->getSubExpr()); + } else if (const auto *ACO = + dyn_cast(Initializer)) { + return this->visitConditional( + ACO, [&](const Expr *Ex) { return this->visitRecordInitializer(Ex); }); } // Explictly reject these. They only get generated for invalid code. Index: clang/test/AST/Interp/records.cpp =================================================================== --- clang/test/AST/Interp/records.cpp +++ clang/test/AST/Interp/records.cpp @@ -335,3 +335,14 @@ constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); }; + +namespace ConditionalInit { + struct S { int a; }; + + constexpr S getS(bool b) { + return b ? S{12} : S{13}; + } + + static_assert(getS(true).a == 12, ""); + static_assert(getS(false).a == 13, ""); +};