Skip to content

Commit 397a686

Browse files
committed
Fix assertion failure when constant evaluation of a switch jumps over an
uninitialized variable in an init-statement of a 'for' or 'if'. llvm-svn: 372437
1 parent 48b4083 commit 397a686

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4131,6 +4131,21 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
41314131
// preceded by our switch label.
41324132
BlockScopeRAII Scope(Info);
41334133

4134+
// Step into the init statement in case it brings an (uninitialized)
4135+
// variable into scope.
4136+
if (const Stmt *Init = IS->getInit()) {
4137+
EvalStmtResult ESR = EvaluateStmt(Result, Info, Init, Case);
4138+
if (ESR != ESR_CaseNotFound) {
4139+
assert(ESR != ESR_Succeeded);
4140+
return ESR;
4141+
}
4142+
}
4143+
4144+
// Condition variable must be initialized if it exists.
4145+
// FIXME: We can skip evaluating the body if there's a condition
4146+
// variable, as there can't be any case labels within it.
4147+
// (The same is true for 'for' statements.)
4148+
41344149
EvalStmtResult ESR = EvaluateStmt(Result, Info, IS->getThen(), Case);
41354150
if (ESR != ESR_CaseNotFound || !IS->getElse())
41364151
return ESR;
@@ -4147,6 +4162,18 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
41474162

41484163
case Stmt::ForStmtClass: {
41494164
const ForStmt *FS = cast<ForStmt>(S);
4165+
BlockScopeRAII Scope(Info);
4166+
4167+
// Step into the init statement in case it brings an (uninitialized)
4168+
// variable into scope.
4169+
if (const Stmt *Init = FS->getInit()) {
4170+
EvalStmtResult ESR = EvaluateStmt(Result, Info, Init, Case);
4171+
if (ESR != ESR_CaseNotFound) {
4172+
assert(ESR != ESR_Succeeded);
4173+
return ESR;
4174+
}
4175+
}
4176+
41504177
EvalStmtResult ESR =
41514178
EvaluateLoopBody(Result, Info, FS->getBody(), Case);
41524179
if (ESR != ESR_Continue)

clang/test/SemaCXX/constant-expression-cxx2a.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,4 +620,17 @@ namespace Uninit {
620620
constexpr int s1 = switch_var(1);
621621
constexpr int s2 = switch_var(2);
622622
static_assert(s1 == 1 && s2 == 2);
623+
624+
constexpr bool switch_into_init_stmt() {
625+
switch (1) {
626+
if (int n; false) {
627+
for (int m; false;) {
628+
case 1:
629+
n = m = 1;
630+
return n == 1 && m == 1;
631+
}
632+
}
633+
}
634+
}
635+
static_assert(switch_into_init_stmt());
623636
}

0 commit comments

Comments
 (0)