xref: /llvm-project/clang/test/Analysis/builtin_overflow.c (revision fba6c887c110a501b311f6b01721eaf3a5dd994e)
1 // RUN: %clang_analyze_cc1 -triple x86_64-unknown-unknown -verify %s \
2 // RUN:   -analyzer-checker=core,debug.ExprInspection,alpha.core.BoolAssignment
3 
4 #define __UINT_MAX__ (__INT_MAX__ * 2U + 1U)
5 #define __INT_MIN__  (-__INT_MAX__ - 1)
6 
7 void clang_analyzer_dump_int(int);
8 void clang_analyzer_dump_long(long);
9 void clang_analyzer_eval(int);
10 void clang_analyzer_warnIfReached(void);
11 
12 void test_add_nooverflow(void)
13 {
14    int res;
15 
16    if (__builtin_add_overflow(10, 20, &res)) {
17      clang_analyzer_warnIfReached();
18      return;
19    }
20 
21    clang_analyzer_dump_int(res); //expected-warning{{30 S32b}}
22 }
23 
24 void test_add_overflow(void)
25 {
26    int res;
27 
28    if (__builtin_add_overflow(__INT_MAX__, 1, &res)) {
29      clang_analyzer_dump_int(res); //expected-warning{{1st function call argument is an uninitialized value}}
30      return;
31    }
32 
33    clang_analyzer_warnIfReached();
34 }
35 
36 void test_add_underoverflow(void)
37 {
38    int res;
39 
40    if (__builtin_add_overflow(__INT_MIN__, -1, &res)) {
41      clang_analyzer_dump_int(res); //expected-warning{{1st function call argument is an uninitialized value}}
42      return;
43    }
44 
45    clang_analyzer_warnIfReached();
46 }
47 
48 void test_sub_underflow(void)
49 {
50    int res;
51 
52    if (__builtin_sub_overflow(__INT_MIN__, 10, &res)) {
53      return;
54    }
55 
56    clang_analyzer_warnIfReached();
57 }
58 
59 void test_sub_overflow(void)
60 {
61    int res;
62 
63    if (__builtin_sub_overflow(__INT_MAX__, -1, &res)) {
64      return;
65    }
66 
67    clang_analyzer_warnIfReached();
68 }
69 
70 void test_sub_nooverflow(void)
71 {
72    int res;
73 
74    if (__builtin_sub_overflow(__INT_MAX__, 1, &res)) {
75      clang_analyzer_warnIfReached();
76      return;
77    }
78 
79    clang_analyzer_dump_int(res); //expected-warning{{2147483646 S32b}}
80 }
81 
82 void test_mul_overflow(void)
83 {
84    int res;
85 
86    if (__builtin_mul_overflow(__INT_MAX__, 2, &res)) {
87      return;
88    }
89 
90    clang_analyzer_warnIfReached();
91 }
92 
93 void test_mul_underflow(void)
94 {
95    int res;
96 
97    if (__builtin_mul_overflow(__INT_MIN__, -2, &res)) {
98      return;
99    }
100 
101    clang_analyzer_warnIfReached();
102 }
103 
104 void test_mul_nooverflow(void)
105 {
106    int res;
107 
108    if (__builtin_mul_overflow(10, -2, &res)) {
109      clang_analyzer_warnIfReached();
110      return;
111    }
112 
113    clang_analyzer_dump_int(res); //expected-warning{{-20 S32b}}
114 }
115 
116 void test_nooverflow_diff_types(void)
117 {
118    long res;
119 
120    // This is not an overflow, since result type is long.
121    if (__builtin_add_overflow(__INT_MAX__, 1, &res)) {
122      clang_analyzer_warnIfReached();
123      return;
124    }
125 
126    clang_analyzer_dump_long(res); //expected-warning{{2147483648 S64b}}
127 }
128 
129 void test_uaddll_overflow_contraints(unsigned long a, unsigned long b)
130 {
131    unsigned long long res;
132 
133    if (a != 10)
134      return;
135    if (b != 10)
136      return;
137 
138    if (__builtin_uaddll_overflow(a, b, &res)) {
139      clang_analyzer_warnIfReached();
140      return;
141    }
142 }
143 
144 void test_uadd_overflow_contraints(unsigned a, unsigned b)
145 {
146    unsigned res;
147 
148    if (a > 5)
149      return;
150    if (b != 10)
151      return;
152 
153    if (__builtin_uadd_overflow(a, b, &res)) {
154      clang_analyzer_warnIfReached();
155      return;
156    }
157 }
158 
159 void test_bool_assign(void)
160 {
161     int res;
162 
163     // Reproduce issue from GH#111147. __builtin_*_overflow funcions
164     // should return _Bool, but not int.
165     _Bool ret = __builtin_mul_overflow(10, 20, &res); // no crash
166 }
167