xref: /llvm-project/clang/test/Analysis/additive-op-on-sym-int-expr.c (revision 5f4c89edd0ade97ab3e2d6df5375974f4b975d58)
1 // RUN: %clang_analyze_cc1 -triple=x86_64-unknown-linux-gnu -analyzer-checker=core,apiModeling,debug.ExprInspection -analyzer-config eagerly-assume=false -verify %s
2 
3 void clang_analyzer_dump(int);
4 void clang_analyzer_dumpL(long);
5 void clang_analyzer_warnIfReached();
6 
testInspect(int x)7 void testInspect(int x) {
8   if ((x < 10) || (x > 100)) {
9     return;
10   }
11   // x: [10, 100]
12 
13   int i = x + 1;
14   long l = i - 10U;
15   clang_analyzer_dump(i);       // expected-warning-re {{(reg_${{[0-9]+}}<int x>) + 1 }}
16   clang_analyzer_dumpL(l);      // expected-warning-re {{(reg_${{[0-9]+}}<int x>) - 9U }} instead of + 4294967287U
17   clang_analyzer_dumpL(l + 0L); // expected-warning-re {{(reg_${{[0-9]+}}<int x>) - 9 }}  instead of + 4294967287
18 
19   if ((l - 1000) > 0) {
20     clang_analyzer_warnIfReached(); // no-warning
21   }
22   if (l > 1000) {
23     clang_analyzer_warnIfReached(); // no-warning
24   }
25   if (l > 1000L) {
26     clang_analyzer_warnIfReached(); // no-warning
27   }
28   if ((l + 0L) > 1000) {
29     clang_analyzer_warnIfReached(); // no-warning
30   }
31 
32   i = x - 1;
33   l = i + 10U;
34   clang_analyzer_dumpL(l); // expected-warning-re {{(reg_${{[0-9]+}}<int x>) + 9U }} instead of - 4294967287U
35 
36   i = x + (-1);
37   l = i - 10U;
38   clang_analyzer_dumpL(l); // expected-warning-re {{(reg_${{[0-9]+}}<int x>) - 11U }} instead of + 4294967285U
39 
40   i = x + 1U;
41   l = i - 10U;
42   clang_analyzer_dumpL(l); // expected-warning-re {{(reg_${{[0-9]+}}<int x>) - 9U }} instead of + 4294967287U
43 }
44 
45 const int intMin = 1 << (sizeof(int) * 8 - 1);     // INT_MIN, negation value is not representable
46 const long longMin = 1L << (sizeof(long) * 8 - 1); // LONG_MIN, negation value is not representable
47 
testMin(int i,long l)48 void testMin(int i, long l) {
49   clang_analyzer_dump(i + (-1));  // expected-warning-re {{(reg_${{[0-9]+}}<int i>) - 1 }} instead of + -1
50   clang_analyzer_dump(i - (-1));  // expected-warning-re {{(reg_${{[0-9]+}}<int i>) + 1 }} instead of - -1
51   clang_analyzer_dumpL(l + (-1)); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) - 1 }} instead of + -1
52   clang_analyzer_dumpL(l - (-1)); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) + 1 }} instead of - -1
53 
54   // Do not normalize representation if negation would not be representable
55   clang_analyzer_dump(i + intMin); // expected-warning-re {{(reg_${{[0-9]+}}<int i>) + -2147483648 }} no change
56   clang_analyzer_dump(i - intMin); // expected-warning-re {{(reg_${{[0-9]+}}<int i>) - -2147483648 }} no change
57   // Produced value has higher bit with (long) so negation if representable
58   clang_analyzer_dumpL(l + intMin); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) - 2147483648 }} instead of + -2147483648
59   clang_analyzer_dumpL(l - intMin); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) + 2147483648 }} instead of - -2147483648
60 }
61 
changingToUnsigned(unsigned u,int i)62 void changingToUnsigned(unsigned u, int i) {
63   unsigned c = u + (unsigned)i;
64   unsigned d = u - (unsigned)i;
65   if (i == -1) {
66     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) - 1U }}
67     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) + 1U }}
68     return;
69   }
70   if (i == intMin) {
71     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) - 2147483648U }}
72     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) + 2147483648U }}
73     return;
74   }
75 }
76 
extendingToSigned(long l,int i)77 void extendingToSigned(long l, int i) {
78   long c = l + (long)i;
79   long d = l - (long)i;
80   if (i == -1) {
81     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) - 1 }}
82     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) + 1 }}
83     return;
84   }
85   if (i == intMin) {
86     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) - 2147483648 }}
87     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) + 2147483648 }}
88     return;
89   }
90 }
91 
extendingToUnsigned(unsigned long ul,int i)92 void extendingToUnsigned(unsigned long ul, int i) {
93   unsigned long c = ul + (unsigned long)i;
94   unsigned long d = ul - (unsigned long)i;
95   if (i == -1) {
96     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned long ul>) - 1U }}
97     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned long ul>) + 1U }}
98     return;
99   }
100   if (i == intMin) {
101     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned long ul>) - 2147483648U }}
102     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned long ul>) + 2147483648U }}
103     return;
104   }
105 }
106 
truncatingToSigned(int i,long l)107 void truncatingToSigned(int i, long l) {
108   int c = i + (int)l;
109   int d = i - (int)l;
110   if (l == -1L) {
111     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<int i>) - 1 }}
112     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<int i>) + 1 }}
113     return;
114   }
115   if (l == (long)intMin) {      // negation outside of range, no-changes
116     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<int i>) + -2147483648 }}
117     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<int i>) + -2147483648 }}
118     return;
119   }
120   if (l == ((long)intMin - 1L)) { // outside or range, no changes
121     clang_analyzer_dump(c + 0);   // expected-warning-re {{(reg_${{[0-9]+}}<int i>) + 2147483647 }}
122     clang_analyzer_dump(d + 0);   // expected-warning-re {{(reg_${{[0-9]+}}<int i>) - 2147483647 }}
123     return;
124   }
125   if (l == longMin) {           // outside of range, no changes
126     clang_analyzer_dump(c + 0); // expected-warning-re {{reg_${{[0-9]+}}<int i> }}
127     clang_analyzer_dump(d + 0); // expected-warning-re {{reg_${{[0-9]+}}<int i> }}
128     return;
129   }
130 }
131 
truncatingToUnsigned(unsigned u,long l)132 void truncatingToUnsigned(unsigned u, long l) {
133   unsigned c = u + (unsigned)l;
134   unsigned d = u - (unsigned)l;
135   if (l == -1L) {
136     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) - 1U }}
137     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) + 1U }}
138     return;
139   }
140   if (l == (long)intMin) {
141     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) - 2147483648U }}
142     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) + 2147483648U }}
143     return;
144   }
145   if (l == ((long)intMin - 1L)) { // outside or range, no changes
146     clang_analyzer_dump(c + 0);   // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) + 2147483647U }}
147     clang_analyzer_dump(d + 0);   // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) - 2147483647U }}
148     return;
149   }
150   if (l == longMin) {           // outside of range, no changes
151     clang_analyzer_dump(c + 0); // expected-warning-re {{reg_${{[0-9]+}}<unsigned int u> }}
152     clang_analyzer_dump(d + 0); // expected-warning-re {{reg_${{[0-9]+}}<unsigned int u> }}
153     return;
154   }
155 }
156 
157 // Test for crashes
158 typedef long ssize_t;
159 ssize_t write(int, const void *, unsigned long);
160 
crashTest(int x,int fd)161 int crashTest(int x, int fd) {
162   unsigned wres = write(fd, "a", 1);
163   if (wres) {
164   }
165   int t1 = x - wres;
166   if (wres < 0) {
167   }
168   return x + t1; // no crash
169 }
170