diff clang/test/Analysis/equality_tracking.c @ 221:79ff65ed7e25

LLVM12 Original
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 15 Jun 2021 19:15:29 +0900
parents
children 5f17cb93ff66
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/clang/test/Analysis/equality_tracking.c	Tue Jun 15 19:15:29 2021 +0900
@@ -0,0 +1,221 @@
+// RUN: %clang_analyze_cc1 -verify %s \
+// RUN:   -analyzer-checker=core,debug.ExprInspection \
+// RUN:   -analyzer-config eagerly-assume=false
+
+#define NULL (void *)0
+
+#define UCHAR_MAX (unsigned char)(~0U)
+#define CHAR_MAX (char)(UCHAR_MAX & (UCHAR_MAX >> 1))
+#define CHAR_MIN (char)(UCHAR_MAX & ~(UCHAR_MAX >> 1))
+
+void clang_analyzer_eval(int);
+void clang_analyzer_warnIfReached();
+
+int getInt();
+
+void zeroImpliesEquality(int a, int b) {
+  clang_analyzer_eval((a - b) == 0); // expected-warning{{UNKNOWN}}
+  if ((a - b) == 0) {
+    clang_analyzer_eval(b != a);    // expected-warning{{FALSE}}
+    clang_analyzer_eval(b == a);    // expected-warning{{TRUE}}
+    clang_analyzer_eval(!(a != b)); // expected-warning{{TRUE}}
+    clang_analyzer_eval(!(b == a)); // expected-warning{{FALSE}}
+    return;
+  }
+  clang_analyzer_eval((a - b) == 0); // expected-warning{{FALSE}}
+  clang_analyzer_eval(b == a);       // expected-warning{{FALSE}}
+  clang_analyzer_eval(b != a);       // expected-warning{{TRUE}}
+}
+
+void zeroImpliesReversedEqual(int a, int b) {
+  clang_analyzer_eval((b - a) == 0); // expected-warning{{UNKNOWN}}
+  if ((b - a) == 0) {
+    clang_analyzer_eval(b != a); // expected-warning{{FALSE}}
+    clang_analyzer_eval(b == a); // expected-warning{{TRUE}}
+    return;
+  }
+  clang_analyzer_eval((b - a) == 0); // expected-warning{{FALSE}}
+  clang_analyzer_eval(b == a);       // expected-warning{{FALSE}}
+  clang_analyzer_eval(b != a);       // expected-warning{{TRUE}}
+}
+
+void canonicalEqual(int a, int b) {
+  clang_analyzer_eval(a == b); // expected-warning{{UNKNOWN}}
+  if (a == b) {
+    clang_analyzer_eval(b == a); // expected-warning{{TRUE}}
+    return;
+  }
+  clang_analyzer_eval(a == b); // expected-warning{{FALSE}}
+  clang_analyzer_eval(b == a); // expected-warning{{FALSE}}
+}
+
+void test(int a, int b, int c, int d) {
+  if (a == b && c == d) {
+    if (a == 0 && b == d) {
+      clang_analyzer_eval(c == 0); // expected-warning{{TRUE}}
+    }
+    c = 10;
+    if (b == d) {
+      clang_analyzer_eval(c == 10); // expected-warning{{TRUE}}
+      clang_analyzer_eval(d == 10); // expected-warning{{UNKNOWN}}
+                                    // expected-warning@-1{{FALSE}}
+      clang_analyzer_eval(b == a);  // expected-warning{{TRUE}}
+      clang_analyzer_eval(a == d);  // expected-warning{{TRUE}}
+
+      b = getInt();
+      clang_analyzer_eval(a == d); // expected-warning{{TRUE}}
+      clang_analyzer_eval(a == b); // expected-warning{{UNKNOWN}}
+    }
+  }
+
+  if (a != b && b == c) {
+    if (c == 42) {
+      clang_analyzer_eval(b == 42); // expected-warning{{TRUE}}
+      clang_analyzer_eval(a != 42); // expected-warning{{TRUE}}
+    }
+  }
+}
+
+void testIntersection(int a, int b, int c) {
+  if (a < 42 && b > 15 && c >= 25 && c <= 30) {
+    if (a != b)
+      return;
+
+    clang_analyzer_eval(a > 15);  // expected-warning{{TRUE}}
+    clang_analyzer_eval(b < 42);  // expected-warning{{TRUE}}
+    clang_analyzer_eval(a <= 30); // expected-warning{{UNKNOWN}}
+
+    if (c == b) {
+      // For all equal symbols, we should track the minimal common range.
+      //
+      // Also, it should be noted that c is dead at this point, but the
+      // constraint initially associated with c is still around.
+      clang_analyzer_eval(a >= 25 && a <= 30); // expected-warning{{TRUE}}
+      clang_analyzer_eval(b >= 25 && b <= 30); // expected-warning{{TRUE}}
+    }
+  }
+}
+
+void testPromotion(int a, char b) {
+  if (b > 10) {
+    if (a == b) {
+      // FIXME: support transferring char ranges onto equal int symbols
+      //        when char is promoted to int
+      clang_analyzer_eval(a > 10);        // expected-warning{{UNKNOWN}}
+      clang_analyzer_eval(a <= CHAR_MAX); // expected-warning{{UNKNOWN}}
+    }
+  }
+}
+
+void testPromotionOnlyTypes(int a, char b) {
+  if (a == b) {
+    // FIXME: support transferring char ranges onto equal int symbols
+    //        when char is promoted to int
+    clang_analyzer_eval(a <= CHAR_MAX); // expected-warning{{UNKNOWN}}
+  }
+}
+
+void testDowncast(int a, unsigned char b) {
+  if (a <= -10) {
+    if ((unsigned char)a == b) {
+      // Even though ranges for a and b do not intersect,
+      // ranges for (unsigned char)a and b do.
+      clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+    }
+    if (a == b) {
+      // FIXME: This case on the other hand is different, it shouldn't be
+      //        reachable.  However, the corrent symbolic information available
+      //        to the solver doesn't allow it to distinguish this expression
+      //        from the previous one.
+      clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+    }
+  }
+}
+
+void testPointers(int *a, int *b, int *c, int *d) {
+  if (a == b && c == d) {
+    if (a == NULL && b == d) {
+      clang_analyzer_eval(c == NULL); // expected-warning{{TRUE}}
+    }
+  }
+
+  if (a != b && b == c) {
+    if (c == NULL) {
+      clang_analyzer_eval(a != NULL); // expected-warning{{TRUE}}
+    }
+  }
+}
+
+void testDisequalitiesAfter(int a, int b, int c) {
+  if (a >= 10 && b <= 42) {
+    if (a == b && c == 15 && c != a) {
+      clang_analyzer_eval(b != c);  // expected-warning{{TRUE}}
+      clang_analyzer_eval(a != 15); // expected-warning{{TRUE}}
+      clang_analyzer_eval(b != 15); // expected-warning{{TRUE}}
+      clang_analyzer_eval(b >= 10); // expected-warning{{TRUE}}
+      clang_analyzer_eval(a <= 42); // expected-warning{{TRUE}}
+    }
+  }
+}
+
+void testDisequalitiesBefore(int a, int b, int c) {
+  if (a >= 10 && b <= 42 && c == 15) {
+    if (a == b && c != a) {
+      clang_analyzer_eval(b != c);  // expected-warning{{TRUE}}
+      clang_analyzer_eval(a != 15); // expected-warning{{TRUE}}
+      clang_analyzer_eval(b != 15); // expected-warning{{TRUE}}
+      clang_analyzer_eval(b >= 10); // expected-warning{{TRUE}}
+      clang_analyzer_eval(a <= 42); // expected-warning{{TRUE}}
+    }
+  }
+}
+
+void avoidInfeasibleConstraintsForClasses(int a, int b) {
+  if (a >= 0 && a <= 10 && b >= 20 && b <= 50) {
+    if ((b - a) == 0) {
+      clang_analyzer_warnIfReached(); // no warning
+    }
+    if (a == b) {
+      clang_analyzer_warnIfReached(); // no warning
+    }
+    if (a != b) {
+      clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+    } else {
+      clang_analyzer_warnIfReached(); // no warning
+    }
+  }
+}
+
+void avoidInfeasibleConstraintforGT(int a, int b) {
+  int c = b - a;
+  if (c <= 0)
+    return;
+  // c > 0
+  // b - a > 0
+  // b > a
+  if (a != b) {
+    clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+    return;
+  }
+  clang_analyzer_warnIfReached(); // no warning
+  // a == b
+  if (c < 0)
+    ;
+}
+
+void avoidInfeasibleConstraintforLT(int a, int b) {
+  int c = b - a;
+  if (c >= 0)
+    return;
+  // c < 0
+  // b - a < 0
+  // b < a
+  if (a != b) {
+    clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+    return;
+  }
+  clang_analyzer_warnIfReached(); // no warning
+  // a == b
+  if (c < 0)
+    ;
+}