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.

llvm-svn: 110082
This commit is contained in:
John McCall 2010-08-02 23:33:14 +00:00
parent 460a356bf6
commit 4a33fa95c0
4 changed files with 54 additions and 34 deletions

View File

@ -1855,9 +1855,9 @@ def warn_missing_braces : Warning<
def err_redefinition_of_label : Error<"redefinition of label '%0'">; def err_redefinition_of_label : Error<"redefinition of label '%0'">;
def err_undeclared_label_use : Error<"use of undeclared 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< 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< def err_indirect_goto_without_addrlabel : Error<
"indirect goto in function with no address-of-label expressions">; "indirect goto in function with no address-of-label expressions">;
def warn_indirect_goto_in_protected_scope : Warning< def warn_indirect_goto_in_protected_scope : Warning<

View File

@ -180,22 +180,6 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
// If we found a label, remember that it is in ParentScope scope. // If we found a label, remember that it is in ParentScope scope.
switch (S->getStmtClass()) { 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: case Stmt::AddrLabelExprClass:
IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel()); IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel());
break; break;
@ -235,6 +219,24 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
Stmt *SubStmt = *CI; Stmt *SubStmt = *CI;
if (SubStmt == 0) continue; 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 // If this is a declstmt with a VLA definition, it defines a scope from here
// to the end of the containing context. // to the end of the containing context.
if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) { if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) {

View File

@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=gnu99 %s -Wno-unreachable-code // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=gnu99 %s -Wno-unreachable-code
int test1(int x) { 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 a[x]; // expected-note {{jump bypasses initialization of variable length array}}
int b[x]; // expected-note {{jump bypasses initialization of variable length array}} int b[x]; // expected-note {{jump bypasses initialization of variable length array}}
L: L:
@ -9,7 +9,7 @@ int test1(int x) {
} }
int test2(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}} typedef int a[x]; // expected-note {{jump bypasses initialization of VLA typedef}}
L: L:
return sizeof(a); return sizeof(a);
@ -18,14 +18,14 @@ int test2(int x) {
void test3clean(int*); void test3clean(int*);
int test3() { 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))}} int a __attribute((cleanup(test3clean))); // expected-note {{jump bypasses initialization of variable with __attribute__((cleanup))}}
L: L:
return a; return a;
} }
int test4(int x) { 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}} int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
test4(x); test4(x);
L: L:
@ -50,7 +50,7 @@ void test7(int x) {
switch (x) { switch (x) {
case 1: ; case 1: ;
int a[x]; // expected-note {{jump bypasses initialization of variable length array}} 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; a[1] = 2;
break; break;
} }
@ -58,17 +58,17 @@ void test7(int x) {
int test8(int x) { int test8(int x) {
// For statement. // 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}} for (int arr[x]; // expected-note {{jump bypasses initialization of variable length array}}
; ++x) ; ++x)
L2:; L2:;
// Statement expressions. // 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}} int Y = ({ int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
L3: 4; }); 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}} int A[x], // expected-note {{jump bypasses initialization of variable length array}}
B[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) int A[x], B = ({ if (x)
goto L7; goto L7;
else else
goto L8; // expected-error {{illegal goto into protected scope}} goto L8; // expected-error {{goto into protected scope}}
4; }), 4; }),
C[x]; // expected-note {{jump bypasses initialization of variable length array}} C[x]; // expected-note {{jump bypasses initialization of variable length array}}
L8:; // bad L8:; // bad
@ -103,7 +103,7 @@ int test8(int x) {
goto L9; goto L9;
else else
// FIXME: // FIXME:
goto L10; // fixme-error {{illegal goto into protected scope}} goto L10; // fixme-error {{goto into protected scope}}
4; })]; 4; })];
L10:; // bad L10:; // bad
} }
@ -123,7 +123,7 @@ int test8(int x) {
} }
// Statement expressions 2. // Statement expressions 2.
goto L1; // expected-error {{illegal goto into protected scope}} goto L1; // expected-error {{goto into protected scope}}
return x == ({ return x == ({
int a[x]; // expected-note {{jump bypasses initialization of variable length array}} int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
L1: L1:
@ -151,14 +151,14 @@ L4:
} }
void test10(int n, void *P) { 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}} typedef int A[n]; // expected-note {{jump bypasses initialization of VLA typedef}}
L0: 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}} A b, c[10]; // expected-note 2 {{jump bypasses initialization of variable length array}}
L1: 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}} A d[n]; // expected-note {{jump bypasses initialization of variable length array}}
L2: L2:
return; return;
@ -171,7 +171,7 @@ void test11(int n) {
case 2: case 2:
case 3:; case 3:;
int Arr[n]; // expected-note {{jump bypasses initialization of variable length array}} 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; return;
} }
}; };
@ -185,7 +185,7 @@ void test12(int n) {
L1: L1:
goto L2; goto L2;
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}} int Arr[n]; // expected-note {{jump bypasses initialization of variable length array}}
L3: L3:
goto L4; goto L4;

View File

@ -133,3 +133,21 @@ namespace test7 {
return; 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++;
}
}