forked from OSchip/llvm-project
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
This commit is contained in:
parent
48b40834dc
commit
397a686762
|
@ -4131,6 +4131,21 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
|
|||
// preceded by our switch label.
|
||||
BlockScopeRAII Scope(Info);
|
||||
|
||||
// Step into the init statement in case it brings an (uninitialized)
|
||||
// variable into scope.
|
||||
if (const Stmt *Init = IS->getInit()) {
|
||||
EvalStmtResult ESR = EvaluateStmt(Result, Info, Init, Case);
|
||||
if (ESR != ESR_CaseNotFound) {
|
||||
assert(ESR != ESR_Succeeded);
|
||||
return ESR;
|
||||
}
|
||||
}
|
||||
|
||||
// Condition variable must be initialized if it exists.
|
||||
// FIXME: We can skip evaluating the body if there's a condition
|
||||
// variable, as there can't be any case labels within it.
|
||||
// (The same is true for 'for' statements.)
|
||||
|
||||
EvalStmtResult ESR = EvaluateStmt(Result, Info, IS->getThen(), Case);
|
||||
if (ESR != ESR_CaseNotFound || !IS->getElse())
|
||||
return ESR;
|
||||
|
@ -4147,6 +4162,18 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
|
|||
|
||||
case Stmt::ForStmtClass: {
|
||||
const ForStmt *FS = cast<ForStmt>(S);
|
||||
BlockScopeRAII Scope(Info);
|
||||
|
||||
// Step into the init statement in case it brings an (uninitialized)
|
||||
// variable into scope.
|
||||
if (const Stmt *Init = FS->getInit()) {
|
||||
EvalStmtResult ESR = EvaluateStmt(Result, Info, Init, Case);
|
||||
if (ESR != ESR_CaseNotFound) {
|
||||
assert(ESR != ESR_Succeeded);
|
||||
return ESR;
|
||||
}
|
||||
}
|
||||
|
||||
EvalStmtResult ESR =
|
||||
EvaluateLoopBody(Result, Info, FS->getBody(), Case);
|
||||
if (ESR != ESR_Continue)
|
||||
|
|
|
@ -620,4 +620,17 @@ namespace Uninit {
|
|||
constexpr int s1 = switch_var(1);
|
||||
constexpr int s2 = switch_var(2);
|
||||
static_assert(s1 == 1 && s2 == 2);
|
||||
|
||||
constexpr bool switch_into_init_stmt() {
|
||||
switch (1) {
|
||||
if (int n; false) {
|
||||
for (int m; false;) {
|
||||
case 1:
|
||||
n = m = 1;
|
||||
return n == 1 && m == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static_assert(switch_into_init_stmt());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue