llvm-project/clang/test/Analysis/additive-folding.cpp
Richard Trieu 560910c9b8 Improve -Wtautological-constant-out-of-range-compare by taking into account
type conversion between integers.  This allows the warning to be more accurate.

Also, turned the warning off in an analyzer test.  The relavent test cases
are covered by the tests in Sema.

llvm-svn: 167992
2012-11-14 22:50:24 +00:00

196 lines
5.6 KiB
C++

// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -analyzer-constraints=range -Wno-tautological-compare %s
void clang_analyzer_eval(bool);
#define UINT_MAX (~0U)
#define INT_MAX (UINT_MAX & (UINT_MAX >> 1))
#define INT_MIN (-INT_MAX - 1)
//---------------
// Plus/minus
//---------------
void separateExpressions (int a) {
int b = a + 1;
--b;
clang_analyzer_eval(a != 0 && b == 0); // expected-warning{{FALSE}}
}
void oneLongExpression (int a) {
// Expression canonicalization should still allow this to work, even though
// the first term is on the left.
int b = 15 + a + 15 - 10 - 20;
clang_analyzer_eval(a != 0 && b == 0); // expected-warning{{FALSE}}
}
void mixedTypes (int a) {
// Different additive types should not cause crashes when constant-folding.
// This is part of PR7406.
int b = a + 1LL;
clang_analyzer_eval(a != 0 && (b-1) == 0); // not crash, expected-warning{{FALSE}}
int c = a + 1U;
clang_analyzer_eval(a != 0 && (c-1) == 0); // not crash, expected-warning{{FALSE}}
}
//---------------
// Comparisons
//---------------
// Equality and inequality only
void eq_ne (unsigned a) {
if (a == UINT_MAX) {
clang_analyzer_eval(a+1 == 0); // expected-warning{{TRUE}}
clang_analyzer_eval(a-1 == UINT_MAX-1); // expected-warning{{TRUE}}
} else {
clang_analyzer_eval(a+1 != 0); // expected-warning{{TRUE}}
clang_analyzer_eval(a-1 != UINT_MAX-1); // expected-warning{{TRUE}}
}
}
// Mixed typed inequalities (part of PR7406)
// These should not crash.
void mixed_eq_ne (int a) {
if (a == 1) {
clang_analyzer_eval(a+1U == 2); // expected-warning{{TRUE}}
clang_analyzer_eval(a-1U == 0); // expected-warning{{TRUE}}
} else {
clang_analyzer_eval(a+1U != 2); // expected-warning{{TRUE}}
clang_analyzer_eval(a-1U != 0); // expected-warning{{TRUE}}
}
}
// Simple order comparisons with no adjustment
void baselineGT (unsigned a) {
if (a > 0)
clang_analyzer_eval(a != 0); // expected-warning{{TRUE}}
else
clang_analyzer_eval(a == 0); // expected-warning{{TRUE}}
}
void baselineGE (unsigned a) {
if (a >= UINT_MAX)
clang_analyzer_eval(a == UINT_MAX); // expected-warning{{TRUE}}
else
clang_analyzer_eval(a != UINT_MAX); // expected-warning{{TRUE}}
}
void baselineLT (unsigned a) {
if (a < UINT_MAX)
clang_analyzer_eval(a != UINT_MAX); // expected-warning{{TRUE}}
else
clang_analyzer_eval(a == UINT_MAX); // expected-warning{{TRUE}}
}
void baselineLE (unsigned a) {
if (a <= 0)
clang_analyzer_eval(a == 0); // expected-warning{{TRUE}}
else
clang_analyzer_eval(a != 0); // expected-warning{{TRUE}}
}
// Adjustment gives each of these an extra solution!
void adjustedGT (unsigned a) {
clang_analyzer_eval(a-1 > UINT_MAX-1); // expected-warning{{UNKNOWN}}
}
void adjustedGE (unsigned a) {
clang_analyzer_eval(a-1 > UINT_MAX-1); // expected-warning{{UNKNOWN}}
if (a-1 >= UINT_MAX-1)
clang_analyzer_eval(a == UINT_MAX); // expected-warning{{UNKNOWN}}
}
void adjustedLT (unsigned a) {
clang_analyzer_eval(a+1 < 1); // expected-warning{{UNKNOWN}}
}
void adjustedLE (unsigned a) {
clang_analyzer_eval(a+1 <= 1); // expected-warning{{UNKNOWN}}
if (a+1 <= 1)
clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}}
}
// Tautologies
// The negative forms are exercised as well
// because clang_analyzer_eval tests both possibilities.
void tautologies(unsigned a) {
clang_analyzer_eval(a <= UINT_MAX); // expected-warning{{TRUE}}
clang_analyzer_eval(a >= 0); // expected-warning{{TRUE}}
}
// Tautologies from outside the range of the symbol
void tautologiesOutside(unsigned char a) {
clang_analyzer_eval(a <= 0x100); // expected-warning{{TRUE}}
clang_analyzer_eval(a < 0x100); // expected-warning{{TRUE}}
clang_analyzer_eval(a != 0x100); // expected-warning{{TRUE}}
clang_analyzer_eval(a != -1); // expected-warning{{TRUE}}
clang_analyzer_eval(a > -1); // expected-warning{{TRUE}}
clang_analyzer_eval(a >= -1); // expected-warning{{TRUE}}
}
// Wraparound with mixed types. Note that the analyzer assumes
// -fwrapv semantics.
void mixedWraparoundSanityCheck(int a) {
int max = INT_MAX;
int min = INT_MIN;
int b = a + 1;
clang_analyzer_eval(a == max && b != min); // expected-warning{{FALSE}}
}
void mixedWraparoundLE_GT(int a) {
int max = INT_MAX;
int min = INT_MIN;
clang_analyzer_eval((a + 2) <= (max + 1LL)); // expected-warning{{TRUE}}
clang_analyzer_eval((a - 2) > (min - 1LL)); // expected-warning{{TRUE}}
clang_analyzer_eval((a + 2LL) <= max); // expected-warning{{UNKNOWN}}
}
void mixedWraparoundGE_LT(int a) {
int max = INT_MAX;
int min = INT_MIN;
clang_analyzer_eval((a + 2) < (max + 1LL)); // expected-warning{{TRUE}}
clang_analyzer_eval((a - 2) >= (min - 1LL)); // expected-warning{{TRUE}}
clang_analyzer_eval((a - 2LL) >= min); // expected-warning{{UNKNOWN}}
}
void mixedWraparoundEQ_NE(int a) {
int max = INT_MAX;
clang_analyzer_eval((a + 2) != (max + 1LL)); // expected-warning{{TRUE}}
clang_analyzer_eval((a + 2LL) == (max + 1LL)); // expected-warning{{UNKNOWN}}
}
// Mixed-signedness comparisons.
void mixedSignedness(int a, unsigned b) {
int sMin = INT_MIN;
unsigned uMin = INT_MIN;
clang_analyzer_eval(a == sMin && a != uMin); // expected-warning{{FALSE}}
clang_analyzer_eval(b == uMin && b != sMin); // expected-warning{{FALSE}}
}
void multiplicativeSanityTest(int x) {
// At one point we were ignoring the *4 completely -- the constraint manager
// would see x < 8 and then declare the assertion to be known false.
if (x*4 < 8)
return;
clang_analyzer_eval(x == 3); // expected-warning{{UNKNOWN}}
}