summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGen/PR8880.c
diff options
context:
space:
mode:
authorSerge Pavlov <sepavloff@gmail.com>2014-01-23 15:05:00 +0000
committerSerge Pavlov <sepavloff@gmail.com>2014-01-23 15:05:00 +0000
commit09f9924acf1a8644e9458833d3c8ea40d7ddbc46 (patch)
treeab81b6c65a12f96059f2bed913314d8f138c7925 /clang/test/CodeGen/PR8880.c
parent5a68c4b28747fc5da182916b801de9a34e59a0dd (diff)
downloadbcm5719-llvm-09f9924acf1a8644e9458833d3c8ea40d7ddbc46.tar.gz
bcm5719-llvm-09f9924acf1a8644e9458833d3c8ea40d7ddbc46.zip
Fix to PR8880 (clang dies processing a for loop)
Due to statement expressions supported as GCC extension, it is possible to put 'break' or 'continue' into a loop/switch statement but outside its body, for example: for ( ; ({ if (first) { first = 0; continue; } 0; }); ) This code is rejected by GCC if compiled in C mode but is accepted in C++ code. GCC bug 44715 tracks this discrepancy. Clang used code generation that differs from GCC in both modes: only statement of the third expression of 'for' behaves as if it was inside loop body. This change makes code generation more close to GCC, considering 'break' or 'continue' statement in condition and increment expressions of a loop as it was inside the loop body. It also adds error for the cases when 'break'/'continue' appear outside loop due to this syntax. If code generation differ from GCC, warning is issued. Differential Revision: http://llvm-reviews.chandlerc.com/D2518 llvm-svn: 199897
Diffstat (limited to 'clang/test/CodeGen/PR8880.c')
-rw-r--r--clang/test/CodeGen/PR8880.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/clang/test/CodeGen/PR8880.c b/clang/test/CodeGen/PR8880.c
new file mode 100644
index 00000000000..e03d2a42b61
--- /dev/null
+++ b/clang/test/CodeGen/PR8880.c
@@ -0,0 +1,173 @@
+// RUN: %clang_cc1 -Wno-gcc-compat -emit-llvm -o - %s | FileCheck %s
+
+void pr8880_cg_1(int *iptr) {
+// CHECK-LABEL: define void @pr8880_cg_1(
+ int i, j;
+// CHECK: br label %[[OUTER_COND:[0-9A-Za-z$._]+]]
+ for (i = 2; i != 10 ; i++ )
+// CHECK: [[OUTER_COND]]
+// CHECK: label %[[OUTER_BODY:[0-9A-Za-z$._]+]], label %[[OUTER_END:[0-9A-Za-z$._]+]]
+// CHECK: [[OUTER_BODY]]
+// CHECK: br label %[[INNER_COND:[0-9A-Za-z$._]+]]
+ for (j = 3 ; j < 22; (void)({ ++j; break; j;})) {
+// CHECK: [[INNER_COND]]
+// CHECK: label %[[INNER_BODY:[0-9A-Za-z$._]+]], label %[[INNER_END:[0-9A-Za-z$._]+]]
+// CHECK: [[INNER_BODY]]
+ *iptr = 7;
+// CHECK: store i32 7,
+// CHECK: br label %[[INNER_INC:[0-9A-Za-z$._]+]]
+// CHECK: [[INNER_INC]]
+
+// break in 3rd expression of inner loop causes branch to end of inner loop
+
+// CHECK: br label %[[INNER_END:[0-9A-Za-z$._]+]]
+// CHECK: [[INNER_END]]
+ }
+// CHECK: br label %[[OUTER_INC:[0-9A-Za-z$._]+]]
+// CHECK: [[OUTER_INC]]
+// CHECK: br label %[[OUTER_COND]]
+// CHECK: [[OUTER_END]]
+// CHECK: ret
+}
+
+void pr8880_cg_2(int *iptr) {
+// CHECK-LABEL: define void @pr8880_cg_2(
+ int i, j;
+// CHECK: br label %[[OUTER_COND:[0-9A-Za-z$._]+]]
+ for (i = 2; i != 10 ; i++ )
+// CHECK: [[OUTER_COND]]
+// CHECK: label %[[OUTER_BODY:[0-9A-Za-z$._]+]], label %[[OUTER_END:[0-9A-Za-z$._]+]]
+// CHECK: [[OUTER_BODY]]
+// CHECK: br label %[[INNER_COND:[0-9A-Za-z$._]+]]
+ for (j = 3 ; j < 22; (void)({ ++j; continue; j;})) {
+// CHECK: [[INNER_COND]]
+// CHECK: label %[[INNER_BODY:[0-9A-Za-z$._]+]], label %[[INNER_END:[0-9A-Za-z$._]+]]
+// CHECK: [[INNER_BODY]]
+ *iptr = 7;
+// CHECK: store i32 7,
+// CHECK: br label %[[INNER_INC:[0-9A-Za-z$._]+]]
+// CHECK: [[INNER_INC]]
+
+// continue in 3rd expression of inner loop causes branch to inc of inner loop
+
+// CHECK: br label %[[INNER_INC]]
+// CHECK: [[INNER_END]]
+ }
+// CHECK: br label %[[OUTER_INC:[0-9A-Za-z$._]+]]
+// CHECK: [[OUTER_INC]]
+// CHECK: br label %[[OUTER_COND]]
+// CHECK: [[OUTER_END]]
+// CHECK: ret
+}
+
+void pr8880_cg_3(int *iptr) {
+// CHECK-LABEL: define void @pr8880_cg_3(
+ int i, j;
+// CHECK: br label %[[OUTER_COND:[0-9A-Za-z$._]+]]
+ for (i = 2 ; i != 10 ; i++ )
+// CHECK: [[OUTER_COND]]
+// CHECK: label %[[OUTER_BODY:[0-9A-Za-z$._]+]], label %[[OUTER_END:[0-9A-Za-z$._]+]]
+// CHECK: [[OUTER_BODY]]
+// CHECK: br label %[[INNER_COND:[0-9A-Za-z$._]+]]
+ for (j = 3 ; ({break; j;}); j++) {
+
+// break in 2nd expression of inner loop causes branch to end of inner loop
+
+// CHECK: [[INNER_COND]]
+// CHECK: br label %[[INNER_END:[0-9A-Za-z$._]+]]
+// CHECK: label %[[INNER_BODY:[0-9A-Za-z$._]+]], label %[[INNER_END:[0-9A-Za-z$._]+]]
+// CHECK: [[INNER_BODY]]
+ *iptr = 7;
+// CHECK: store i32 7,
+// CHECK: br label %[[INNER_INC:[0-9A-Za-z$._]+]]
+// CHECK: [[INNER_INC]]
+// CHECK: br label %[[INNER_COND]]
+ }
+// CHECK: [[INNER_END]]
+// CHECK: br label %[[OUTER_INC:[0-9A-Za-z$._]+]]
+// CHECK: [[OUTER_INC]]
+// CHECK: br label %[[OUTER_COND]]
+// CHECK: [[OUTER_END]]
+// CHECK: ret
+}
+
+void pr8880_cg_4(int *iptr) {
+// CHECK-LABEL: define void @pr8880_cg_4(
+ int i, j;
+// CHECK: br label %[[OUTER_COND:[0-9A-Za-z$._]+]]
+ for (i = 2 ; i != 10 ; i++ )
+// CHECK: [[OUTER_COND]]
+// CHECK: label %[[OUTER_BODY:[0-9A-Za-z$._]+]], label %[[OUTER_END:[0-9A-Za-z$._]+]]
+// CHECK: [[OUTER_BODY]]
+// CHECK: br label %[[INNER_COND:[0-9A-Za-z$._]+]]
+ for (j = 3 ; ({continue; j;}); j++) {
+
+// continue in 2nd expression of inner loop causes branch to inc of inner loop
+
+// CHECK: [[INNER_COND]]
+// CHECK: br label %[[INNER_INC:[0-9A-Za-z$._]+]]
+// CHECK: label %[[INNER_BODY:[0-9A-Za-z$._]+]], label %[[INNER_END:[0-9A-Za-z$._]+]]
+// CHECK: [[INNER_BODY]]
+ *iptr = 7;
+// CHECK: store i32 7,
+// CHECK: br label %[[INNER_INC]]
+// CHECK: [[INNER_INC]]
+// CHECK: br label %[[INNER_COND]]
+ }
+// CHECK: [[INNER_END]]
+// CHECK: br label %[[OUTER_INC:[0-9A-Za-z$._]+]]
+// CHECK: [[OUTER_INC]]
+// CHECK: br label %[[OUTER_COND]]
+// CHECK: [[OUTER_END]]
+// CHECK: ret
+}
+
+void pr8880_cg_5(int x, int *iptr) {
+// CHECK-LABEL: define void @pr8880_cg_5(
+ int y = 5;
+// CHECK: br label %[[OUTER_COND:[0-9A-Za-z$._]+]]
+// CHECK: [[OUTER_COND]]
+ while(--x) {
+// CHECK: label %[[OUTER_BODY:[0-9A-Za-z$._]+]], label %[[OUTER_END:[0-9A-Za-z$._]+]]
+// CHECK: [[OUTER_BODY]]
+// CHECK: br label %[[INNER_COND:[0-9A-Za-z$._]+]]
+ while(({ break; --y; })) {
+// CHECK: [[INNER_COND]]
+// CHECK: br label %[[INNER_END:[0-9A-Za-z$._]+]]
+// CHECK: label %[[INNER_BODY:[0-9A-Za-z$._]+]], label %[[INNER_END:[0-9A-Za-z$._]+]]
+// CHECK: [[INNER_BODY]]
+ *iptr = 7;
+// CHECK: store i32 7,
+ }
+// CHECK: br label %[[INNER_COND]]
+ }
+// CHECK: [[INNER_END]]
+// CHECK: br label %[[OUTER_COND]]
+// CHECK: [[OUTER_END]]
+// CHECK: ret void
+}
+
+void pr8880_cg_6(int x, int *iptr) {
+// CHECK-LABEL: define void @pr8880_cg_6(
+ int y = 5;
+// CHECK: br label %[[OUTER_COND:[0-9A-Za-z$._]+]]
+// CHECK: [[OUTER_COND]]
+ while(--x) {
+// CHECK: label %[[OUTER_BODY:[0-9A-Za-z$._]+]], label %[[OUTER_END:[0-9A-Za-z$._]+]]
+// CHECK: [[OUTER_BODY]]
+// CHECK: br label %[[INNER_BODY:[0-9A-Za-z$._]+]]
+// CHECK: [[INNER_BODY]]
+ do {
+// CHECK: store i32 7,
+ *iptr = 7;
+// CHECK: br label %[[INNER_COND:[0-9A-Za-z$._]+]]
+ } while(({ break; --y; }));
+// CHECK: [[INNER_COND]]
+// CHECK: br label %[[INNER_END:[0-9A-Za-z$._]+]]
+// CHECK: label %[[INNER_BODY:[0-9A-Za-z$._]+]], label %[[INNER_END]]
+ }
+// CHECK: [[INNER_END]]
+// CHECK: br label %[[OUTER_COND]]
+// CHECK: [[OUTER_END]]
+// CHECK: ret void
+}
OpenPOWER on IntegriCloud