Skip to content

Commit 5a0c30f

Browse files
committed
Handle returning from an expansion properly in constant evaluation
1 parent b188e7c commit 5a0c30f

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5956,19 +5956,24 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
59565956

59575957
// No need to push an extra scope for these since they're already
59585958
// CompoundStmts.
5959+
EvalStmtResult ESR = ESR_Succeeded;
59595960
for (const Stmt *Instantiation : Expansion->getInstantiations()) {
5960-
EvalStmtResult ESR = EvaluateStmt(Result, Info, Instantiation);
5961+
ESR = EvaluateStmt(Result, Info, Instantiation);
59615962
if (ESR == ESR_Failed ||
59625963
ShouldPropagateBreakContinue(Info, Expansion, &Scope, ESR))
59635964
return ESR;
59645965
if (ESR != ESR_Continue) {
59655966
// Succeeded here actually means we encountered a 'break'.
5966-
assert(ESR == ESR_Succeeded);
5967+
assert(ESR == ESR_Succeeded || ESR == ESR_Returned);
59675968
break;
59685969
}
59695970
}
59705971

5971-
return Scope.destroy() ? ESR_Succeeded : ESR_Failed;
5972+
// Map Continue back to Succeeded if we fell off the end of the loop.
5973+
if (ESR == ESR_Continue)
5974+
ESR = ESR_Succeeded;
5975+
5976+
return Scope.destroy() ? ESR : ESR_Failed;
59725977
}
59735978

59745979
case Stmt::SwitchStmtClass:

clang/test/SemaCXX/cxx2c-expansion-statements.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -918,3 +918,24 @@ static_assert(lifetime_extension_instantiate_expansions<int>() == 47);
918918
static_assert(lifetime_extension_dependent_expansion_stmt<int>() == 47);
919919
static_assert(foo<int>().lifetime_extension_multiple_instantiations<int>() == 47);
920920
}
921+
922+
template <typename... Ts>
923+
constexpr int return_from_expansion(Ts... ts) {
924+
template for (int i : {1, 2, 3}) {
925+
return (ts + ...);
926+
}
927+
__builtin_unreachable();
928+
}
929+
930+
static_assert(return_from_expansion(4, 5, 6) == 15);
931+
932+
void not_constexpr();
933+
934+
constexpr int empty_expansion_consteval() {
935+
template for (auto _ : {}) {
936+
not_constexpr();
937+
}
938+
return 3;
939+
}
940+
941+
static_assert(empty_expansion_consteval() == 3);

0 commit comments

Comments
 (0)