113 changes: 113 additions & 0 deletions clang/test/Analysis/constraint_manager_negate.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection,core.builtin \
// RUN: -analyzer-config eagerly-assume=false \
// RUN: -verify %s

void clang_analyzer_eval(int);
void clang_analyzer_dump(int);

void exit(int);

#define UINT_MIN (0U)
#define UINT_MAX (~UINT_MIN)
#define UINT_MID (UINT_MAX / 2 + 1)
#define INT_MAX (UINT_MAX & (UINT_MAX >> 1))
#define INT_MIN (UINT_MAX & ~(UINT_MAX >> 1))

extern void abort() __attribute__((__noreturn__));
#define assert(expr) ((expr) ? (void)(0) : abort())

void negate_positive_range(int a) {
assert(-a > 0);
// -a: [1, INT_MAX]
// a: [INT_MIN + 1, -1]
clang_analyzer_eval(a < 0); // expected-warning{{TRUE}}
clang_analyzer_eval(a > INT_MIN); // expected-warning{{TRUE}}
}

void negate_positive_range2(int a) {
assert(a > 0);
// a: [1, INT_MAX]
// -a: [INT_MIN + 1, -1]
clang_analyzer_eval(-a < 0); // expected-warning{{TRUE}}
clang_analyzer_eval(-a > INT_MIN); // expected-warning{{TRUE}}
}

// INT_MIN equals 0b100...00.
// Its two's compelement is 0b011...11 + 1 = 0b100...00 (itself).
_Static_assert(INT_MIN == -INT_MIN, "");
void negate_int_min(int a) {
assert(a == INT_MIN);
clang_analyzer_eval(-a == INT_MIN); // expected-warning{{TRUE}}
}

void negate_mixed(int a) {
assert(a > 0 || a == INT_MIN);
clang_analyzer_eval(-a <= 0); // expected-warning{{TRUE}}
}

void effective_range(int a) {
assert(a >= 0);
assert(-a >= 0);
clang_analyzer_eval(a == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(-a == 0); // expected-warning{{TRUE}}
}

_Static_assert(-INT_MIN == INT_MIN, "");
void effective_range_2(int a) {
assert(a <= 0);
assert(-a <= 0);
clang_analyzer_eval(a == 0 || a == INT_MIN); // expected-warning{{TRUE}}
}

void negate_symexpr(int a, int b) {
assert(3 <= a * b && a * b <= 5);
clang_analyzer_eval(-(a * b) >= -5); // expected-warning{{TRUE}}
clang_analyzer_eval(-(a * b) <= -3); // expected-warning{{TRUE}}
}

void negate_unsigned_min(unsigned a) {
assert(a == UINT_MIN);
clang_analyzer_eval(-a == UINT_MIN); // expected-warning{{TRUE}}
clang_analyzer_eval(-a != UINT_MIN); // expected-warning{{FALSE}}
clang_analyzer_eval(-a > UINT_MIN); // expected-warning{{FALSE}}
clang_analyzer_eval(-a < UINT_MIN); // expected-warning{{FALSE}}
}

_Static_assert(7u - 3u != 3u - 7u, "");
_Static_assert(-4u == UINT_MAX - 3u, "");
void negate_unsigned_4(unsigned a) {
assert(a == 4u);
clang_analyzer_eval(-a == 4u); // expected-warning{{FALSE}}
clang_analyzer_eval(-a != 4u); // expected-warning{{TRUE}}
clang_analyzer_eval(-a == UINT_MAX - 3u); // expected-warning{{TRUE}}
}

// UINT_MID equals 0b100...00.
// Its two's compelement is 0b011...11 + 1 = 0b100...00 (itself).
_Static_assert(UINT_MID == -UINT_MID, "");
void negate_unsigned_mid(unsigned a) {
assert(a == UINT_MID);
clang_analyzer_eval(-a == UINT_MID); // expected-warning{{TRUE}}
clang_analyzer_eval(-a != UINT_MID); // expected-warning{{FALSE}}
}

void negate_unsigned_mid2(unsigned a) {
assert(UINT_MIN < a && a < UINT_MID);
// a: [UINT_MIN+1, UINT_MID-1]
// -a: [UINT_MID+1, UINT_MAX]
clang_analyzer_eval(-a > UINT_MID); // expected-warning{{TRUE}}
clang_analyzer_eval(-a <= UINT_MAX); // expected-warning{{TRUE}}
}

_Static_assert(1u - 2u == UINT_MAX, "");
_Static_assert(2u - 1u == 1, "");
void negate_unsigned_max(unsigned a) {
assert(a == UINT_MAX);
clang_analyzer_eval(-a == 1); // expected-warning{{TRUE}}
clang_analyzer_eval(-a != 1); // expected-warning{{FALSE}}
}
void negate_unsigned_one(unsigned a) {
assert(a == 1);
clang_analyzer_eval(-a == UINT_MAX); // expected-warning{{TRUE}}
clang_analyzer_eval(-a < UINT_MAX); // expected-warning{{FALSE}}
}
99 changes: 47 additions & 52 deletions clang/test/Analysis/constraint_manager_negate_difference.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection,core.builtin -analyzer-config aggressive-binary-operation-simplification=true -verify %s
// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection,core.builtin \
// RUN: -analyzer-config eagerly-assume=false \
// RUN: -verify %s

void clang_analyzer_eval(int);

Expand All @@ -10,11 +12,8 @@ void exit(int);
#define INT_MAX (UINT_MAX & (UINT_MAX >> 1))
#define INT_MIN (UINT_MAX & ~(UINT_MAX >> 1))

extern void __assert_fail (__const char *__assertion, __const char *__file,
unsigned int __line, __const char *__function)
__attribute__ ((__noreturn__));
#define assert(expr) \
((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__))
extern void abort() __attribute__((__noreturn__));
#define assert(expr) ((expr) ? (void)(0) : abort())

void assert_in_range(int x) {
assert(x <= ((int)INT_MAX / 4));
Expand All @@ -33,69 +32,60 @@ void assert_in_range_2(int m, int n) {

void equal(int m, int n) {
assert_in_range_2(m, n);
if (m != n)
return;
assert(m == n);
assert_in_wide_range(m - n);
clang_analyzer_eval(n == m); // expected-warning{{TRUE}}
}

void non_equal(int m, int n) {
assert_in_range_2(m, n);
if (m == n)
return;
assert(m != n);
assert_in_wide_range(m - n);
clang_analyzer_eval(n != m); // expected-warning{{TRUE}}
}

void less_or_equal(int m, int n) {
assert_in_range_2(m, n);
if (m < n)
return;
assert(m >= n);
assert_in_wide_range(m - n);
clang_analyzer_eval(n <= m); // expected-warning{{TRUE}}
}

void less(int m, int n) {
assert_in_range_2(m, n);
if (m <= n)
return;
assert(m > n);
assert_in_wide_range(m - n);
clang_analyzer_eval(n < m); // expected-warning{{TRUE}}
}

void greater_or_equal(int m, int n) {
assert_in_range_2(m, n);
if (m > n)
return;
assert(m <= n);
assert_in_wide_range(m - n);
clang_analyzer_eval(n >= m); // expected-warning{{TRUE}}
}

void greater(int m, int n) {
assert_in_range_2(m, n);
if (m >= n)
return;
assert(m < n);
assert_in_wide_range(m - n);
clang_analyzer_eval(n > m); // expected-warning{{TRUE}}
}

void negate_positive_range(int m, int n) {
if (m - n <= 0)
return;
assert(m - n > 0);
clang_analyzer_eval(n - m < 0); // expected-warning{{TRUE}}
clang_analyzer_eval(n - m > INT_MIN); // expected-warning{{TRUE}}
clang_analyzer_eval(n - m == INT_MIN); // expected-warning{{FALSE}}
}

_Static_assert(INT_MIN == -INT_MIN, "");
void negate_int_min(int m, int n) {
if (m - n != INT_MIN)
return;
assert(m - n == INT_MIN);
clang_analyzer_eval(n - m == INT_MIN); // expected-warning{{TRUE}}
}

void negate_mixed(int m, int n) {
if (m -n > INT_MIN && m - n <= 0)
return;
assert(m - n > 0 || m - n == INT_MIN);
clang_analyzer_eval(n - m <= 0); // expected-warning{{TRUE}}
}

Expand All @@ -106,54 +96,59 @@ void effective_range(int m, int n) {
clang_analyzer_eval(n - m == 0); // expected-warning{{TRUE}}
}

_Static_assert(INT_MIN == -INT_MIN, "");
void effective_range_2(int m, int n) {
assert(m - n <= 0);
assert(n - m <= 0);
clang_analyzer_eval(m - n == 0); // expected-warning{{TRUE}} expected-warning{{FALSE}}
clang_analyzer_eval(n - m == 0); // expected-warning{{TRUE}} expected-warning{{FALSE}}
clang_analyzer_eval(m - n == 0 || m - n == INT_MIN); // expected-warning{{TRUE}}
}

void negate_unsigned_min(unsigned m, unsigned n) {
if (m - n == UINT_MIN) {
clang_analyzer_eval(n - m == UINT_MIN); // expected-warning{{TRUE}}
clang_analyzer_eval(n - m != UINT_MIN); // expected-warning{{FALSE}}
clang_analyzer_eval(n - m > UINT_MIN); // expected-warning{{FALSE}}
clang_analyzer_eval(n - m < UINT_MIN); // expected-warning{{FALSE}}
}
assert(m - n == UINT_MIN);
clang_analyzer_eval(n - m == UINT_MIN); // expected-warning{{TRUE}}
clang_analyzer_eval(n - m != UINT_MIN); // expected-warning{{FALSE}}
clang_analyzer_eval(n - m > UINT_MIN); // expected-warning{{FALSE}}
clang_analyzer_eval(n - m < UINT_MIN); // expected-warning{{FALSE}}
}

_Static_assert(7u - 3u != 3u - 7u, "");
void negate_unsigned_4(unsigned m, unsigned n) {
assert(m - n == 4u);
clang_analyzer_eval(n - m == 4u); // expected-warning{{FALSE}}
clang_analyzer_eval(n - m != 4u); // expected-warning{{TRUE}}
}

_Static_assert(UINT_MID == -UINT_MID, "");
void negate_unsigned_mid(unsigned m, unsigned n) {
if (m - n == UINT_MID) {
clang_analyzer_eval(n - m == UINT_MID); // expected-warning{{TRUE}}
clang_analyzer_eval(n - m != UINT_MID); // expected-warning{{FALSE}}
}
assert(m - n == UINT_MID);
clang_analyzer_eval(n - m == UINT_MID); // expected-warning{{TRUE}}
clang_analyzer_eval(n - m != UINT_MID); // expected-warning{{FALSE}}
}

void negate_unsigned_mid2(unsigned m, unsigned n) {
if (m - n < UINT_MID && m - n > UINT_MIN) {
clang_analyzer_eval(n - m > UINT_MID); // expected-warning{{TRUE}}
clang_analyzer_eval(n - m < UINT_MID); // expected-warning{{FALSE}}
}
assert(UINT_MIN < m - n && m - n < UINT_MID);
clang_analyzer_eval(n - m > UINT_MID); // expected-warning{{TRUE}}
clang_analyzer_eval(n - m <= UINT_MAX); // expected-warning{{TRUE}}
}

_Static_assert(1u - 2u == UINT_MAX, "");
_Static_assert(2u - 1u == 1, "");
void negate_unsigned_max(unsigned m, unsigned n) {
if (m - n == UINT_MAX) {
clang_analyzer_eval(n - m == 1); // expected-warning{{TRUE}}
clang_analyzer_eval(n - m != 1); // expected-warning{{FALSE}}
}
assert(m - n == UINT_MAX);
clang_analyzer_eval(n - m == 1); // expected-warning{{TRUE}}
clang_analyzer_eval(n - m != 1); // expected-warning{{FALSE}}
}

void negate_unsigned_one(unsigned m, unsigned n) {
if (m - n == 1) {
clang_analyzer_eval(n - m == UINT_MAX); // expected-warning{{TRUE}}
clang_analyzer_eval(n - m < UINT_MAX); // expected-warning{{FALSE}}
}
assert(m - n == 1);
clang_analyzer_eval(n - m == UINT_MAX); // expected-warning{{TRUE}}
clang_analyzer_eval(n - m < UINT_MAX); // expected-warning{{FALSE}}
}

// The next code is a repro for the bug PR41588
void negated_unsigned_range(unsigned x, unsigned y) {
clang_analyzer_eval(x - y != 0); // expected-warning{{FALSE}} expected-warning{{TRUE}}
clang_analyzer_eval(y - x != 0); // expected-warning{{FALSE}} expected-warning{{TRUE}}
clang_analyzer_eval(x - y != 0); // expected-warning{{UNKNOWN}}
clang_analyzer_eval(y - x != 0); // expected-warning{{UNKNOWN}}
// expected no assertion on the next line
clang_analyzer_eval(x - y != 0); // expected-warning{{FALSE}} expected-warning{{TRUE}}
clang_analyzer_eval(x - y != 0); // expected-warning{{UNKNOWN}}
}
1 change: 1 addition & 0 deletions clang/test/Analysis/explain-svals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ void test_3(S s) {
void test_4(int x, int y) {
int z;
static int stat;
clang_analyzer_explain(-x); // expected-warning-re{{{{^\- \(argument 'x'\)$}}}}
clang_analyzer_explain(x + 1); // expected-warning-re{{{{^\(argument 'x'\) \+ 1$}}}}
clang_analyzer_explain(1 + y); // expected-warning-re{{{{^\(argument 'y'\) \+ 1$}}}}
clang_analyzer_explain(x + y); // expected-warning-re{{{{^\(argument 'x'\) \+ \(argument 'y'\)$}}}}
Expand Down
2 changes: 2 additions & 0 deletions clang/test/Analysis/expr-inspection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ void foo(int x, unsigned y) {
clang_analyzer_express(x); // expected-warning{{Unable to express}}

clang_analyzer_denote(x, "$x");
clang_analyzer_express(-x); // expected-warning{{-$x}}

clang_analyzer_denote(y, "$y");
clang_analyzer_express(x + y); // expected-warning{{$x + $y}}

Expand Down
23 changes: 23 additions & 0 deletions clang/test/Analysis/unary-sym-expr-no-crash.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// RUN: %clang_analyze_cc1 %s \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config eagerly-assume=false \
// RUN: -analyzer-config support-symbolic-integer-casts=false \
// RUN: -verify

// RUN: %clang_analyze_cc1 %s \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config eagerly-assume=false \
// RUN: -analyzer-config support-symbolic-integer-casts=true \
// RUN: -verify

// expected-no-diagnostics

void clang_analyzer_eval(int);
void clang_analyzer_dump(int);

void crash(int b, long c) {
b = c;
if (b > 0)
if(-b) // should not crash here
;
}
33 changes: 33 additions & 0 deletions clang/test/Analysis/unary-sym-expr-z3-refutation.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// RUN: %clang_analyze_cc1 %s \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config eagerly-assume=true \
// RUN: -verify

// RUN: %clang_analyze_cc1 %s \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config eagerly-assume=true \
// RUN: -analyzer-config support-symbolic-integer-casts=true \
// RUN: -verify

// RUN: %clang_analyze_cc1 %s \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config eagerly-assume=true \
// RUN: -analyzer-config crosscheck-with-z3=true \
// RUN: -verify

// RUN: %clang_analyze_cc1 %s \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config eagerly-assume=true \
// RUN: -analyzer-config crosscheck-with-z3=true \
// RUN: -analyzer-config support-symbolic-integer-casts=true \
// RUN: -verify

// REQUIRES: z3

void k(long L) {
int g = L;
int h = g + 1;
int j;
j += -h < 0; // should not crash
// expected-warning@-1{{garbage}}
}
47 changes: 47 additions & 0 deletions clang/test/Analysis/unary-sym-expr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// RUN: %clang_analyze_cc1 %s \
// RUN: -analyzer-checker=core,debug.ExprInspection \
// RUN: -analyzer-config eagerly-assume=false \
// RUN: -verify

void clang_analyzer_eval(int);
void clang_analyzer_dump(int);

int test(int x, int y) {

clang_analyzer_dump(-x); // expected-warning{{-reg_$0<int x>}}
clang_analyzer_dump(~x); // expected-warning{{~reg_$0<int x>}}
int z = x + y;
clang_analyzer_dump(-z); // expected-warning{{-((reg_$0<int x>) + (reg_$1<int y>))}}
clang_analyzer_dump(-(x + y)); // expected-warning{{-((reg_$0<int x>) + (reg_$1<int y>))}}
clang_analyzer_dump(-x + y); // expected-warning{{(-reg_$0<int x>) + (reg_$1<int y>)}}

if (-x == 0) {
clang_analyzer_eval(-x == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(-x > 0); // expected-warning{{FALSE}}
clang_analyzer_eval(-x < 0); // expected-warning{{FALSE}}
}
if (~y == 0) {
clang_analyzer_eval(~y == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(~y > 0); // expected-warning{{FALSE}}
clang_analyzer_eval(~y < 0); // expected-warning{{FALSE}}
}
(void)(x);
return 42;
}

void test_svalbuilder_simplification(int x, int y) {
if (x + y != 3)
return;
clang_analyzer_eval(-(x + y) == -3); // expected-warning{{TRUE}}
// FIXME Commutativity is not supported yet.
clang_analyzer_eval(-(y + x) == -3); // expected-warning{{UNKNOWN}}
}

int test_fp(int flag) {
int value;
if (flag == 0)
value = 1;
if (-flag == 0)
return value; // no-warning
return 42;
}
14 changes: 14 additions & 0 deletions clang/test/Analysis/z3-crosscheck.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ int foo(int x)
return 0;
}

int unary(int x, long l)
{
int *z = 0;
int y = l;
if ((x & 1) && ((x & 1) ^ 1))
if (-y)
#ifdef NO_CROSSCHECK
return *z; // expected-warning {{Dereference of null pointer (loaded from variable 'z')}}
#else
return *z; // no-warning
#endif
return 0;
}

void g(int d);

void f(int *a, int *b) {
Expand Down