xref: /llvm-project/clang/test/CodeGen/ignore-overflow-pattern.c (revision 1e5c1a342e87961513da84a55cb7a3c3ba22b354)
1295fe0bdSJustin Stitt // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-undefined-ignore-overflow-pattern=all %s -emit-llvm -o - | FileCheck %s
2295fe0bdSJustin Stitt // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-undefined-ignore-overflow-pattern=all -fwrapv %s -emit-llvm -o - | FileCheck %s
376236fafSJustin Stitt // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-undefined-ignore-overflow-pattern=add-signed-overflow-test,add-unsigned-overflow-test %s -emit-llvm -o - | FileCheck %s --check-prefix=ADD
4295fe0bdSJustin Stitt // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-undefined-ignore-overflow-pattern=negated-unsigned-const %s -emit-llvm -o - | FileCheck %s --check-prefix=NEGATE
576236fafSJustin Stitt // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsanitize=signed-integer-overflow,unsigned-integer-overflow -fsanitize-undefined-ignore-overflow-pattern=unsigned-post-decr-while %s -emit-llvm -o - | FileCheck %s --check-prefix=WHILE
6295fe0bdSJustin Stitt 
7295fe0bdSJustin Stitt // Ensure some common overflow-dependent or overflow-prone code patterns don't
8295fe0bdSJustin Stitt // trigger the overflow sanitizers. In many cases, overflow warnings caused by
9295fe0bdSJustin Stitt // these patterns are seen as "noise" and result in users turning off
10295fe0bdSJustin Stitt // sanitization all together.
11295fe0bdSJustin Stitt 
12295fe0bdSJustin Stitt // A pattern like "if (a + b < a)" simply checks for overflow and usually means
13295fe0bdSJustin Stitt // the user is trying to handle it gracefully.
14295fe0bdSJustin Stitt 
15295fe0bdSJustin Stitt // Similarly, a pattern resembling "while (i--)" is extremely common and
16295fe0bdSJustin Stitt // warning on its inevitable overflow can be seen as superfluous. Do note that
17295fe0bdSJustin Stitt // using "i" in future calculations can be tricky because it will still
18295fe0bdSJustin Stitt // wrap-around.
19295fe0bdSJustin Stitt 
20295fe0bdSJustin Stitt // Another common pattern that, in some cases, is found to be too noisy is
21295fe0bdSJustin Stitt // unsigned negation, for example:
22295fe0bdSJustin Stitt // unsigned long A = -1UL;
23295fe0bdSJustin Stitt 
24*1e5c1a34SChandler Carruth // Skip over parts of the IR containing this file's name.
25*1e5c1a34SChandler Carruth // CHECK: source_filename = {{.*}}
26295fe0bdSJustin Stitt 
27*1e5c1a34SChandler Carruth // Ensure we don't see anything about handling overflow before the tests below.
28295fe0bdSJustin Stitt // CHECK-NOT: handle{{.*}}overflow
29295fe0bdSJustin Stitt 
30295fe0bdSJustin Stitt extern unsigned a, b, c;
3176236fafSJustin Stitt extern int u, v;
32295fe0bdSJustin Stitt extern unsigned some(void);
33295fe0bdSJustin Stitt 
34295fe0bdSJustin Stitt // ADD-LABEL: @basic_commutativity
35295fe0bdSJustin Stitt // WHILE-LABEL: @basic_commutativity
36295fe0bdSJustin Stitt // NEGATE-LABEL: @basic_commutativity
37295fe0bdSJustin Stitt // WHILE: handler.add_overflow
38295fe0bdSJustin Stitt // NEGATE: handler.add_overflow
39295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow
40295fe0bdSJustin Stitt void basic_commutativity(void) {
41295fe0bdSJustin Stitt   if (a + b < a)
42295fe0bdSJustin Stitt     c = 9;
43295fe0bdSJustin Stitt   if (a + b < b)
44295fe0bdSJustin Stitt     c = 9;
45295fe0bdSJustin Stitt   if (b + a < b)
46295fe0bdSJustin Stitt     c = 9;
47295fe0bdSJustin Stitt   if (b + a < a)
48295fe0bdSJustin Stitt     c = 9;
49295fe0bdSJustin Stitt   if (a > a + b)
50295fe0bdSJustin Stitt     c = 9;
51295fe0bdSJustin Stitt   if (a > b + a)
52295fe0bdSJustin Stitt     c = 9;
53295fe0bdSJustin Stitt   if (b > a + b)
54295fe0bdSJustin Stitt     c = 9;
55295fe0bdSJustin Stitt   if (b > b + a)
56295fe0bdSJustin Stitt     c = 9;
5776236fafSJustin Stitt   if (u + v < u)
5876236fafSJustin Stitt     c = 9;
59295fe0bdSJustin Stitt }
60295fe0bdSJustin Stitt 
61295fe0bdSJustin Stitt // ADD-LABEL: @arguments_and_commutativity
62295fe0bdSJustin Stitt // WHILE-LABEL: @arguments_and_commutativity
63295fe0bdSJustin Stitt // NEGATE-LABEL: @arguments_and_commutativity
64295fe0bdSJustin Stitt // WHILE: handler.add_overflow
65295fe0bdSJustin Stitt // NEGATE: handler.add_overflow
66295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow
67295fe0bdSJustin Stitt void arguments_and_commutativity(unsigned V1, unsigned V2) {
68295fe0bdSJustin Stitt   if (V1 + V2 < V1)
69295fe0bdSJustin Stitt     c = 9;
70295fe0bdSJustin Stitt   if (V1 + V2 < V2)
71295fe0bdSJustin Stitt     c = 9;
72295fe0bdSJustin Stitt   if (V2 + V1 < V2)
73295fe0bdSJustin Stitt     c = 9;
74295fe0bdSJustin Stitt   if (V2 + V1 < V1)
75295fe0bdSJustin Stitt     c = 9;
76295fe0bdSJustin Stitt   if (V1 > V1 + V2)
77295fe0bdSJustin Stitt     c = 9;
78295fe0bdSJustin Stitt   if (V1 > V2 + V1)
79295fe0bdSJustin Stitt     c = 9;
80295fe0bdSJustin Stitt   if (V2 > V1 + V2)
81295fe0bdSJustin Stitt     c = 9;
82295fe0bdSJustin Stitt   if (V2 > V2 + V1)
83295fe0bdSJustin Stitt     c = 9;
84295fe0bdSJustin Stitt }
85295fe0bdSJustin Stitt 
86295fe0bdSJustin Stitt // ADD-LABEL: @pointers
87295fe0bdSJustin Stitt // WHILE-LABEL: @pointers
88295fe0bdSJustin Stitt // NEGATE-LABEL: @pointers
89295fe0bdSJustin Stitt // WHILE: handler.add_overflow
90295fe0bdSJustin Stitt // NEGATE: handler.add_overflow
91295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow
92295fe0bdSJustin Stitt void pointers(unsigned *P1, unsigned *P2, unsigned V1) {
93295fe0bdSJustin Stitt   if (*P1 + *P2 < *P1)
94295fe0bdSJustin Stitt     c = 9;
95295fe0bdSJustin Stitt   if (*P1 + V1 < V1)
96295fe0bdSJustin Stitt     c = 9;
97295fe0bdSJustin Stitt   if (V1 + *P2 < *P2)
98295fe0bdSJustin Stitt     c = 9;
99295fe0bdSJustin Stitt }
100295fe0bdSJustin Stitt 
101295fe0bdSJustin Stitt struct OtherStruct {
102295fe0bdSJustin Stitt   unsigned foo, bar;
103295fe0bdSJustin Stitt };
104295fe0bdSJustin Stitt 
105295fe0bdSJustin Stitt struct MyStruct {
106295fe0bdSJustin Stitt   unsigned base, offset;
107295fe0bdSJustin Stitt   struct OtherStruct os;
108295fe0bdSJustin Stitt };
109295fe0bdSJustin Stitt 
110295fe0bdSJustin Stitt extern struct MyStruct ms;
111295fe0bdSJustin Stitt 
112295fe0bdSJustin Stitt // ADD-LABEL: @structs
113295fe0bdSJustin Stitt // WHILE-LABEL: @structs
114295fe0bdSJustin Stitt // NEGATE-LABEL: @structs
115295fe0bdSJustin Stitt // WHILE: handler.add_overflow
116295fe0bdSJustin Stitt // NEGATE: handler.add_overflow
117295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow
118295fe0bdSJustin Stitt void structs(void) {
119295fe0bdSJustin Stitt   if (ms.base + ms.offset < ms.base)
120295fe0bdSJustin Stitt     c = 9;
121295fe0bdSJustin Stitt }
122295fe0bdSJustin Stitt 
123295fe0bdSJustin Stitt // ADD-LABEL: @nestedstructs
124295fe0bdSJustin Stitt // WHILE-LABEL: @nestedstructs
125295fe0bdSJustin Stitt // NEGATE-LABEL: @nestedstructs
126295fe0bdSJustin Stitt // WHILE: handler.add_overflow
127295fe0bdSJustin Stitt // NEGATE: handler.add_overflow
128295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow
129295fe0bdSJustin Stitt void nestedstructs(void) {
130295fe0bdSJustin Stitt   if (ms.os.foo + ms.os.bar < ms.os.foo)
131295fe0bdSJustin Stitt     c = 9;
132295fe0bdSJustin Stitt }
133295fe0bdSJustin Stitt 
134295fe0bdSJustin Stitt // ADD-LABEL: @constants
135295fe0bdSJustin Stitt // WHILE-LABEL: @constants
136295fe0bdSJustin Stitt // NEGATE-LABEL: @constants
137295fe0bdSJustin Stitt // WHILE: handler.add_overflow
138295fe0bdSJustin Stitt // NEGATE: handler.add_overflow
139295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow
140295fe0bdSJustin Stitt // Normally, this would be folded into a simple call to the overflow handler
141295fe0bdSJustin Stitt // and a store. Excluding this pattern results in just a store.
142295fe0bdSJustin Stitt void constants(void) {
143295fe0bdSJustin Stitt   unsigned base = 4294967295;
144295fe0bdSJustin Stitt   unsigned offset = 1;
145295fe0bdSJustin Stitt   if (base + offset < base)
146295fe0bdSJustin Stitt     c = 9;
147295fe0bdSJustin Stitt }
148295fe0bdSJustin Stitt // ADD-LABEL: @common_while
149295fe0bdSJustin Stitt // NEGATE-LABEL: @common_while
150295fe0bdSJustin Stitt // WHILE-LABEL: @common_while
151295fe0bdSJustin Stitt // ADD: usub.with.overflow
152295fe0bdSJustin Stitt // NEGATE: usub.with.overflow
153295fe0bdSJustin Stitt // WHILE:  %dec = add i32 %0, -1
154295fe0bdSJustin Stitt void common_while(unsigned i) {
155295fe0bdSJustin Stitt   // This post-decrement usually causes overflow sanitizers to trip on the very
156295fe0bdSJustin Stitt   // last operation.
157295fe0bdSJustin Stitt   while (i--) {
158295fe0bdSJustin Stitt     some();
159295fe0bdSJustin Stitt   }
160295fe0bdSJustin Stitt }
161295fe0bdSJustin Stitt 
162295fe0bdSJustin Stitt // ADD-LABEL: @negation
163295fe0bdSJustin Stitt // NEGATE-LABEL: @negation
164295fe0bdSJustin Stitt // WHILE-LABEL @negation
165295fe0bdSJustin Stitt // ADD: negate_overflow
166295fe0bdSJustin Stitt // NEGATE-NOT: negate_overflow
167295fe0bdSJustin Stitt // WHILE: negate_overflow
168295fe0bdSJustin Stitt // Normally, these assignments would trip the unsigned overflow sanitizer.
169295fe0bdSJustin Stitt void negation(void) {
170295fe0bdSJustin Stitt #define SOME -1UL
171295fe0bdSJustin Stitt   unsigned long A = -1UL;
172295fe0bdSJustin Stitt   unsigned long B = -2UL;
173295fe0bdSJustin Stitt   unsigned long C = -SOME;
174295fe0bdSJustin Stitt   (void)A;(void)B;(void)C;
175295fe0bdSJustin Stitt }
176295fe0bdSJustin Stitt 
177295fe0bdSJustin Stitt 
178295fe0bdSJustin Stitt // ADD-LABEL: @function_call
179295fe0bdSJustin Stitt // WHILE-LABEL: @function_call
180295fe0bdSJustin Stitt // NEGATE-LABEL: @function_call
181295fe0bdSJustin Stitt // WHILE: handler.add_overflow
182295fe0bdSJustin Stitt // NEGATE: handler.add_overflow
183295fe0bdSJustin Stitt // ADD-NOT: handler.add_overflow
184295fe0bdSJustin Stitt void function_call(void) {
185295fe0bdSJustin Stitt   if (b + some() < b)
186295fe0bdSJustin Stitt     c = 9;
187295fe0bdSJustin Stitt }
188