aboutsummaryrefslogtreecommitdiff
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
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
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--lib/Sema/JumpDiagnostics.cpp34
-rw-r--r--test/Sema/scope-check.c32
-rw-r--r--test/SemaCXX/scope-check.cpp18
4 files changed, 54 insertions, 34 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 283dab70dc..ef59f985db 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1855,9 +1855,9 @@ def warn_missing_braces : Warning<
def err_redefinition_of_label : Error<"redefinition of label '%0'">;
def err_undeclared_label_use : Error<"use of undeclared label '%0'">;
-def err_goto_into_protected_scope : Error<"illegal goto into protected scope">;
+def err_goto_into_protected_scope : Error<"goto into protected scope">;
def err_switch_into_protected_scope : Error<
- "illegal switch case into protected scope">;
+ "switch case is in protected scope">;
def err_indirect_goto_without_addrlabel : Error<
"indirect goto in function with no address-of-label expressions">;
def warn_indirect_goto_in_protected_scope : Warning<
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)) {
diff --git a/test/Sema/scope-check.c b/test/Sema/scope-check.c
index f3881ed086..4ccb64c9aa 100644
--- a/test/Sema/scope-check.c
+++ b/test/Sema/scope-check.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=gnu99 %s -Wno-unreachable-code
int test1(int x) {
- goto L; // expected-error{{illegal goto into protected scope}}
+ goto L; // expected-error{{goto into protected scope}}
int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
int b[x]; // expected-note {{jump bypasses initialization of variable length array}}
L:
@@ -9,7 +9,7 @@ int test1(int x) {
}
int test2(int x) {
- goto L; // expected-error{{illegal goto into protected scope}}
+ goto L; // expected-error{{goto into protected scope}}
typedef int a[x]; // expected-note {{jump bypasses initialization of VLA typedef}}
L:
return sizeof(a);
@@ -18,14 +18,14 @@ int test2(int x) {
void test3clean(int*);
int test3() {
- goto L; // expected-error{{illegal goto into protected scope}}
+ goto L; // expected-error{{goto into protected scope}}
int a __attribute((cleanup(test3clean))); // expected-note {{jump bypasses initialization of variable with __attribute__((cleanup))}}
L:
return a;
}
int test4(int x) {
- goto L; // expected-error{{illegal goto into protected scope}}
+ goto L; // expected-error{{goto into protected scope}}
int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
test4(x);
L:
@@ -50,7 +50,7 @@ void test7(int x) {
switch (x) {
case 1: ;
int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
- case 2: // expected-error {{illegal switch case into protected scope}}
+ case 2: // expected-error {{switch case is in protected scope}}
a[1] = 2;
break;
}
@@ -58,17 +58,17 @@ void test7(int x) {
int test8(int x) {
// For statement.
- goto L2; // expected-error {{illegal goto into protected scope}}
+ goto L2; // expected-error {{goto into protected scope}}
for (int arr[x]; // expected-note {{jump bypasses initialization of variable length array}}
; ++x)
L2:;
// Statement expressions.
- goto L3; // expected-error {{illegal goto into protected scope}}
+ goto L3; // expected-error {{goto into protected scope}}
int Y = ({ int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
L3: 4; });
- goto L4; // expected-error {{illegal goto into protected scope}}
+ goto L4; // expected-error {{goto into protected scope}}
{
int A[x], // expected-note {{jump bypasses initialization of variable length array}}
B[x]; // expected-note {{jump bypasses initialization of variable length array}}
@@ -91,7 +91,7 @@ int test8(int x) {
int A[x], B = ({ if (x)
goto L7;
else
- goto L8; // expected-error {{illegal goto into protected scope}}
+ goto L8; // expected-error {{goto into protected scope}}
4; }),
C[x]; // expected-note {{jump bypasses initialization of variable length array}}
L8:; // bad
@@ -103,7 +103,7 @@ int test8(int x) {
goto L9;
else
// FIXME:
- goto L10; // fixme-error {{illegal goto into protected scope}}
+ goto L10; // fixme-error {{goto into protected scope}}
4; })];
L10:; // bad
}
@@ -123,7 +123,7 @@ int test8(int x) {
}
// Statement expressions 2.
- goto L1; // expected-error {{illegal goto into protected scope}}
+ goto L1; // expected-error {{goto into protected scope}}
return x == ({
int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
L1:
@@ -151,14 +151,14 @@ L4:
}
void test10(int n, void *P) {
- goto L0; // expected-error {{illegal goto into protected scope}}
+ goto L0; // expected-error {{goto into protected scope}}
typedef int A[n]; // expected-note {{jump bypasses initialization of VLA typedef}}
L0:
- goto L1; // expected-error {{illegal goto into protected scope}}
+ goto L1; // expected-error {{goto into protected scope}}
A b, c[10]; // expected-note 2 {{jump bypasses initialization of variable length array}}
L1:
- goto L2; // expected-error {{illegal goto into protected scope}}
+ goto L2; // expected-error {{goto into protected scope}}
A d[n]; // expected-note {{jump bypasses initialization of variable length array}}
L2:
return;
@@ -171,7 +171,7 @@ void test11(int n) {
case 2:
case 3:;
int Arr[n]; // expected-note {{jump bypasses initialization of variable length array}}
- case 4: // expected-error {{illegal switch case into protected scope}}
+ case 4: // expected-error {{switch case is in protected scope}}
return;
}
};
@@ -185,7 +185,7 @@ void test12(int n) {
L1:
goto L2;
L2:
- goto L3; // expected-error {{illegal goto into protected scope}}
+ goto L3; // expected-error {{goto into protected scope}}
int Arr[n]; // expected-note {{jump bypasses initialization of variable length array}}
L3:
goto L4;
diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp
index dd70d9744a..cdc3868a7b 100644
--- a/test/SemaCXX/scope-check.cpp
+++ b/test/SemaCXX/scope-check.cpp
@@ -133,3 +133,21 @@ namespace test7 {
return;
}
}
+
+// PR7789
+namespace test8 {
+ void test1(int c) {
+ switch (c) {
+ case 0:
+ int x = 56; // expected-note {{jump bypasses variable initialization}}
+ case 1: // expected-error {{switch case is in protected scope}}
+ x = 10;
+ }
+ }
+
+ void test2() {
+ goto l2; // expected-error {{goto into protected scope}}
+ l1: int x = 5; // expected-note {{jump bypasses variable initialization}}
+ l2: x++;
+ }
+}