xref: /llvm-project/clang/test/Analysis/additive-op-on-sym-int-expr.c (revision 5f4c89edd0ade97ab3e2d6df5375974f4b975d58)
114742443STomasz Kamiński // RUN: %clang_analyze_cc1 -triple=x86_64-unknown-linux-gnu -analyzer-checker=core,apiModeling,debug.ExprInspection -analyzer-config eagerly-assume=false -verify %s
214742443STomasz Kamiński 
314742443STomasz Kamiński void clang_analyzer_dump(int);
414742443STomasz Kamiński void clang_analyzer_dumpL(long);
514742443STomasz Kamiński void clang_analyzer_warnIfReached();
614742443STomasz Kamiński 
testInspect(int x)714742443STomasz Kamiński void testInspect(int x) {
814742443STomasz Kamiński   if ((x < 10) || (x > 100)) {
914742443STomasz Kamiński     return;
1014742443STomasz Kamiński   }
1114742443STomasz Kamiński   // x: [10, 100]
1214742443STomasz Kamiński 
1314742443STomasz Kamiński   int i = x + 1;
1414742443STomasz Kamiński   long l = i - 10U;
1514742443STomasz Kamiński   clang_analyzer_dump(i);       // expected-warning-re {{(reg_${{[0-9]+}}<int x>) + 1 }}
1614742443STomasz Kamiński   clang_analyzer_dumpL(l);      // expected-warning-re {{(reg_${{[0-9]+}}<int x>) - 9U }} instead of + 4294967287U
1714742443STomasz Kamiński   clang_analyzer_dumpL(l + 0L); // expected-warning-re {{(reg_${{[0-9]+}}<int x>) - 9 }}  instead of + 4294967287
1814742443STomasz Kamiński 
1914742443STomasz Kamiński   if ((l - 1000) > 0) {
2014742443STomasz Kamiński     clang_analyzer_warnIfReached(); // no-warning
2114742443STomasz Kamiński   }
2214742443STomasz Kamiński   if (l > 1000) {
2314742443STomasz Kamiński     clang_analyzer_warnIfReached(); // no-warning
2414742443STomasz Kamiński   }
2514742443STomasz Kamiński   if (l > 1000L) {
2614742443STomasz Kamiński     clang_analyzer_warnIfReached(); // no-warning
2714742443STomasz Kamiński   }
2814742443STomasz Kamiński   if ((l + 0L) > 1000) {
2914742443STomasz Kamiński     clang_analyzer_warnIfReached(); // no-warning
3014742443STomasz Kamiński   }
3114742443STomasz Kamiński 
3214742443STomasz Kamiński   i = x - 1;
3314742443STomasz Kamiński   l = i + 10U;
3414742443STomasz Kamiński   clang_analyzer_dumpL(l); // expected-warning-re {{(reg_${{[0-9]+}}<int x>) + 9U }} instead of - 4294967287U
3514742443STomasz Kamiński 
3614742443STomasz Kamiński   i = x + (-1);
3714742443STomasz Kamiński   l = i - 10U;
3814742443STomasz Kamiński   clang_analyzer_dumpL(l); // expected-warning-re {{(reg_${{[0-9]+}}<int x>) - 11U }} instead of + 4294967285U
3914742443STomasz Kamiński 
4014742443STomasz Kamiński   i = x + 1U;
4114742443STomasz Kamiński   l = i - 10U;
4214742443STomasz Kamiński   clang_analyzer_dumpL(l); // expected-warning-re {{(reg_${{[0-9]+}}<int x>) - 9U }} instead of + 4294967287U
4314742443STomasz Kamiński }
4414742443STomasz Kamiński 
4514742443STomasz Kamiński const int intMin = 1 << (sizeof(int) * 8 - 1);     // INT_MIN, negation value is not representable
4614742443STomasz Kamiński const long longMin = 1L << (sizeof(long) * 8 - 1); // LONG_MIN, negation value is not representable
4714742443STomasz Kamiński 
testMin(int i,long l)4814742443STomasz Kamiński void testMin(int i, long l) {
4914742443STomasz Kamiński   clang_analyzer_dump(i + (-1));  // expected-warning-re {{(reg_${{[0-9]+}}<int i>) - 1 }} instead of + -1
5014742443STomasz Kamiński   clang_analyzer_dump(i - (-1));  // expected-warning-re {{(reg_${{[0-9]+}}<int i>) + 1 }} instead of - -1
5114742443STomasz Kamiński   clang_analyzer_dumpL(l + (-1)); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) - 1 }} instead of + -1
5214742443STomasz Kamiński   clang_analyzer_dumpL(l - (-1)); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) + 1 }} instead of - -1
5314742443STomasz Kamiński 
5414742443STomasz Kamiński   // Do not normalize representation if negation would not be representable
5514742443STomasz Kamiński   clang_analyzer_dump(i + intMin); // expected-warning-re {{(reg_${{[0-9]+}}<int i>) + -2147483648 }} no change
5614742443STomasz Kamiński   clang_analyzer_dump(i - intMin); // expected-warning-re {{(reg_${{[0-9]+}}<int i>) - -2147483648 }} no change
5714742443STomasz Kamiński   // Produced value has higher bit with (long) so negation if representable
5814742443STomasz Kamiński   clang_analyzer_dumpL(l + intMin); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) - 2147483648 }} instead of + -2147483648
5914742443STomasz Kamiński   clang_analyzer_dumpL(l - intMin); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) + 2147483648 }} instead of - -2147483648
6014742443STomasz Kamiński }
6114742443STomasz Kamiński 
changingToUnsigned(unsigned u,int i)62*5f4c89edSRageking8 void changingToUnsigned(unsigned u, int i) {
6314742443STomasz Kamiński   unsigned c = u + (unsigned)i;
6414742443STomasz Kamiński   unsigned d = u - (unsigned)i;
6514742443STomasz Kamiński   if (i == -1) {
6614742443STomasz Kamiński     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) - 1U }}
6714742443STomasz Kamiński     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) + 1U }}
6814742443STomasz Kamiński     return;
6914742443STomasz Kamiński   }
7014742443STomasz Kamiński   if (i == intMin) {
7114742443STomasz Kamiński     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) - 2147483648U }}
7214742443STomasz Kamiński     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) + 2147483648U }}
7314742443STomasz Kamiński     return;
7414742443STomasz Kamiński   }
7514742443STomasz Kamiński }
7614742443STomasz Kamiński 
extendingToSigned(long l,int i)7714742443STomasz Kamiński void extendingToSigned(long l, int i) {
7814742443STomasz Kamiński   long c = l + (long)i;
7914742443STomasz Kamiński   long d = l - (long)i;
8014742443STomasz Kamiński   if (i == -1) {
8114742443STomasz Kamiński     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) - 1 }}
8214742443STomasz Kamiński     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) + 1 }}
8314742443STomasz Kamiński     return;
8414742443STomasz Kamiński   }
8514742443STomasz Kamiński   if (i == intMin) {
8614742443STomasz Kamiński     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) - 2147483648 }}
8714742443STomasz Kamiński     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<long l>) + 2147483648 }}
8814742443STomasz Kamiński     return;
8914742443STomasz Kamiński   }
9014742443STomasz Kamiński }
9114742443STomasz Kamiński 
extendingToUnsigned(unsigned long ul,int i)92*5f4c89edSRageking8 void extendingToUnsigned(unsigned long ul, int i) {
9314742443STomasz Kamiński   unsigned long c = ul + (unsigned long)i;
9414742443STomasz Kamiński   unsigned long d = ul - (unsigned long)i;
9514742443STomasz Kamiński   if (i == -1) {
9614742443STomasz Kamiński     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned long ul>) - 1U }}
9714742443STomasz Kamiński     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned long ul>) + 1U }}
9814742443STomasz Kamiński     return;
9914742443STomasz Kamiński   }
10014742443STomasz Kamiński   if (i == intMin) {
10114742443STomasz Kamiński     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned long ul>) - 2147483648U }}
10214742443STomasz Kamiński     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned long ul>) + 2147483648U }}
10314742443STomasz Kamiński     return;
10414742443STomasz Kamiński   }
10514742443STomasz Kamiński }
10614742443STomasz Kamiński 
truncatingToSigned(int i,long l)10714742443STomasz Kamiński void truncatingToSigned(int i, long l) {
10814742443STomasz Kamiński   int c = i + (int)l;
10914742443STomasz Kamiński   int d = i - (int)l;
11014742443STomasz Kamiński   if (l == -1L) {
11114742443STomasz Kamiński     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<int i>) - 1 }}
11214742443STomasz Kamiński     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<int i>) + 1 }}
11314742443STomasz Kamiński     return;
11414742443STomasz Kamiński   }
11514742443STomasz Kamiński   if (l == (long)intMin) {      // negation outside of range, no-changes
11614742443STomasz Kamiński     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<int i>) + -2147483648 }}
11714742443STomasz Kamiński     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<int i>) + -2147483648 }}
11814742443STomasz Kamiński     return;
11914742443STomasz Kamiński   }
12014742443STomasz Kamiński   if (l == ((long)intMin - 1L)) { // outside or range, no changes
12114742443STomasz Kamiński     clang_analyzer_dump(c + 0);   // expected-warning-re {{(reg_${{[0-9]+}}<int i>) + 2147483647 }}
12214742443STomasz Kamiński     clang_analyzer_dump(d + 0);   // expected-warning-re {{(reg_${{[0-9]+}}<int i>) - 2147483647 }}
12314742443STomasz Kamiński     return;
12414742443STomasz Kamiński   }
12514742443STomasz Kamiński   if (l == longMin) {           // outside of range, no changes
12614742443STomasz Kamiński     clang_analyzer_dump(c + 0); // expected-warning-re {{reg_${{[0-9]+}}<int i> }}
12714742443STomasz Kamiński     clang_analyzer_dump(d + 0); // expected-warning-re {{reg_${{[0-9]+}}<int i> }}
12814742443STomasz Kamiński     return;
12914742443STomasz Kamiński   }
13014742443STomasz Kamiński }
13114742443STomasz Kamiński 
truncatingToUnsigned(unsigned u,long l)13214742443STomasz Kamiński void truncatingToUnsigned(unsigned u, long l) {
13314742443STomasz Kamiński   unsigned c = u + (unsigned)l;
13414742443STomasz Kamiński   unsigned d = u - (unsigned)l;
13514742443STomasz Kamiński   if (l == -1L) {
13614742443STomasz Kamiński     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) - 1U }}
13714742443STomasz Kamiński     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) + 1U }}
13814742443STomasz Kamiński     return;
13914742443STomasz Kamiński   }
14014742443STomasz Kamiński   if (l == (long)intMin) {
14114742443STomasz Kamiński     clang_analyzer_dump(c + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) - 2147483648U }}
14214742443STomasz Kamiński     clang_analyzer_dump(d + 0); // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) + 2147483648U }}
14314742443STomasz Kamiński     return;
14414742443STomasz Kamiński   }
14514742443STomasz Kamiński   if (l == ((long)intMin - 1L)) { // outside or range, no changes
14614742443STomasz Kamiński     clang_analyzer_dump(c + 0);   // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) + 2147483647U }}
14714742443STomasz Kamiński     clang_analyzer_dump(d + 0);   // expected-warning-re {{(reg_${{[0-9]+}}<unsigned int u>) - 2147483647U }}
14814742443STomasz Kamiński     return;
14914742443STomasz Kamiński   }
15014742443STomasz Kamiński   if (l == longMin) {           // outside of range, no changes
15114742443STomasz Kamiński     clang_analyzer_dump(c + 0); // expected-warning-re {{reg_${{[0-9]+}}<unsigned int u> }}
15214742443STomasz Kamiński     clang_analyzer_dump(d + 0); // expected-warning-re {{reg_${{[0-9]+}}<unsigned int u> }}
15314742443STomasz Kamiński     return;
15414742443STomasz Kamiński   }
15514742443STomasz Kamiński }
15614742443STomasz Kamiński 
15714742443STomasz Kamiński // Test for crashes
15814742443STomasz Kamiński typedef long ssize_t;
15914742443STomasz Kamiński ssize_t write(int, const void *, unsigned long);
16014742443STomasz Kamiński 
crashTest(int x,int fd)16114742443STomasz Kamiński int crashTest(int x, int fd) {
16214742443STomasz Kamiński   unsigned wres = write(fd, "a", 1);
16314742443STomasz Kamiński   if (wres) {
16414742443STomasz Kamiński   }
16514742443STomasz Kamiński   int t1 = x - wres;
16614742443STomasz Kamiński   if (wres < 0) {
16714742443STomasz Kamiński   }
16814742443STomasz Kamiński   return x + t1; // no crash
16914742443STomasz Kamiński }
170