Douglas Gregor 0afa7f66cd Tweak the typo-correction implementation to determine corrections
solely based on the names it sees, rather than actual declarations it
gets. In essence, we determine the set of names that are "close
enough" to the typo'd name. Then, we perform name lookup for each of
those names, filtering out those that aren't actually visible, and
typo-correct from the remaining results.

Overall, there isn't much of a change in the behavior of typo
correction here. The only test-suite change comes from the fact that
we make good on our promise to require that the user type 3 characters
for each 1 character corrected. 

The real intent behind this change is to set the stage for an
optimization to typo correction (so that we don't need to deserialize
all declarations in a translation unit) and future work in finding
missing qualification ("'vector' isn't in scope; did you mean
'std::vector'?). Plus, the code is cleaner this way.

llvm-svn: 116511
2010-10-14 20:34:08 +00:00

291 lines
5.6 KiB
C

// RUN: %clang_cc1 -fsyntax-only -verify %s
void f (int z) {
while (z) {
default: z--; // expected-error {{statement not in switch}}
}
}
void foo(int X) {
switch (X) {
case 42: ; // expected-note {{previous case}}
case 5000000000LL: // expected-warning {{overflow}}
case 42: // expected-error {{duplicate case value}}
;
case 100 ... 99: ; // expected-warning {{empty case range}}
case 43: ; // expected-note {{previous case}}
case 43 ... 45: ; // expected-error {{duplicate case value}}
case 100 ... 20000:; // expected-note {{previous case}}
case 15000 ... 40000000:; // expected-error {{duplicate case value}}
}
}
void test3(void) {
// empty switch;
switch (0); // expected-warning {{no case matching constant switch condition '0'}}
}
extern int g();
void test4()
{
int cond;
switch (cond) {
case 0 && g():
case 1 || g():
break;
}
switch(cond) {
case g(): // expected-error {{expression is not an integer constant expression}}
case 0 ... g(): // expected-error {{expression is not an integer constant expression}}
break;
}
switch (cond) {
case 0 && g() ... 1 || g():
break;
}
switch (cond) {
case g() && 0: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}}
break;
}
switch (cond) {
case 0 ... g() || 1: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}}
break;
}
}
void test5(int z) {
switch(z) {
default: // expected-note {{previous case defined here}}
default: // expected-error {{multiple default labels in one switch}}
break;
}
}
void test6() {
char ch = 'a';
switch(ch) {
case 1234: // expected-warning {{overflow converting case value}}
break;
}
}
// PR5606
int f0(int var) {
switch (va) { // expected-error{{use of undeclared identifier 'va'}}
case 1:
break;
case 2:
return 1;
}
return 2;
}
void test7() {
enum {
A = 1,
B
} a;
switch(a) { //expected-warning{{enumeration value 'B' not handled in switch}}
case A:
break;
}
switch(a) {
case B:
case A:
break;
}
switch(a) {
case A:
case B:
case 3: // expected-warning{{case value not in enumerated type ''}}
break;
}
switch(a) {
case A:
case B:
case 3 ... //expected-warning{{case value not in enumerated type ''}}
4: //expected-warning{{case value not in enumerated type ''}}
break;
}
switch(a) {
case 1 ... 2:
break;
}
switch(a) {
case 0 ... 2: //expected-warning{{case value not in enumerated type ''}}
break;
}
switch(a) {
case 1 ... 3: //expected-warning{{case value not in enumerated type ''}}
break;
}
switch(a) {
case 0 ... //expected-warning{{case value not in enumerated type ''}}
3: //expected-warning{{case value not in enumerated type ''}}
break;
}
}
void test8() {
enum {
A,
B,
C = 1
} a;
switch(a) {
case A:
case B:
break;
}
switch(a) {
case A:
case C:
break;
}
switch(a) { //expected-warning{{enumeration value 'B' not handled in switch}}
case A:
break;
}
}
void test9() {
enum {
A = 3,
C = 1
} a;
switch(a) {
case 0: //expected-warning{{case value not in enumerated type ''}}
case 1:
case 2: //expected-warning{{case value not in enumerated type ''}}
case 3:
case 4: //expected-warning{{case value not in enumerated type ''}}
break;
}
}
void test10() {
enum {
A = 10,
C = 2,
B = 4,
D = 12
} a;
switch(a) {
case 0 ... //expected-warning{{case value not in enumerated type ''}}
1: //expected-warning{{case value not in enumerated type ''}}
case 2 ... 4:
case 5 ... //expected-warning{{case value not in enumerated type ''}}
9: //expected-warning{{case value not in enumerated type ''}}
case 10 ... 12:
case 13 ... //expected-warning{{case value not in enumerated type ''}}
16: //expected-warning{{case value not in enumerated type ''}}
break;
}
}
void test11() {
enum {
A = -1,
B,
C
} a;
switch(a) { //expected-warning{{enumeration value 'A' not handled in switch}}
case B:
case C:
break;
}
switch(a) {
case B:
case C:
break;
default:
break;
}
}
void test12() {
enum {
A = -1,
B = 4294967286
} a;
switch(a) {
case A:
case B:
break;
}
}
// <rdar://problem/7643909>
typedef enum {
val1,
val2,
val3
} my_type_t;
int test13(my_type_t t) {
switch(t) { // expected-warning{{enumeration value 'val3' not handled in switch}}
case val1:
return 1;
case val2:
return 2;
}
return -1;
}
// <rdar://problem/7658121>
enum {
EC0 = 0xFFFF0000,
EC1 = 0xFFFF0001,
};
int test14(int a) {
switch(a) {
case EC0: return 0;
case EC1: return 1;
}
return 0;
}
void f1(unsigned x) {
switch (x) {
case -1: break;
default: break;
}
}
void test15() {
int i = 0;
switch (1) { // expected-warning {{no case matching constant switch condition '1'}}
case 0: i = 0; break;
case 2: i++; break;
}
}
void test16() {
const char c = '5';
switch (c) { // expected-warning {{no case matching constant switch condition '53'}}
case '6': return;
}
}
// PR7359
void test17(int x) {
switch (x >= 17) { // expected-warning {{switch condition has boolean value}}
case 0: return;
}
switch ((int) (x <= 17)) {
case 0: return;
}
}