| // RUN: %clang_cc1 -triple i386-unknown-unknown -O3 %s -emit-llvm -o - | FileCheck %s |
| |
| int foo(int i) { |
| int j = 0; |
| switch (i) { |
| case -1: |
| j = 1; break; |
| case 1 : |
| j = 2; break; |
| case 2: |
| j = 3; break; |
| default: |
| j = 42; break; |
| } |
| j = j + 1; |
| return j; |
| } |
| |
| int foo2(int i) { |
| int j = 0; |
| switch (i) { |
| case 1 : |
| j = 2; break; |
| case 2 ... 10: |
| j = 3; break; |
| default: |
| j = 42; break; |
| } |
| j = j + 1; |
| return j; |
| } |
| |
| int foo3(int i) { |
| int j = 0; |
| switch (i) { |
| default: |
| j = 42; break; |
| case 111: |
| j = 111; break; |
| case 0 ... 100: |
| j = 1; break; |
| case 222: |
| j = 222; break; |
| } |
| return j; |
| } |
| |
| |
| static int foo4(int i) { |
| int j = 0; |
| switch (i) { |
| case 111: |
| j = 111; break; |
| case 0 ... 100: |
| j = 1; break; |
| case 222: |
| j = 222; break; |
| default: |
| j = 42; break; |
| case 501 ... 600: |
| j = 5; break; |
| } |
| return j; |
| } |
| |
| // CHECK-LABEL: define i32 @foo4t() |
| // CHECK: ret i32 376 |
| // CHECK: } |
| int foo4t() { |
| // 111 + 1 + 222 + 42 = 376 |
| return foo4(111) + foo4(99) + foo4(222) + foo4(601); |
| } |
| |
| // CHECK-LABEL: define void @foo5() |
| // CHECK-NOT: switch |
| // CHECK: } |
| void foo5(){ |
| switch(0){ |
| default: |
| if (0) { |
| |
| } |
| } |
| } |
| |
| // CHECK-LABEL: define void @foo6() |
| // CHECK-NOT: switch |
| // CHECK: } |
| void foo6(){ |
| switch(0){ |
| } |
| } |
| |
| // CHECK-LABEL: define void @foo7() |
| // CHECK-NOT: switch |
| // CHECK: } |
| void foo7(){ |
| switch(0){ |
| foo7(); |
| } |
| } |
| |
| |
| // CHECK-LABEL: define i32 @f8( |
| // CHECK: ret i32 3 |
| // CHECK: } |
| int f8(unsigned x) { |
| switch(x) { |
| default: |
| return 3; |
| case 0xFFFFFFFF ... 1: // This range should be empty because x is unsigned. |
| return 0; |
| } |
| } |
| |
| // Ensure that default after a case range is not ignored. |
| // |
| // CHECK-LABEL: define i32 @f9() |
| // CHECK: ret i32 10 |
| // CHECK: } |
| static int f9_0(unsigned x) { |
| switch(x) { |
| case 10 ... 0xFFFFFFFF: |
| return 0; |
| default: |
| return 10; |
| } |
| } |
| int f9() { |
| return f9_0(2); |
| } |
| |
| // Ensure that this doesn't compile to infinite loop in g() due to |
| // miscompilation of fallthrough from default to a (tested) case |
| // range. |
| // |
| // CHECK-LABEL: define i32 @f10() |
| // CHECK: ret i32 10 |
| // CHECK: } |
| static int f10_0(unsigned x) { |
| switch(x) { |
| default: |
| x += 1; |
| case 10 ... 0xFFFFFFFF: |
| return 0; |
| } |
| } |
| |
| int f10() { |
| f10_0(1); |
| return 10; |
| } |
| |
| // This generated incorrect code because of poor switch chaining. |
| // |
| // CHECK-LABEL: define i32 @f11( |
| // CHECK: ret i32 3 |
| // CHECK: } |
| int f11(int x) { |
| switch(x) { |
| default: |
| return 3; |
| case 10 ... 0xFFFFFFFF: |
| return 0; |
| } |
| } |
| |
| // This just asserted because of the way case ranges were calculated. |
| // |
| // CHECK-LABEL: define i32 @f12( |
| // CHECK: ret i32 3 |
| // CHECK: } |
| int f12(int x) { |
| switch (x) { |
| default: |
| return 3; |
| case 10 ... -1: |
| return 0; |
| } |
| } |
| |
| // Make sure return is not constant (if empty range is skipped or miscompiled) |
| // |
| // CHECK-LABEL: define i32 @f13( |
| // CHECK: ret i32 % |
| // CHECK: } |
| int f13(unsigned x) { |
| switch(x) { |
| case 2: |
| // fallthrough empty range |
| case 10 ... 9: |
| return 10; |
| default: |
| return 0; |
| } |
| } |
| |
| // Don't delete a basic block that we want to introduce later references to. |
| // This isn't really specific to switches, but it's easy to show with them. |
| // rdar://problem/8837067 |
| int f14(int x) { |
| switch (x) { |
| |
| // case range so that the case block has no predecessors |
| case 0 ... 15: |
| // any expression which doesn't introduce a new block |
| (void) 0; |
| // kaboom |
| |
| default: |
| return x; |
| } |
| } |