1 // REQUIRES: x86-registered-target
2 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=0 -fsanitize=array-bounds        %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-0
3 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=0 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-0,CXX,CXX-STRICT-0
4 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=1 -fsanitize=array-bounds        %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-1
5 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=1 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-1,CXX
6 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=2 -fsanitize=array-bounds        %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-2
7 // RUN: %clang_cc1 -emit-llvm -triple x86_64 -fstrict-flex-arrays=2 -fsanitize=array-bounds -x c++ %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-STRICT-2,CXX
8 // Before flexible array member was added to C99, many projects use a
9 // one-element array as the last member of a structure as an alternative.
10 // E.g. https://github.com/python/cpython/issues/84301
11 // Suppress such errors with -fstrict-flex-arrays=0.
12 struct One {
13   int a[1];
14 };
15 struct Two {
16   int a[2];
17 };
18 struct Three {
19   int a[3];
20 };
21 
22 // CHECK-LABEL: define {{.*}} @{{.*}}test_one{{.*}}(
23 int test_one(struct One *p, int i) {
24   // CHECK-STRICT-0-NOT: @__ubsan
25   // CHECK-STRICT-1-NOT: @__ubsan
26   // CHECK-STRICT-2:     call void @__ubsan_handle_out_of_bounds_abort(
27   return p->a[i] + (p->a)[i];
28 }
29 
30 // CHECK-LABEL: define {{.*}} @{{.*}}test_two{{.*}}(
31 int test_two(struct Two *p, int i) {
32   // CHECK-STRICT-0:     call void @__ubsan_handle_out_of_bounds_abort(
33   // CHECK-STRICT-1:     call void @__ubsan_handle_out_of_bounds_abort(
34   // CHECK-STRICT-2:     call void @__ubsan_handle_out_of_bounds_abort(
35   return p->a[i] + (p->a)[i];
36 }
37 
38 // CHECK-LABEL: define {{.*}} @{{.*}}test_three{{.*}}(
39 int test_three(struct Three *p, int i) {
40   // CHECK-STRICT-0:     call void @__ubsan_handle_out_of_bounds_abort(
41   // CHECK-STRICT-1:     call void @__ubsan_handle_out_of_bounds_abort(
42   // CHECK-STRICT-2:     call void @__ubsan_handle_out_of_bounds_abort(
43   return p->a[i] + (p->a)[i];
44 }
45 
46 #define FLEXIBLE 1
47 struct Macro {
48   int a[FLEXIBLE];
49 };
50 
51 // CHECK-LABEL: define {{.*}} @{{.*}}test_macro{{.*}}(
52 int test_macro(struct Macro *p, int i) {
53   // CHECK-STRICT-0-NOT: @__ubsan
54   return p->a[i] + (p->a)[i];
55 }
56 
57 #if defined __cplusplus
58 
59 struct Base {
60   int b;
61 };
62 struct NoStandardLayout : Base {
63   int a[1];
64 };
65 
66 // CXX-LABEL: define {{.*}} @{{.*}}test_nostandardlayout{{.*}}(
67 int test_nostandardlayout(NoStandardLayout *p, int i) {
68   // CXX-STRICT-0-NOT: @__ubsan
69   return p->a[i] + (p->a)[i];
70 }
71 
72 template<int N> struct Template {
73   int a[N];
74 };
75 
76 // CXX-LABEL: define {{.*}} @{{.*}}test_template{{.*}}(
77 int test_template(Template<1> *p, int i) {
78   // CXX-STRICT-0-NOT: @__ubsan
79   return p->a[i] + (p->a)[i];
80 }
81 
82 #endif
83