diff options
author | John McCall <rjmccall@apple.com> | 2010-08-02 23:33:14 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-08-02 23:33:14 +0000 |
commit | 97ba481f3f45e5b63b4a354bfb471ce146b7de57 (patch) | |
tree | 9bc386dd915140e3b29a41c0eb564aa0c4fad60b /lib/Sema/JumpDiagnostics.cpp | |
parent | db9d2145f1d85f64dba2c9b92416621ce01090a6 (diff) |
Labels (and case statement) don't create independent scope parents for the
purposes of the jump checker. Also extend Ted's iteration fix to labels.
Fixes PR7789.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110082 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/JumpDiagnostics.cpp')
-rw-r--r-- | lib/Sema/JumpDiagnostics.cpp | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index f696d6acbf..866a358e13 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -180,22 +180,6 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { // If we found a label, remember that it is in ParentScope scope. switch (S->getStmtClass()) { - case Stmt::LabelStmtClass: - case Stmt::DefaultStmtClass: - LabelAndGotoScopes[S] = ParentScope; - break; - case Stmt::CaseStmtClass: { - // Specially handle CaseStmts since they can nest each other in the - // AST and blow out the stack when we walk them. - CaseStmt *CS = cast<CaseStmt>(S); - do { - LabelAndGotoScopes[CS] = ParentScope; - S = CS; // 'CS' is the new current statement (if it isn't already). - CS = dyn_cast<CaseStmt>(CS->getSubStmt()); - } while (CS); - break; - } - case Stmt::AddrLabelExprClass: IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel()); break; @@ -235,6 +219,24 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { Stmt *SubStmt = *CI; if (SubStmt == 0) continue; + // Cases, labels, and defaults aren't "scope parents". It's also + // important to handle these iteratively instead of recursively in + // order to avoid blowing out the stack. + while (true) { + Stmt *Next; + if (isa<CaseStmt>(SubStmt)) + Next = cast<CaseStmt>(SubStmt)->getSubStmt(); + else if (isa<DefaultStmt>(SubStmt)) + Next = cast<DefaultStmt>(SubStmt)->getSubStmt(); + else if (isa<LabelStmt>(SubStmt)) + Next = cast<LabelStmt>(SubStmt)->getSubStmt(); + else + break; + + LabelAndGotoScopes[SubStmt] = ParentScope; + SubStmt = Next; + } + // If this is a declstmt with a VLA definition, it defines a scope from here // to the end of the containing context. if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) { |