cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
217 lines
6.1 KiB
C++
217 lines
6.1 KiB
C++
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -Wno-tautological-compare -analyzer-config eagerly-assume=false %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 mixedWraparoundBasicCheck(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 mixedSignedness2(int a) {
|
|
if (a != -1)
|
|
return;
|
|
clang_analyzer_eval(a == UINT_MAX); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
void mixedSignedness3(unsigned a) {
|
|
if (a != UINT_MAX)
|
|
return;
|
|
clang_analyzer_eval(a == -1); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
|
|
void multiplicativeBasicTest(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}}
|
|
}
|
|
|
|
void additiveSymSymFolding(int x, int y) {
|
|
// We should simplify 'x - 1' to '0' and handle the comparison,
|
|
// despite both sides being complicated symbols.
|
|
int z = x - 1;
|
|
if (x == 1)
|
|
if (y >= 0)
|
|
clang_analyzer_eval(z <= y); // expected-warning{{TRUE}}
|
|
}
|