mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-02 10:16:06 +00:00

about the permitted scopes. Specifically: 1) Permit labels and gotos to appear after a prologue of variable initializations. 2) Permit indirect gotos to jump out of scopes that don't require cleanup. 3) Diagnose possible attempts to indirect-jump out of scopes that do require cleanup. This requires a substantial reinvention of the algorithm for checking indirect goto. The current algorithm is Omega(M*N), with M = the number of unique scopes being jumped from and N = the number of unique scopes being jumped to, with an additional factor that is probably (worst-case) linear in the depth of scopes. Thus the entire thing is likely cubic given some truly bizarre ill-formed code; on well-formed code the additional factor collapses to an amortized constant (when amortized over the entire function) and so the algorithm is quadratic. Even this requires every label to appear in its own scope, which would be very unusual for indirect-goto code (and extremely unlikely for well-formed code); it is far more likely that all labels will be in the same scope and so the algorithm becomes linear. For such a marginal feature, I am fairly happy with this result. (this is using JumpDiagnostic's definition of scope, where successive variables in a block appear in their own scope) llvm-svn: 103536
202 lines
5.0 KiB
C
202 lines
5.0 KiB
C
// 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}}
|
|
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:
|
|
return sizeof a;
|
|
}
|
|
|
|
int test2(int x) {
|
|
goto L; // expected-error{{illegal 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}}
|
|
int a __attribute((cleanup(test3clean))); // expected-note {{jump bypasses initialization of declaration with __attribute__((cleanup))}}
|
|
L:
|
|
return a;
|
|
}
|
|
|
|
int test4(int x) {
|
|
goto L; // expected-error{{illegal goto into protected scope}}
|
|
int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
|
|
test4(x);
|
|
L:
|
|
return sizeof a;
|
|
}
|
|
|
|
int test5(int x) {
|
|
int a[x];
|
|
test5(x);
|
|
goto L; // Ok.
|
|
L:
|
|
goto L; // Ok.
|
|
return sizeof a;
|
|
}
|
|
|
|
int test6() {
|
|
// just plain invalid.
|
|
goto x; // expected-error {{use of undeclared label 'x'}}
|
|
}
|
|
|
|
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}}
|
|
a[1] = 2;
|
|
break;
|
|
}
|
|
}
|
|
|
|
int test8(int x) {
|
|
// For statement.
|
|
goto L2; // expected-error {{illegal 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}}
|
|
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}}
|
|
{
|
|
int A[x], // expected-note {{jump bypasses initialization of variable length array}}
|
|
B[x]; // expected-note {{jump bypasses initialization of variable length array}}
|
|
L4: ;
|
|
}
|
|
|
|
{
|
|
L5: ;// ok
|
|
int A[x], B = ({ if (x)
|
|
goto L5;
|
|
else
|
|
goto L6;
|
|
4; });
|
|
L6:; // ok.
|
|
if (x) goto L6; // ok
|
|
}
|
|
|
|
{
|
|
L7: ;// ok
|
|
int A[x], B = ({ if (x)
|
|
goto L7;
|
|
else
|
|
goto L8; // expected-error {{illegal goto into protected scope}}
|
|
4; }),
|
|
C[x]; // expected-note {{jump bypasses initialization of variable length array}}
|
|
L8:; // bad
|
|
}
|
|
|
|
{
|
|
L9: ;// ok
|
|
int A[({ if (x)
|
|
goto L9;
|
|
else
|
|
// FIXME:
|
|
goto L10; // fixme-error {{illegal goto into protected scope}}
|
|
4; })];
|
|
L10:; // bad
|
|
}
|
|
|
|
{
|
|
// FIXME: Crashes goto checker.
|
|
//goto L11;// ok
|
|
//int A[({ L11: 4; })];
|
|
}
|
|
|
|
{
|
|
goto L12;
|
|
|
|
int y = 4; // fixme-warn: skips initializer.
|
|
L12:
|
|
;
|
|
}
|
|
|
|
// Statement expressions 2.
|
|
goto L1; // expected-error {{illegal goto into protected scope}}
|
|
return x == ({
|
|
int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
|
|
L1:
|
|
42; });
|
|
}
|
|
|
|
void test9(int n, void *P) {
|
|
int Y;
|
|
int Z = 4;
|
|
goto *P; // expected-warning {{indirect goto might cross protected scopes}}
|
|
|
|
L2: ;
|
|
int a[n]; // expected-note {{jump bypasses initialization of variable length array}}
|
|
|
|
L3: // expected-note {{possible target of indirect goto}}
|
|
L4:
|
|
goto *P;
|
|
goto L3; // ok
|
|
goto L4; // ok
|
|
|
|
void *Ptrs[] = {
|
|
&&L2,
|
|
&&L3
|
|
};
|
|
}
|
|
|
|
void test10(int n, void *P) {
|
|
goto L0; // expected-error {{illegal 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}}
|
|
A b, c[10]; // expected-note 2 {{jump bypasses initialization of variable length array}}
|
|
L1:
|
|
goto L2; // expected-error {{illegal goto into protected scope}}
|
|
A d[n]; // expected-note {{jump bypasses initialization of variable length array}}
|
|
L2:
|
|
return;
|
|
}
|
|
|
|
void test11(int n) {
|
|
void *P = ^{
|
|
switch (n) {
|
|
case 1:;
|
|
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}}
|
|
return;
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
// TODO: When and if gotos are allowed in blocks, this should work.
|
|
void test12(int n) {
|
|
void *P = ^{
|
|
goto L1;
|
|
L1:
|
|
goto L2;
|
|
L2:
|
|
goto L3; // expected-error {{illegal goto into protected scope}}
|
|
int Arr[n]; // expected-note {{jump bypasses initialization of variable length array}}
|
|
L3:
|
|
goto L4;
|
|
L4: return;
|
|
};
|
|
}
|
|
|
|
void test13(int n, void *p) {
|
|
int vla[n];
|
|
goto *p;
|
|
a0: ;
|
|
static void *ps[] = { &&a0 };
|
|
}
|