summaryrefslogtreecommitdiffstats
path: root/lib/Sema/JumpDiagnostics.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-08-02 23:33:14 +0000
committerJohn McCall <rjmccall@apple.com>2010-08-02 23:33:14 +0000
commit97ba481f3f45e5b63b4a354bfb471ce146b7de57 (patch)
tree9bc386dd915140e3b29a41c0eb564aa0c4fad60b /lib/Sema/JumpDiagnostics.cpp
parentdb9d2145f1d85f64dba2c9b92416621ce01090a6 (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.cpp34
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)) {