mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 20:16:05 +00:00
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:
parent
460a356bf6
commit
4a33fa95c0
@ -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<
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user