// 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;
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)) {
// 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:
}
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);
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:
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;
}
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}}
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
goto L9;
else
// FIXME:
- goto L10; // fixme-error {{illegal goto into protected scope}}
+ goto L10; // fixme-error {{goto into protected scope}}
4; })];
L10:; // bad
}
}
// 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:
}
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;
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;
}
};
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;