-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,unix.Malloc -verify -analyzer-constraints=range %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -analyzer-constraints=range %s
+
+void clang_analyzer_eval(int);
-// These are used to trigger warnings.
-typedef typeof(sizeof(int)) size_t;
-void *malloc(size_t);
-void free(void *);
-#define NULL ((void*)0)
#define UINT_MAX (~0U)
#define INT_MAX (UINT_MAX & (UINT_MAX >> 1))
#define INT_MIN (-INT_MAX - 1)
// solution range across an overflow boundary (Min for <, Max for >).
// This corresponds to one set of branches in RangeConstraintManager.
void smallAdjustmentGT (unsigned a) {
- void *b = NULL;
if (a+2 > 1)
- b = malloc(1);
- if (a == UINT_MAX-1 || a == UINT_MAX)
- return; // no-warning
- else if (a < UINT_MAX-1)
- free(b);
- return; // no-warning
+ clang_analyzer_eval(a < UINT_MAX-1); // expected-warning{{TRUE}}
+ else
+ clang_analyzer_eval(a == UINT_MAX-1 || a == UINT_MAX); // expected-warning{{TRUE}}
}
void smallAdjustmentGE (unsigned a) {
- void *b = NULL;
if (a+2 >= 1)
- b = malloc(1);
- if (a == UINT_MAX-1)
- return; // no-warning
- else if (a < UINT_MAX-1 || a == UINT_MAX)
- free(b);
- return; // no-warning
+ clang_analyzer_eval(a < UINT_MAX-1 || a == UINT_MAX); // expected-warning{{TRUE}}
+ else
+ clang_analyzer_eval(a == UINT_MAX-1); // expected-warning{{TRUE}}
}
void smallAdjustmentLT (unsigned a) {
- void *b = NULL;
if (a+1 < 2)
- b = malloc(1);
- if (a == 0 || a == UINT_MAX)
- free(b);
- return; // no-warning
+ clang_analyzer_eval(a == 0 || a == UINT_MAX); // expected-warning{{TRUE}}
}
void smallAdjustmentLE (unsigned a) {
- void *b = NULL;
if (a+1 <= 2)
- b = malloc(1);
- if (a == 0 || a == 1 || a == UINT_MAX)
- free(b);
- return; // no-warning
+ clang_analyzer_eval(a == 0 || a == 1 || a == UINT_MAX); // expected-warning{{TRUE}}
}
// comparison value over an overflow boundary (Min for <, Max for >).
// This corresponds to one set of branches in RangeConstraintManager.
void largeAdjustmentGT (unsigned a) {
- void *b = NULL;
if (a-2 > UINT_MAX-1)
- b = malloc(1);
- if (a == 1 || a == 0)
- free(b);
- else if (a > 1)
- free(b);
- return; // no-warning
+ clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
+ else
+ clang_analyzer_eval(a != 1); // expected-warning{{TRUE}}
}
void largeAdjustmentGE (unsigned a) {
- void *b = NULL;
if (a-2 >= UINT_MAX-1)
- b = malloc(1);
- if (a > 1)
- return; // no-warning
- else if (a == 1 || a == 0)
- free(b);
- return; // no-warning
+ clang_analyzer_eval(a == 1 || a == 0); // expected-warning{{TRUE}}
+ else
+ clang_analyzer_eval(a > 1); // expected-warning{{TRUE}}
}
void largeAdjustmentLT (unsigned a) {
- void *b = NULL;
if (a+2 < 1)
- b = malloc(1);
- if (a == UINT_MAX-1 || a == UINT_MAX)
- free(b);
- else if (a < UINT_MAX-1)
- return; // no-warning
- return; // no-warning
+ clang_analyzer_eval(a == UINT_MAX-1); // expected-warning{{TRUE}}
+ else
+ clang_analyzer_eval(a != UINT_MAX-1); // expected-warning{{TRUE}}
}
void largeAdjustmentLE (unsigned a) {
- void *b = NULL;
if (a+2 <= 1)
- b = malloc(1);
- if (a < UINT_MAX-1)
- return; // no-warning
- else if (a == UINT_MAX-1 || a == UINT_MAX)
- free(b);
- return; // no-warning
+ clang_analyzer_eval(a == UINT_MAX-1 || a == UINT_MAX); // expected-warning{{TRUE}}
+ else
+ clang_analyzer_eval(a < UINT_MAX-1); // expected-warning{{TRUE}}
}
// Test the nine cases in RangeConstraintManager's pinning logic.
+// For out-of-range tautologies, it may be the negation that actually
+// triggers the case in question.
void mixedComparisons1(signed char a) {
// Case 1: The range is entirely below the symbol's range.
int min = INT_MIN;
- if ((a - 2) < (min + 5LL))
- return; // expected-warning{{never executed}}
+ clang_analyzer_eval((a - 2) >= (min + 5LL)); // expected-warning{{TRUE}}
- if (a == 0)
- return; // no-warning
- if (a == 0x7F)
- return; // no-warning
- if (a == -0x80)
- return; // no-warning
- return; // no-warning
+ clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}}
}
void mixedComparisons2(signed char a) {
// Case 2: Only the lower end of the range is outside.
+ clang_analyzer_eval((a - 5) < (-0x81LL)); // expected-warning{{UNKNOWN}}
+
if ((a - 5) < (-0x81LL)) {
- if (a == 0)
- return; // expected-warning{{never executed}}
- if (a == 0x7F)
- return; // expected-warning{{never executed}}
- if (a == -0x80)
- return; // no-warning
- return; // no-warning
- } else {
- return; // no-warning
+ clang_analyzer_eval(a == 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(a == 0x7F); // expected-warning{{FALSE}}
+ clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}}
}
}
void mixedComparisons3(signed char a) {
// Case 3: The entire symbol range is covered.
- if ((a - 0x200) < -0x100LL) {
- if (a == 0)
- return; // no-warning
- if (a == 0x7F)
- return; // no-warning
- if (a == -0x80)
- return; // no-warning
- return; // no-warning
- } else {
- return; // expected-warning{{never executed}}
- }
+ clang_analyzer_eval((a - 0x200) < -0x100LL); // expected-warning{{TRUE}}
+
+ clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}}
}
void mixedComparisons4(signed char a) {
// Case 4: The range wraps around, but the lower wrap is out-of-range.
+ clang_analyzer_eval((a - 5) > 0LL); // expected-warning{{UNKNOWN}}
+
if ((a - 5) > 0LL) {
- if (a == 0)
- return; // expected-warning{{never executed}}
- if (a == 0x7F)
- return; // no-warning
- if (a == -0x80)
- return; // expected-warning{{never executed}}
- return; // no-warning
- } else {
- return; // no-warning
+ clang_analyzer_eval(a == 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == -0x80); // expected-warning{{FALSE}}
}
}
void mixedComparisons5(signed char a) {
- // Case 5a: The range is inside and does not wrap.
- if ((a + 5) == 0LL) {
- if (a == 0)
- return; // expected-warning{{never executed}}
- if (a == 0x7F)
- return; // expected-warning{{never executed}}
- if (a == -0x80)
- return; // expected-warning{{never executed}}
- return; // no-warning
- } else {
- return; // no-warning
- }
-}
+ // Case 5: The range is inside and may or may not wrap.
+ clang_analyzer_eval((a + 5) == 0LL); // expected-warning{{UNKNOWN}}
-void mixedComparisons5Wrap(signed char a) {
- // Case 5b: The range is inside and does wrap.
- if ((a + 5) != 0LL) {
- if (a == 0)
- return; // no-warning
- if (a == 0x7F)
- return; // no-warning
- if (a == -0x80)
- return; // no-warning
- return; // no-warning
+ if ((a + 5) == 0LL) {
+ clang_analyzer_eval(a == 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(a == 0x7F); // expected-warning{{FALSE}}
+ clang_analyzer_eval(a == -0x80); // expected-warning{{FALSE}}
} else {
- return; // no-warning
+ clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}}
}
}
void mixedComparisons6(signed char a) {
// Case 6: Only the upper end of the range is outside.
+ clang_analyzer_eval((a + 5) > 0x81LL); // expected-warning{{UNKNOWN}}
+
if ((a + 5) > 0x81LL) {
- if (a == 0)
- return; // expected-warning{{never executed}}
- if (a == 0x7F)
- return; // no-warning
- if (a == -0x80)
- return; // expected-warning{{never executed}}
- return; // no-warning
- } else {
- return; // no-warning
+ clang_analyzer_eval(a == 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == -0x80); // expected-warning{{FALSE}}
}
}
// Case 7: The range wraps around but is entirely outside the symbol's range.
int min = INT_MIN;
- if ((a + 2) < (min + 5LL))
- return; // expected-warning{{never executed}}
+ clang_analyzer_eval((a + 2) >= (min + 5LL)); // expected-warning{{TRUE}}
- if (a == 0)
- return; // no-warning
- if (a == 0x7F)
- return; // no-warning
- if (a == -0x80)
- return; // no-warning
- return; // no-warning
+ clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}}
}
void mixedComparisons8(signed char a) {
// Case 8: The range wraps, but the upper wrap is out of range.
+ clang_analyzer_eval((a + 5) < 0LL); // expected-warning{{UNKNOWN}}
+
if ((a + 5) < 0LL) {
- if (a == 0)
- return; // expected-warning{{never executed}}
- if (a == 0x7F)
- return; // expected-warning{{never executed}}
- if (a == -0x80)
- return; // no-warning
- return; // no-warning
- } else {
- return; // no-warning
+ clang_analyzer_eval(a == 0); // expected-warning{{FALSE}}
+ clang_analyzer_eval(a == 0x7F); // expected-warning{{FALSE}}
+ clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}}
}
}
// Case 9: The range is entirely above the symbol's range.
int max = INT_MAX;
- if ((a + 2) > (max - 5LL))
- return; // expected-warning{{never executed}}
+ clang_analyzer_eval((a + 2) <= (max - 5LL)); // expected-warning{{TRUE}}
- if (a == 0)
- return; // no-warning
- if (a == 0x7F)
- return; // no-warning
- if (a == -0x80)
- return; // no-warning
- return; // no-warning
+ clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == 0x7F); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == -0x80); // expected-warning{{UNKNOWN}}
}
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,unix.Malloc -verify -analyzer-constraints=basic %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode,unix.Malloc -verify -analyzer-constraints=range %s
-
-// These are used to trigger warnings.
-typedef typeof(sizeof(int)) size_t;
-void *malloc(size_t);
-void free(void *);
-#define NULL ((void*)0)
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -analyzer-constraints=basic -Wno-tautological-compare %s
+// 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)
int b = a + 1;
--b;
- void *buf = malloc(1);
- if (a != 0 && b == 0)
- return; // expected-warning{{never executed}}
- free(buf);
+ clang_analyzer_eval(a != 0 && b == 0); // expected-warning{{FALSE}}
}
void oneLongExpression (int a) {
// the first term is on the left.
int b = 15 + a + 15 - 10 - 20;
- void *buf = malloc(1);
- if (a != 0 && b == 0)
- return; // expected-warning{{never executed}}
- free(buf);
+ clang_analyzer_eval(a != 0 && b == 0); // expected-warning{{FALSE}}
}
void mixedTypes (int a) {
- void *buf = malloc(1);
-
// Different additive types should not cause crashes when constant-folding.
// This is part of PR7406.
int b = a + 1LL;
- if (a != 0 && (b-1) == 0) // not crash
- return; // expected-warning{{never executed}}
+ clang_analyzer_eval(a != 0 && (b-1) == 0); // not crash, expected-warning{{FALSE}}
int c = a + 1U;
- if (a != 0 && (c-1) == 0) // not crash
- return; // expected-warning{{never executed}}
-
- free(buf);
+ clang_analyzer_eval(a != 0 && (c-1) == 0); // not crash, expected-warning{{FALSE}}
}
//---------------
// Equality and inequality only
void eq_ne (unsigned a) {
- void *b = NULL;
- if (a == UINT_MAX)
- b = malloc(1);
- if (a+1 != 0)
- return; // no-warning
- if (a-1 != UINT_MAX-1)
- return; // no-warning
- free(b);
-}
-
-void ne_eq (unsigned a) {
- void *b = NULL;
- if (a != UINT_MAX)
- b = malloc(1);
- if (a+1 == 0)
- return; // no-warning
- if (a-1 == UINT_MAX-1)
- return; // no-warning
- free(b);
+ 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) {
- void *b = NULL;
- if (a == 1)
- b = malloc(1);
- if (a+1U != 2)
- return; // no-warning
- if (a-1U != 0)
- return; // expected-warning{{never executed}}
- free(b);
-}
-
-void mixed_ne_eq (int a) {
- void *b = NULL;
- if (a != 1)
- b = malloc(1);
- if (a+1U == 2)
- return; // no-warning
- if (a-1U == 0)
- return; // expected-warning{{never executed}}
- free(b);
+ 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) {
- void *b = NULL;
if (a > 0)
- b = malloc(1);
- if (a == 0)
- return; // no-warning
- free(b);
+ clang_analyzer_eval(a != 0); // expected-warning{{TRUE}}
+ else
+ clang_analyzer_eval(a == 0); // expected-warning{{TRUE}}
}
void baselineGE (unsigned a) {
- void *b = NULL;
if (a >= UINT_MAX)
- b = malloc(1);
- if (a == UINT_MAX)
- free(b);
- return; // no-warning
+ clang_analyzer_eval(a == UINT_MAX); // expected-warning{{TRUE}}
+ else
+ clang_analyzer_eval(a != UINT_MAX); // expected-warning{{TRUE}}
}
void baselineLT (unsigned a) {
- void *b = NULL;
if (a < UINT_MAX)
- b = malloc(1);
- if (a == UINT_MAX)
- return; // no-warning
- free(b);
+ clang_analyzer_eval(a != UINT_MAX); // expected-warning{{TRUE}}
+ else
+ clang_analyzer_eval(a == UINT_MAX); // expected-warning{{TRUE}}
}
void baselineLE (unsigned a) {
- void *b = NULL;
if (a <= 0)
- b = malloc(1);
- if (a == 0)
- free(b);
- return; // no-warning
+ 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) {
- void *b = NULL;
- if (a-1 > UINT_MAX-1)
- b = malloc(1);
- return; // expected-warning{{leak}}
+ clang_analyzer_eval(a-1 > UINT_MAX-1); // expected-warning{{UNKNOWN}}
}
void adjustedGE (unsigned a) {
- void *b = NULL;
+ clang_analyzer_eval(a-1 > UINT_MAX-1); // expected-warning{{UNKNOWN}}
+
if (a-1 >= UINT_MAX-1)
- b = malloc(1);
- if (a == UINT_MAX)
- free(b);
- return; // expected-warning{{leak}}
+ clang_analyzer_eval(a == UINT_MAX); // expected-warning{{UNKNOWN}}
}
void adjustedLT (unsigned a) {
- void *b = NULL;
- if (a+1 < 1)
- b = malloc(1);
- return; // expected-warning{{leak}}
+ clang_analyzer_eval(a+1 < 1); // expected-warning{{UNKNOWN}}
}
void adjustedLE (unsigned a) {
- void *b = NULL;
+ clang_analyzer_eval(a+1 <= 1); // expected-warning{{UNKNOWN}}
+
if (a+1 <= 1)
- b = malloc(1);
- if (a == 0)
- free(b);
- return; // expected-warning{{leak}}
+ clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}}
}
// Tautologies
-void tautologyGT (unsigned a) {
- void *b = malloc(1);
- if (a > UINT_MAX)
- return; // no-warning
- free(b);
-}
-
-void tautologyGE (unsigned a) {
- void *b = malloc(1);
- if (a >= 0) // expected-warning{{always true}}
- free(b);
- return; // no-warning
-}
-
-void tautologyLT (unsigned a) {
- void *b = malloc(1);
- if (a < 0) // expected-warning{{always false}}
- return; // expected-warning{{never executed}}
- free(b);
-}
-
-void tautologyLE (unsigned a) {
- void *b = malloc(1);
- if (a <= UINT_MAX)
- free(b);
- return; // no-warning
+// 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 tautologyOutsideGT(unsigned char a) {
- void *b = malloc(1);
- if (a > 0x100)
- return; // expected-warning{{never executed}}
- if (a > -1)
- free(b);
- return; // no-warning
-}
+void tautologiesOutside(unsigned char a) {
+ clang_analyzer_eval(a <= 0x100); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a < 0x100); // expected-warning{{TRUE}}
-void tautologyOutsideGE(unsigned char a) {
- void *b = malloc(1);
- if (a >= 0x100)
- return; // expected-warning{{never executed}}
- if (a >= -1)
- free(b);
- return; // no-warning
-}
+ clang_analyzer_eval(a != 0x100); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a != -1); // expected-warning{{TRUE}}
-void tautologyOutsideLT(unsigned char a) {
- void *b = malloc(1);
- if (a < -1)
- return; // expected-warning{{never executed}}
- if (a < 0x100)
- free(b);
- return; // no-warning
-}
-
-void tautologyOutsideLE (unsigned char a) {
- void *b = malloc(1);
- if (a <= -1)
- return; // expected-warning{{never executed}}
- if (a <= 0x100)
- free(b);
- return; // no-warning
-}
-
-void tautologyOutsideEQ(unsigned char a) {
- if (a == 0x100)
- malloc(1); // expected-warning{{never executed}}
- if (a == -1)
- malloc(1); // expected-warning{{never executed}}
-}
-
-void tautologyOutsideNE(unsigned char a) {
- void *sentinel = malloc(1);
- if (a != 0x100)
- free(sentinel);
-
- sentinel = malloc(1);
- if (a != -1)
- free(sentinel);
+ clang_analyzer_eval(a > -1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a >= -1); // expected-warning{{TRUE}}
}
int min = INT_MIN;
int b = a + 1;
- if (a == max && b != min)
- return; // expected-warning{{never executed}}
-}
-
-void mixedWraparoundGT(int a) {
- int max = INT_MAX;
-
- if ((a + 2) > (max + 1LL))
- return; // expected-warning{{never executed}}
+ clang_analyzer_eval(a == max && b != min); // expected-warning{{FALSE}}
}
-void mixedWraparoundGE(int a) {
+void mixedWraparoundLE_GT(int a) {
int max = INT_MAX;
int min = INT_MIN;
- if ((a + 2) >= (max + 1LL))
- return; // expected-warning{{never executed}}
-
- void *sentinel = malloc(1);
- if ((a - 2LL) >= min)
- free(sentinel);
- return; // expected-warning{{leak}}
-}
-
-void mixedWraparoundLT(int a) {
- int min = INT_MIN;
-
- if ((a - 2) < (min - 1LL))
- return; // expected-warning{{never executed}}
+ 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 mixedWraparoundLE(int a) {
+void mixedWraparoundGE_LT(int a) {
int max = INT_MAX;
int min = INT_MIN;
- if ((a - 2) <= (min - 1LL))
- return; // expected-warning{{never executed}}
-
- void *sentinel = malloc(1);
- if ((a + 2LL) <= max)
- free(sentinel);
- return; // expected-warning{{leak}}
-}
-
-void mixedWraparoundEQ(int a) {
- int max = INT_MAX;
-
- if ((a + 2) == (max + 1LL))
- return; // expected-warning{{never executed}}
+ 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 mixedWraparoundNE(int a) {
+void mixedWraparoundEQ_NE(int a) {
int max = INT_MAX;
- void *sentinel = malloc(1);
- if ((a + 2) != (max + 1LL))
- free(sentinel);
- return; // no-warning
+ clang_analyzer_eval((a + 2) != (max + 1LL)); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a + 2LL) == (max + 1LL)); // expected-warning{{UNKNOWN}}
}
void mixedSignedness(int a, unsigned b) {
int sMin = INT_MIN;
unsigned uMin = INT_MIN;
- if (a == sMin && a != uMin)
- return; // expected-warning{{never executed}}
- if (b == uMin && b != sMin)
- return; // expected-warning{{never executed}}
+
+ clang_analyzer_eval(a == sMin && a != uMin); // expected-warning{{FALSE}}
+ clang_analyzer_eval(b == uMin && b != sMin); // expected-warning{{FALSE}}
}
// turning the symbol into a ConcreteInt, rather than ExprEngine.
// Test relational operators.
- if ((local + 1) < 2)
- malloc(1); // expected-warning{{never executed}}
- if (2 > (local + 1))
- malloc(1); // expected-warning{{never executed}}
+ clang_analyzer_eval((local + 1) >= 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval(2 <= (local + 1)); // expected-warning{{TRUE}}
// Test equality operators.
- if ((local + 1) == 1)
- malloc(1); // expected-warning{{never executed}}
- if (1 == (local + 1))
- malloc(1); // expected-warning{{never executed}}
+ clang_analyzer_eval((local + 1) != 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(1 != (local + 1)); // expected-warning{{TRUE}}
}
void PR12206_truncation(signed char x) {
signed int value = 1 + (1 << 8);
// Test relational operators.
- if ((local + 1) >= value)
- malloc(1); // expected-warning{{never executed}}
- if (value <= (local + 1))
- malloc(1); // expected-warning{{never executed}}
+ clang_analyzer_eval((local + 1) < value); // expected-warning{{TRUE}}
+ clang_analyzer_eval(value > (local + 1)); // expected-warning{{TRUE}}
// Test equality operators.
- if ((local + 1) == value)
- malloc(1); // expected-warning{{never executed}}
- if (value == (local + 1))
- malloc(1); // expected-warning{{never executed}}
+ clang_analyzer_eval((local + 1) != value); // expected-warning{{TRUE}}
+ clang_analyzer_eval(value != (local + 1)); // expected-warning{{TRUE}}
}
void multiplicativeSanityTest(int x) {
// At one point we were ignoring the *4 completely -- the constraint manager
- // would see x < 8 and then declare the next part unreachable.
+ // would see x < 8 and then declare the assertion to be known false.
if (x*4 < 8)
return;
- if (x == 3)
- malloc(1);
- return; // expected-warning{{leak}}
+
+ clang_analyzer_eval(x == 3); // expected-warning{{UNKNOWN}}
}
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,experimental.deadcode.UnreachableCode -analyzer-store=region -analyzer-constraints=basic -verify %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,experimental.deadcode.UnreachableCode -analyzer-store=region -analyzer-constraints=range -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=range -verify %s
+
+void clang_analyzer_eval(int);
int string_literal_init() {
char a[] = "abc";
char b[2] = "abc"; // expected-warning{{too long}}
char c[5] = "abc";
- if (a[1] != 'b')
- return 0; // expected-warning{{never executed}}
- if (b[1] != 'b')
- return 0; // expected-warning{{never executed}}
- if (c[1] != 'b')
- return 0; // expected-warning{{never executed}}
+ clang_analyzer_eval(a[1] == 'b'); // expected-warning{{TRUE}}
+ clang_analyzer_eval(b[1] == 'b'); // expected-warning{{TRUE}}
+ clang_analyzer_eval(c[1] == 'b'); // expected-warning{{TRUE}}
- if (a[3] != 0)
- return 0; // expected-warning{{never executed}}
- if (c[3] != 0)
- return 0; // expected-warning{{never executed}}
+ clang_analyzer_eval(a[3] == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(c[3] == 0); // expected-warning{{TRUE}}
- if (c[4] != 0)
- return 0; // expected-warning{{never executed}}
+ clang_analyzer_eval(c[4] == 0); // expected-warning{{TRUE}}
return 42;
}
void struct_as_array() {
- struct simple { int x; };
+ struct simple { int x; int y; };
struct simple a;
struct simple *p = &a;
+
p->x = 5;
- if (!p[0].x)
- return; // expected-warning{{never executed}}
- if (p[0].x)
- return; // no-warning
+ clang_analyzer_eval(a.x == 5); // expected-warning{{TRUE}}
+ clang_analyzer_eval(p[0].x == 5); // expected-warning{{TRUE}}
+
+ p[0].y = 5;
+ clang_analyzer_eval(a.y == 5); // expected-warning{{TRUE}}
+ clang_analyzer_eval(p->y == 5); // expected-warning{{TRUE}}
}
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store region -analyzer-inline-call -cfg-add-initializers -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store region -analyzer-ipa=inlining -cfg-add-initializers -verify %s
// XFAIL: *
+void clang_analyzer_eval(bool);
+
class A {
int x;
public:
void f() {
B b;
- if (b.getx() != 0) {
- int *p = 0;
- *p = 0; // no-warning
- }
+ clang_analyzer_eval(b.getx() == 0); // expected-warning{{TRUE}}
}
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,experimental.unix.cstring -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,experimental.unix.cstring -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,experimental.unix.cstring -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring.NullArg,experimental.unix.cstring.OutOfBounds,experimental.unix.cstring.BufferOverlap,experimental.unix.cstring.NotNullTerminated -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
//===----------------------------------------------------------------------===
// Declarations
typedef typeof(sizeof(int)) size_t;
+void clang_analyzer_eval(int);
+
//===----------------------------------------------------------------------===
// memcpy()
//===----------------------------------------------------------------------===
memcpy(dst, src, 4); // no-warning
- if (memcpy(dst, src, 4) != dst) {
- (void)*(char*)0; // no-warning
- }
+ clang_analyzer_eval(memcpy(dst, src, 4) == dst); // expected-warning{{TRUE}}
- if (dst[0] != 0)
- (void)*(char*)0; // expected-warning{{null}}
+ // If we actually model the copy, we can make this known.
+ // The important thing for now is that the old value has been invalidated.
+ clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
}
void memcpy1 () {
void memcpy_unknown_size (size_t n) {
char a[4], b[4] = {1};
- if (memcpy(a, b, n) != a)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(memcpy(a, b, n) == a); // expected-warning{{TRUE}}
}
void memcpy_unknown_size_warn (size_t n) {
char a[4];
- if (memcpy(a, 0, n) != a) // expected-warning{{Null pointer argument in call to memory copy function}}
- (void)*(char*)0; // no-warning
+ void *result = memcpy(a, 0, n); // expected-warning{{Null pointer argument in call to memory copy function}}
+ clang_analyzer_eval(result == a); // no-warning (above is fatal)
}
//===----------------------------------------------------------------------===
mempcpy(dst, src, 4); // no-warning
- if (mempcpy(dst, src, 4) != &dst[4]) {
- (void)*(char*)0; // no-warning
- }
+ clang_analyzer_eval(mempcpy(dst, src, 4) == &dst[4]); // expected-warning{{TRUE}}
- if (dst[0] != 0)
- (void)*(char*)0; // expected-warning{{null}}
+ // If we actually model the copy, we can make this known.
+ // The important thing for now is that the old value has been invalidated.
+ clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
}
void mempcpy1 () {
void mempcpy_unknown_size_warn (size_t n) {
char a[4];
- if (mempcpy(a, 0, n) != a) // expected-warning{{Null pointer argument in call to memory copy function}}
- (void)*(char*)0; // no-warning
+ void *result = mempcpy(a, 0, n); // expected-warning{{Null pointer argument in call to memory copy function}}
+ clang_analyzer_eval(result == a); // no-warning (above is fatal)
}
void mempcpy_unknownable_size (char *src, float n) {
memmove(dst, src, 4); // no-warning
- if (memmove(dst, src, 4) != dst) {
- (void)*(char*)0; // no-warning
- }
+ clang_analyzer_eval(memmove(dst, src, 4) == dst); // expected-warning{{TRUE}}
- if (dst[0] != 0)
- (void)*(char*)0; // expected-warning{{null}}
+ // If we actually model the copy, we can make this known.
+ // The important thing for now is that the old value has been invalidated.
+ clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
}
void memmove1 () {
// __builtin_bcmp is not defined with const in Builtins.def.
int bcmp(/*const*/ void *s1, /*const*/ void *s2, size_t n);
#define memcmp bcmp
-
+//
#else /* VARIANT */
#define memcmp BUILTIN(memcmp)
void memcmp3 () {
char a[] = {1, 2, 3, 4};
- if (memcmp(a, a, 4))
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(memcmp(a, a, 4) == 0); // expected-warning{{TRUE}}
}
void memcmp4 (char *input) {
char a[] = {1, 2, 3, 4};
- if (memcmp(a, input, 4))
- (void)*(char*)0; // expected-warning{{null}}
+ clang_analyzer_eval(memcmp(a, input, 4) == 0); // expected-warning{{UNKNOWN}}
}
void memcmp5 (char *input) {
char a[] = {1, 2, 3, 4};
- if (memcmp(a, 0, 0)) // no-warning
- (void)*(char*)0; // no-warning
- if (memcmp(0, a, 0)) // no-warning
- (void)*(char*)0; // no-warning
- if (memcmp(a, input, 0)) // no-warning
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(memcmp(a, 0, 0) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(memcmp(0, a, 0) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(memcmp(a, input, 0) == 0); // expected-warning{{TRUE}}
}
void memcmp6 (char *a, char *b, size_t n) {
int result = memcmp(a, b, n);
if (result != 0)
- return;
- if (n == 0)
- (void)*(char*)0; // expected-warning{{null}}
+ clang_analyzer_eval(n != 0); // expected-warning{{TRUE}}
+ // else
+ // analyzer_assert_unknown(n == 0);
+
+ // We can't do the above comparison because n has already been constrained.
+ // On one path n == 0, on the other n != 0.
}
int memcmp7 (char *a, size_t x, size_t y, size_t n) {
bcopy(src, dst, 4); // no-warning
- if (dst[0] != 0)
- (void)*(char*)0; // expected-warning{{null}}
+ // If we actually model the copy, we can make this known.
+ // The important thing for now is that the old value has been invalidated.
+ clang_analyzer_eval(dst[0] != 0); // expected-warning{{UNKNOWN}}
}
void bcopy1 () {
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.deadcode.UnreachableCode -Wno-null-dereference -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
-// Trigger a warning if the analyzer reaches this point in the control flow.
-#define WARN ((void)*(char*)0)
+void clang_analyzer_eval(int);
// There should be no warnings unless otherwise indicated.
// Sema can already catch the simple comparison a==a,
// since that's usually a logic error (and not path-dependent).
int b = a;
- if (!(b==a)) WARN; // expected-warning{{never executed}}
- if (!(b>=a)) WARN; // expected-warning{{never executed}}
- if (!(b<=a)) WARN; // expected-warning{{never executed}}
- if (b!=a) WARN; // expected-warning{{never executed}}
- if (b>a) WARN; // expected-warning{{never executed}}
- if (b<a) WARN; // expected-warning{{never executed}}
+ clang_analyzer_eval(b == a); // expected-warning{{TRUE}}
+ clang_analyzer_eval(b >= a); // expected-warning{{TRUE}}
+ clang_analyzer_eval(b <= a); // expected-warning{{TRUE}}
+ clang_analyzer_eval(b != a); // expected-warning{{FALSE}}
+ clang_analyzer_eval(b > a); // expected-warning{{FALSE}}
+ clang_analyzer_eval(b < a); // expected-warning{{FALSE}}
}
void testSelfOperations (int a) {
- if ((a|a) != a) WARN; // expected-warning{{never executed}}
- if ((a&a) != a) WARN; // expected-warning{{never executed}}
- if ((a^a) != 0) WARN; // expected-warning{{never executed}}
- if ((a-a) != 0) WARN; // expected-warning{{never executed}}
+ clang_analyzer_eval((a|a) == a); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a&a) == a); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a^a) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a-a) == 0); // expected-warning{{TRUE}}
}
void testIdempotent (int a) {
- if ((a*1) != a) WARN; // expected-warning{{never executed}}
- if ((a/1) != a) WARN; // expected-warning{{never executed}}
- if ((a+0) != a) WARN; // expected-warning{{never executed}}
- if ((a-0) != a) WARN; // expected-warning{{never executed}}
- if ((a<<0) != a) WARN; // expected-warning{{never executed}}
- if ((a>>0) != a) WARN; // expected-warning{{never executed}}
- if ((a^0) != a) WARN; // expected-warning{{never executed}}
- if ((a&(~0)) != a) WARN; // expected-warning{{never executed}}
- if ((a|0) != a) WARN; // expected-warning{{never executed}}
+ clang_analyzer_eval((a*1) == a); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a/1) == a); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a+0) == a); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a-0) == a); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a<<0) == a); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a>>0) == a); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a^0) == a); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a&(~0)) == a); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a|0) == a); // expected-warning{{TRUE}}
}
void testReductionToConstant (int a) {
- if ((a*0) != 0) WARN; // expected-warning{{never executed}}
- if ((a&0) != 0) WARN; // expected-warning{{never executed}}
- if ((a|(~0)) != (~0)) WARN; // expected-warning{{never executed}}
+ clang_analyzer_eval((a*0) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a&0) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval((a|(~0)) == (~0)); // expected-warning{{TRUE}}
}
void testSymmetricIntSymOperations (int a) {
- if ((2+a) != (a+2)) WARN; // expected-warning{{never executed}}
- if ((2*a) != (a*2)) WARN; // expected-warning{{never executed}}
- if ((2&a) != (a&2)) WARN; // expected-warning{{never executed}}
- if ((2^a) != (a^2)) WARN; // expected-warning{{never executed}}
- if ((2|a) != (a|2)) WARN; // expected-warning{{never executed}}
+ clang_analyzer_eval((2+a) == (a+2)); // expected-warning{{TRUE}}
+ clang_analyzer_eval((2*a) == (a*2)); // expected-warning{{TRUE}}
+ clang_analyzer_eval((2&a) == (a&2)); // expected-warning{{TRUE}}
+ clang_analyzer_eval((2^a) == (a^2)); // expected-warning{{TRUE}}
+ clang_analyzer_eval((2|a) == (a|2)); // expected-warning{{TRUE}}
}
void testAsymmetricIntSymOperations (int a) {
- if (((~0) >> a) != (~0)) WARN; // expected-warning{{never executed}}
- if ((0 >> a) != 0) WARN; // expected-warning{{never executed}}
- if ((0 << a) != 0) WARN; // expected-warning{{never executed}}
+ clang_analyzer_eval(((~0) >> a) == (~0)); // expected-warning{{TRUE}}
+ clang_analyzer_eval((0 >> a) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval((0 << a) == 0); // expected-warning{{TRUE}}
// Unsigned right shift shifts in zeroes.
- if ((((unsigned)(~0)) >> ((unsigned) a)) != ((unsigned)(~0)))
- WARN; // expected-warning{{}}
+ clang_analyzer_eval(((~0U) >> a) != (~0U)); // expected-warning{{UNKNOWN}}
}
void testLocations (char *a) {
char *b = a;
- if (!(b==a)) WARN; // expected-warning{{never executed}}
- if (!(b>=a)) WARN; // expected-warning{{never executed}}
- if (!(b<=a)) WARN; // expected-warning{{never executed}}
- if (b!=a) WARN; // expected-warning{{never executed}}
- if (b>a) WARN; // expected-warning{{never executed}}
- if (b<a) WARN; // expected-warning{{never executed}}
- if (b-a) WARN; // expected-warning{{never executed}}
+ clang_analyzer_eval(b == a); // expected-warning{{TRUE}}
+ clang_analyzer_eval(b >= a); // expected-warning{{TRUE}}
+ clang_analyzer_eval(b <= a); // expected-warning{{TRUE}}
+ clang_analyzer_eval(b != a); // expected-warning{{FALSE}}
+ clang_analyzer_eval(b > a); // expected-warning{{FALSE}}
+ clang_analyzer_eval(b < a); // expected-warning{{FALSE}}
}
void testMixedTypeComparisons (char a, unsigned long b) {
if (a != 0) return;
if (b != 0x100) return;
- if (a > b) WARN; // expected-warning{{never executed}}
- if (b < a) WARN; // expected-warning{{never executed}}
- if (a == b) WARN; // expected-warning{{never executed}}
+ clang_analyzer_eval(a <= b); // expected-warning{{TRUE}}
+ clang_analyzer_eval(b >= a); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a != b); // expected-warning{{TRUE}}
}
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store region -cfg-add-initializers -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store region -cfg-add-initializers -verify %s
+
+void clang_analyzer_eval(bool);
class A {
int x;
};
A::A() : x(0) {
- if (x != 0) {
- int *p = 0;
- *p = 0; // no-warning
- }
+ clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}
}
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-inline-call -analyzer-store region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-ipa=inlining -analyzer-store region -verify %s
// XFAIL: *
+void clang_analyzer_eval(bool);
+
struct A {
int x;
A(int a) { x = a; }
void f1() {
A x(3);
- if (x.getx() == 3) {
- int *p = 0;
- *p = 3; // expected-warning{{Dereference of null pointer}}
- } else {
- int *p = 0;
- *p = 3; // no-warning
- }
+ clang_analyzer_eval(x.getx() == 3); // expected-warning{{TRUE}}
}
void f2() {
const A &x = A(3);
- if (x.getx() == 3) {
- int *p = 0;
- *p = 3; // expected-warning{{Dereference of null pointer}}
- } else {
- int *p = 0;
- *p = 3; // no-warning
- }
+ clang_analyzer_eval(x.getx() == 3); // expected-warning{{TRUE}}
}
void f3() {
const A &x = (A)3;
- if (x.getx() == 3) {
- int *p = 0;
- *p = 3; // expected-warning{{Dereference of null pointer}}
- } else {
- int *p = 0;
- *p = 3; // no-warning
- }
+ clang_analyzer_eval(x.getx() == 3); // expected-warning{{TRUE}}
}
-// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.core.FixedAddr,experimental.core.PointerArithm,experimental.core.PointerSub -analyzer-store=region -verify -triple x86_64-apple-darwin9 %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.core.FixedAddr,experimental.core.PointerArithm,experimental.core.PointerSub -analyzer-store=region -verify -triple i686-apple-darwin9 %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.core.FixedAddr,experimental.core.PointerArithm,experimental.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple x86_64-apple-darwin9 %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.core.FixedAddr,experimental.core.PointerArithm,experimental.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple i686-apple-darwin9 %s
-// Used to trigger warnings for unreachable paths.
-#define WARN do { int a, b; int c = &b-&a; } while (0)
+void clang_analyzer_eval(int);
void f1() {
int a[10];
void null_operand(int *a) {
start:
// LHS is a label, RHS is NULL
- if (&&start == 0)
- WARN; // no-warning
- if (&&start < 0)
- WARN; // no-warning
- if (&&start <= 0)
- WARN; // no-warning
- if (!(&&start != 0))
- WARN; // no-warning
- if (!(&&start > 0))
- WARN; // no-warning
- if (!(&&start >= 0))
- WARN; // no-warning
- if (!(&&start - 0))
- WARN; // no-warning
+ clang_analyzer_eval(&&start != 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(&&start >= 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(&&start > 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval((&&start - 0) != 0); // expected-warning{{TRUE}}
// LHS is a non-symbolic value, RHS is NULL
- if (&a == 0)
- WARN; // no-warning
- if (&a < 0)
- WARN; // no-warning
- if (&a <= 0)
- WARN; // no-warning
- if (!(&a != 0))
- WARN; // no-warning
- if (!(&a > 0))
- WARN; // no-warning
- if (!(&a >= 0))
- WARN; // no-warning
-
- if (!(&a - 0)) // expected-warning{{Pointer arithmetic done on non-array variables}}
- WARN; // no-warning
+ clang_analyzer_eval(&a != 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(&a >= 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(&a > 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval((&a - 0) != 0); // expected-warning{{TRUE}} expected-warning{{Pointer arithmetic done on non-array variables}}
// LHS is NULL, RHS is non-symbolic
// The same code is used for labels and non-symbolic values.
- if (0 == &a)
- WARN; // no-warning
- if (0 > &a)
- WARN; // no-warning
- if (0 >= &a)
- WARN; // no-warning
- if (!(0 != &a))
- WARN; // no-warning
- if (!(0 < &a))
- WARN; // no-warning
- if (!(0 <= &a))
- WARN; // no-warning
+ clang_analyzer_eval(0 != &a); // expected-warning{{TRUE}}
+ clang_analyzer_eval(0 <= &a); // expected-warning{{TRUE}}
+ clang_analyzer_eval(0 < &a); // expected-warning{{TRUE}}
// LHS is a symbolic value, RHS is NULL
- if (a == 0)
- WARN; // expected-warning{{}}
- if (a < 0)
- WARN; // no-warning
- if (a <= 0)
- WARN; // expected-warning{{}}
- if (!(a != 0))
- WARN; // expected-warning{{}}
- if (!(a > 0))
- WARN; // expected-warning{{}}
- if (!(a >= 0))
- WARN; // no-warning
- if (!(a - 0))
- WARN; // expected-warning{{}}
+ clang_analyzer_eval(a != 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a >= 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a <= 0); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval((a - 0) != 0); // expected-warning{{UNKNOWN}}
// LHS is NULL, RHS is a symbolic value
- if (0 == a)
- WARN; // expected-warning{{}}
- if (0 > a)
- WARN; // no-warning
- if (0 >= a)
- WARN; // expected-warning{{}}
- if (!(0 != a))
- WARN; // expected-warning{{}}
- if (!(0 < a))
- WARN; // expected-warning{{}}
- if (!(0 <= a))
- WARN; // no-warning
+ clang_analyzer_eval(0 != a); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(0 <= a); // expected-warning{{TRUE}}
+ clang_analyzer_eval(0 < a); // expected-warning{{UNKNOWN}}
}
void const_locs() {
char *a = (char*)0x1000;
char *b = (char*)0x1100;
start:
- if (a==b)
- WARN; // no-warning
- if (!(a!=b))
- WARN; // no-warning
- if (a>b)
- WARN; // no-warning
- if (b<a)
- WARN; // no-warning
- if (a>=b)
- WARN; // no-warning
- if (b<=a)
- WARN; // no-warning
- if (b-a != 0x100)
- WARN; // no-warning
-
- if (&&start == a)
- WARN; // expected-warning{{}}
- if (a == &&start)
- WARN; // expected-warning{{}}
- if (&a == (char**)a)
- WARN; // expected-warning{{}}
- if ((char**)a == &a)
- WARN; // expected-warning{{}}
+ clang_analyzer_eval(a != b); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a < b); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a <= b); // expected-warning{{TRUE}}
+ clang_analyzer_eval((b-a) == 0x100); // expected-warning{{TRUE}}
+
+ clang_analyzer_eval(&&start == a); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == &&start); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(&a == (char**)a); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval((char**)a == &a); // expected-warning{{UNKNOWN}}
}
void array_matching_types() {
int *a = &array[2];
int *b = &array[5];
- if (a==b)
- WARN; // no-warning
- if (!(a!=b))
- WARN; // no-warning
- if (a>b)
- WARN; // no-warning
- if (b<a)
- WARN; // no-warning
- if (a>=b)
- WARN; // no-warning
- if (b<=a)
- WARN; // no-warning
- if ((b-a) == 0)
- WARN; // no-warning
+ clang_analyzer_eval(a != b); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a < b); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a <= b); // expected-warning{{TRUE}}
+ clang_analyzer_eval((b-a) != 0); // expected-warning{{TRUE}}
}
// This takes a different code path than array_matching_types()
int *a = &array[2];
char *b = (char*)&array[5];
- if (a==b) // expected-warning{{comparison of distinct pointer types}}
- WARN; // no-warning
- if (!(a!=b)) // expected-warning{{comparison of distinct pointer types}}
- WARN; // no-warning
- if (a>b) // expected-warning{{comparison of distinct pointer types}}
- WARN; // no-warning
- if (b<a) // expected-warning{{comparison of distinct pointer types}}
- WARN; // no-warning
- if (a>=b) // expected-warning{{comparison of distinct pointer types}}
- WARN; // no-warning
- if (b<=a) // expected-warning{{comparison of distinct pointer types}}
- WARN; // no-warning
+ clang_analyzer_eval(a != b); // expected-warning{{TRUE}} expected-warning{{comparison of distinct pointer types}}
+ clang_analyzer_eval(a < b); // expected-warning{{TRUE}} expected-warning{{comparison of distinct pointer types}}
+ clang_analyzer_eval(a <= b); // expected-warning{{TRUE}} expected-warning{{comparison of distinct pointer types}}
}
struct test { int x; int y; };
void struct_fields() {
struct test a, b;
- if (&a.x == &a.y)
- WARN; // no-warning
- if (!(&a.x != &a.y))
- WARN; // no-warning
- if (&a.x > &a.y)
- WARN; // no-warning
- if (&a.y < &a.x)
- WARN; // no-warning
- if (&a.x >= &a.y)
- WARN; // no-warning
- if (&a.y <= &a.x)
- WARN; // no-warning
+ clang_analyzer_eval(&a.x != &a.y); // expected-warning{{TRUE}}
+ clang_analyzer_eval(&a.x < &a.y); // expected-warning{{TRUE}}
+ clang_analyzer_eval(&a.x <= &a.y); // expected-warning{{TRUE}}
- if (&a.x == &b.x)
- WARN; // no-warning
- if (!(&a.x != &b.x))
- WARN; // no-warning
- if (&a.x > &b.x)
- WARN; // expected-warning{{}}
- if (&b.x < &a.x)
- WARN; // expected-warning{{}}
- if (&a.x >= &b.x)
- WARN; // expected-warning{{}}
- if (&b.x <= &a.x)
- WARN; // expected-warning{{}}
+ clang_analyzer_eval(&a.x != &b.x); // expected-warning{{TRUE}}
+ clang_analyzer_eval(&a.x > &b.x); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(&a.x >= &b.x); // expected-warning{{UNKNOWN}}
}
void mixed_region_types() {
int array[2];
void *a = &array, *b = &s;
- if (&a == &b)
- WARN; // no-warning
- if (!(&a != &b))
- WARN; // no-warning
- if (&a > &b)
- WARN; // expected-warning{{}}
- if (&b < &a)
- WARN; // expected-warning{{}}
- if (&a >= &b)
- WARN; // expected-warning{{}}
- if (&b <= &a)
- WARN; // expected-warning{{}}
+ clang_analyzer_eval(&a != &b); // expected-warning{{TRUE}}
+ clang_analyzer_eval(&a > &b); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(&a >= &b); // expected-warning{{UNKNOWN}}
}
void symbolic_region(int *p) {
int a;
- if (&a == p)
- WARN; // no-warning
- if (&a != p)
- WARN; // expected-warning{{}}
- if (&a > p)
- WARN; // expected-warning{{}}
- if (&a < p)
- WARN; // expected-warning{{}}
- if (&a >= p)
- WARN; // expected-warning{{}}
- if (&a <= p)
- WARN; // expected-warning{{}}
+ clang_analyzer_eval(&a != p); // expected-warning{{TRUE}}
+ clang_analyzer_eval(&a > p); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(&a >= p); // expected-warning{{UNKNOWN}}
}
void PR7527 (int *p) {
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.unix.CString,experimental.deadcode.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,experimental.unix.CString,experimental.deadcode.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s
// XFAIL: *
// This file is for tests that may eventually go into string.c, or may be
#define NULL 0
typedef typeof(sizeof(int)) size_t;
+void clang_analyzer_eval(int);
//===----------------------------------------------------------------------===
// strnlen()
void strnlen_liveness(const char *x) {
if (strnlen(x, 10) < 5)
return;
- if (strnlen(x, 10) < 5)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strnlen(x, 10) < 5); // expected-warning{{FALSE}}
}
void strnlen_subregion() {
size_t a = strnlen(z.a, 10);
z.b[0] = 5;
size_t b = strnlen(z.a, 10);
- if (a == 0 && b != 0)
- (void)*(char*)0; // expected-warning{{never executed}}
+ if (a == 0)
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
use_two_stringsn(&z);
size_t c = strnlen(z.a, 10);
- if (a == 0 && c != 0)
- (void)*(char*)0; // expected-warning{{null}}
+ if (a == 0)
+ clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
}
extern void use_stringn(char *);
void strnlen_argument(char *x) {
size_t a = strnlen(x, 10);
size_t b = strnlen(x, 10);
- if (a == 0 && b != 0)
- (void)*(char*)0; // expected-warning{{never executed}}
+ if (a == 0)
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
use_stringn(x);
size_t c = strnlen(x, 10);
- if (a == 0 && c != 0)
- (void)*(char*)0; // expected-warning{{null}}
+ if (a == 0)
+ clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
}
extern char global_strn[];
void strnlen_global() {
size_t a = strnlen(global_strn, 10);
size_t b = strnlen(global_strn, 10);
- if (a == 0 && b != 0)
- (void)*(char*)0; // expected-warning{{never executed}}
+ if (a == 0)
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
// Call a function with unknown effects, which should invalidate globals.
use_stringn(0);
size_t c = strnlen(global_strn, 10);
- if (a == 0 && c != 0)
- (void)*(char*)0; // expected-warning{{null}}
+ if (a == 0)
+ clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
}
void strnlen_indirect(char *x) {
char *p = x;
char **p2 = &p;
size_t b = strnlen(x, 10);
- if (a == 0 && b != 0)
- (void)*(char*)0; // expected-warning{{never executed}}
+ if (a == 0)
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
extern void use_stringn_ptr(char*const*);
use_stringn_ptr(p2);
size_t c = strnlen(x, 10);
- if (a == 0 && c != 0)
- (void)*(char*)0; // expected-warning{{null}}
+ if (a == 0)
+ clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
}
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,experimental.unix.cstring,experimental.deadcode.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,experimental.unix.cstring,experimental.deadcode.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,experimental.unix.cstring,experimental.deadcode.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s
-// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=experimental.security.taint,core,unix.cstring,experimental.unix.cstring,experimental.deadcode.UnreachableCode -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-checker=core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
+// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-checker=experimental.security.taint,core,unix.cstring,experimental.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify %s
//===----------------------------------------------------------------------===
// Declarations
#define NULL 0
typedef typeof(sizeof(int)) size_t;
+
+void clang_analyzer_eval(int);
+
int scanf(const char *restrict format, ...);
//===----------------------------------------------------------------------===
size_t strlen(const char *s);
void strlen_constant0() {
- if (strlen("123") != 3)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strlen("123") == 3); // expected-warning{{TRUE}}
}
void strlen_constant1() {
const char *a = "123";
- if (strlen(a) != 3)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strlen(a) == 3); // expected-warning{{TRUE}}
}
void strlen_constant2(char x) {
char a[] = "123";
- if (strlen(a) != 3)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strlen(a) == 3); // expected-warning{{TRUE}}
+
a[0] = x;
- if (strlen(a) != 3)
- (void)*(char*)0; // expected-warning{{null}}
+ clang_analyzer_eval(strlen(a) == 3); // expected-warning{{UNKNOWN}}
}
size_t strlen_null() {
size_t a = strlen(z.a);
z.b[0] = 5;
size_t b = strlen(z.a);
- if (a == 0 && b != 0)
- (void)*(char*)0; // expected-warning{{never executed}}
+ if (a == 0)
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
use_two_strings(&z);
size_t c = strlen(z.a);
- if (a == 0 && c != 0)
- (void)*(char*)0; // expected-warning{{null}}
+ if (a == 0)
+ clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
}
extern void use_string(char *);
void strlen_argument(char *x) {
size_t a = strlen(x);
size_t b = strlen(x);
- if (a == 0 && b != 0)
- (void)*(char*)0; // expected-warning{{never executed}}
+ if (a == 0)
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
use_string(x);
size_t c = strlen(x);
- if (a == 0 && c != 0)
- (void)*(char*)0; // expected-warning{{null}}
+ if (a == 0)
+ clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
}
extern char global_str[];
void strlen_global() {
size_t a = strlen(global_str);
size_t b = strlen(global_str);
- if (a == 0 && b != 0)
- (void)*(char*)0; // expected-warning{{never executed}}
+ if (a == 0) {
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
+ // Make sure clang_analyzer_eval does not invalidate globals.
+ clang_analyzer_eval(strlen(global_str) == 0); // expected-warning{{TRUE}}
+ }
// Call a function with unknown effects, which should invalidate globals.
use_string(0);
size_t c = strlen(global_str);
- if (a == 0 && c != 0)
- (void)*(char*)0; // expected-warning{{null}}
+ if (a == 0)
+ clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
}
void strlen_indirect(char *x) {
char *p = x;
char **p2 = &p;
size_t b = strlen(x);
- if (a == 0 && b != 0)
- (void)*(char*)0; // expected-warning{{never executed}}
+ if (a == 0)
+ clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
extern void use_string_ptr(char*const*);
use_string_ptr(p2);
size_t c = strlen(x);
- if (a == 0 && c != 0)
- (void)*(char*)0; // expected-warning{{null}}
+ if (a == 0)
+ clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
}
void strlen_indirect2(char *x) {
use_string_ptr2(p2);
size_t c = strlen(x);
- if (a == 0 && c != 0)
- (void)*(char*)0; // expected-warning{{null}}
+ if (a == 0)
+ clang_analyzer_eval(c == 0); // expected-warning{{UNKNOWN}}
}
void strlen_liveness(const char *x) {
if (strlen(x) < 5)
return;
- if (strlen(x) < 5)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strlen(x) < 5); // expected-warning{{FALSE}}
}
//===----------------------------------------------------------------------===
size_t strnlen(const char *s, size_t maxlen);
void strnlen_constant0() {
- if (strnlen("123", 10) != 3)
- (void)*(char*)0; // expected-warning{{never executed}}
+ clang_analyzer_eval(strnlen("123", 10) == 3); // expected-warning{{TRUE}}
}
void strnlen_constant1() {
const char *a = "123";
- if (strnlen(a, 10) != 3)
- (void)*(char*)0; // expected-warning{{never executed}}
+ clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{TRUE}}
}
void strnlen_constant2(char x) {
char a[] = "123";
- if (strnlen(a, 10) != 3)
- (void)*(char*)0; // expected-warning{{never executed}}
+ clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{TRUE}}
a[0] = x;
- if (strnlen(a, 10) != 3)
- (void)*(char*)0; // expected-warning{{null}}
+ clang_analyzer_eval(strnlen(a, 10) == 3); // expected-warning{{UNKNOWN}}
}
void strnlen_constant4() {
- if (strnlen("123456", 3) != 3)
- (void)*(char*)0; // expected-warning{{never executed}}
+ clang_analyzer_eval(strnlen("123456", 3) == 3); // expected-warning{{TRUE}}
}
void strnlen_constant5() {
const char *a = "123456";
- if (strnlen(a, 3) != 3)
- (void)*(char*)0; // expected-warning{{never executed}}
+ clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{TRUE}}
}
void strnlen_constant6(char x) {
char a[] = "123456";
- if (strnlen(a, 3) != 3)
- (void)*(char*)0; // expected-warning{{never executed}}
+ clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{TRUE}}
a[0] = x;
- if (strnlen(a, 3) != 3)
- (void)*(char*)0; // expected-warning{{null}}
+ clang_analyzer_eval(strnlen(a, 3) == 3); // expected-warning{{UNKNOWN}}
}
size_t strnlen_null() {
}
void strnlen_zero() {
- if (strnlen("abc", 0) != 0)
- (void)*(char*)0; // expected-warning{{never executed}}
- if (strnlen(NULL, 0) != 0) // no-warning
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strnlen("abc", 0) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strnlen(NULL, 0) == 0); // expected-warning{{TRUE}}
}
size_t strnlen_compound_literal() {
}
void strnlen_is_not_strlen(char *x) {
- if (strnlen(x, 10) != strlen(x))
- (void)*(char*)0; // expected-warning{{null}}
+ clang_analyzer_eval(strnlen(x, 10) == strlen(x)); // expected-warning{{UNKNOWN}}
}
void strnlen_at_limit(char *x) {
size_t len = strnlen(x, 10);
- if (len > 10)
- (void)*(char*)0; // expected-warning{{never executed}}
- if (len == 10)
- (void)*(char*)0; // expected-warning{{null}}
-}
-
-void strnlen_less_than_limit(char *x) {
- size_t len = strnlen(x, 10);
- if (len > 10)
- (void)*(char*)0; // expected-warning{{never executed}}
- if (len < 10)
- (void)*(char*)0; // expected-warning{{null}}
+ clang_analyzer_eval(len <= 10); // expected-warning{{TRUE}}
+ clang_analyzer_eval(len == 10); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(len < 10); // expected-warning{{UNKNOWN}}
}
void strnlen_at_actual(size_t limit) {
size_t len = strnlen("abc", limit);
- if (len > 3)
- (void)*(char*)0; // expected-warning{{never executed}}
- if (len == 3)
- (void)*(char*)0; // expected-warning{{null}}
-}
-
-void strnlen_less_than_actual(size_t limit) {
- size_t len = strnlen("abc", limit);
- if (len > 3)
- (void)*(char*)0; // expected-warning{{never executed}}
- if (len < 3)
- (void)*(char*)0; // expected-warning{{null}}
+ clang_analyzer_eval(len <= 3); // expected-warning{{TRUE}}
+ // This is due to eager assertion in strnlen.
+ if (limit == 0) {
+ clang_analyzer_eval(len == 0); // expected-warning{{TRUE}}
+ } else {
+ clang_analyzer_eval(len == 3); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(len < 3); // expected-warning{{UNKNOWN}}
+ }
}
//===----------------------------------------------------------------------===
void strcpy_effects(char *x, char *y) {
char a = x[0];
- if (strcpy(x, y) != x)
- (void)*(char*)0; // no-warning
-
- if (strlen(x) != strlen(y))
- (void)*(char*)0; // no-warning
-
- if (a != x[0])
- (void)*(char*)0; // expected-warning{{null}}
+ clang_analyzer_eval(strcpy(x, y) == x); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
}
void strcpy_overflow(char *y) {
void stpcpy_effect(char *x, char *y) {
char a = x[0];
- if (stpcpy(x, y) != &x[strlen(y)])
- (void)*(char*)0; // no-warning
-
- if (strlen(x) != strlen(y))
- (void)*(char*)0; // no-warning
-
- if (a != x[0])
- (void)*(char*)0; // expected-warning{{null}}
+ clang_analyzer_eval(stpcpy(x, y) == &x[strlen(y)]); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
}
void stpcpy_overflow(char *y) {
if (strlen(y) != 4)
return;
- if (strcat(x, y) != x)
- (void)*(char*)0; // no-warning
-
- if ((int)strlen(x) != (orig_len + strlen(y)))
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcat(x, y) == x); // expected-warning{{TRUE}}
+ clang_analyzer_eval((int)strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}}
}
void strcat_overflow_0(char *y) {
void strcat_symbolic_dst_length(char *dst) {
strcat(dst, "1234");
- if (strlen(dst) < 4)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
}
void strcat_symbolic_src_length(char *src) {
char dst[8] = "1234";
strcat(dst, src);
- if (strlen(dst) < 4)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
}
void strcat_symbolic_dst_length_taint(char *dst) {
scanf("%s", dst); // Taint data.
strcat(dst, "1234");
- if (strlen(dst) < 4)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
}
void strcat_unknown_src_length(char *src, int offset) {
char dst[8] = "1234";
strcat(dst, &src[offset]);
- if (strlen(dst) < 4)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
}
// There is no strcat_unknown_dst_length because if we can't get a symbolic
void strncpy_effects(char *x, char *y) {
char a = x[0];
- if (strncpy(x, y, 5) != x)
- (void)*(char*)0; // no-warning
-
- if (strlen(x) != strlen(y))
- (void)*(char*)0; // expected-warning{{null}}
-
- if (a != x[0])
- (void)*(char*)0; // expected-warning{{null}}
+ clang_analyzer_eval(strncpy(x, y, 5) == x); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen(x) == strlen(y)); // expected-warning{{UNKNOWN}}
+ clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
}
void strncpy_overflow(char *y) {
// strncpy does not null-terminate, so we have no idea what the strlen is
// after this.
- if (strlen(x) > 4)
- (void)*(int*)0; // expected-warning{{null}}
+ clang_analyzer_eval(strlen(x) > 4); // expected-warning{{UNKNOWN}}
}
void strncpy_exactly_matching_buffer2(char *y) {
strncpy(x, y, 4); // no-warning
// This time, we know that y fits in x anyway.
- if (strlen(x) > 3)
- (void)*(int*)0; // no-warning
+ clang_analyzer_eval(strlen(x) <= 3); // expected-warning{{TRUE}}
}
void strncpy_zero(char *src) {
if (strlen(y) != 4)
return;
- if (strncat(x, y, strlen(y)) != x)
- (void)*(char*)0; // no-warning
-
- if (strlen(x) != orig_len + strlen(y))
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncat(x, y, strlen(y)) == x); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}}
}
void strncat_overflow_0(char *y) {
void strncat_symbolic_dst_length(char *dst) {
strncat(dst, "1234", 5);
- if (strlen(dst) < 4)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
}
void strncat_symbolic_src_length(char *src) {
char dst[8] = "1234";
strncat(dst, src, 3);
- if (strlen(dst) < 4)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
char dst2[8] = "1234";
strncat(dst2, src, 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
void strncat_unknown_src_length(char *src, int offset) {
char dst[8] = "1234";
strncat(dst, &src[offset], 3);
- if (strlen(dst) < 4)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
char dst2[8] = "1234";
strncat(dst2, &src[offset], 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
char dst[6] = "1234";
char src[] = "567";
strncat(dst, src, limit); // no-warning
- if (strlen(dst) < 4)
- (void)*(char*)0; // no-warning
- if (strlen(dst) == 4)
- (void)*(char*)0; // expected-warning{{null}}
+
+ clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}}
}
void strncat_unknown_limit(float limit) {
char dst[6] = "1234";
char src[] = "567";
strncat(dst, src, (size_t)limit); // no-warning
- if (strlen(dst) < 4)
- (void)*(char*)0; // no-warning
- if (strlen(dst) == 4)
- (void)*(char*)0; // expected-warning{{null}}
+
+ clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
+ clang_analyzer_eval(strlen(dst) == 4); // expected-warning{{UNKNOWN}}
}
void strncat_too_big(char *dst, char *src) {
int strcmp(const char * s1, const char * s2);
void strcmp_constant0() {
- if (strcmp("123", "123") != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcmp("123", "123") == 0); // expected-warning{{TRUE}}
}
void strcmp_constant_and_var_0() {
char *x = "123";
- if (strcmp(x, "123") != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcmp(x, "123") == 0); // expected-warning{{TRUE}}
}
void strcmp_constant_and_var_1() {
char *x = "123";
- if (strcmp("123", x) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcmp("123", x) == 0); // expected-warning{{TRUE}}
}
void strcmp_0() {
char *x = "123";
char *y = "123";
- if (strcmp(x, y) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcmp(x, y) == 0); // expected-warning{{TRUE}}
}
void strcmp_1() {
char *x = "234";
char *y = "123";
- if (strcmp(x, y) != 1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcmp(x, y) == 1); // expected-warning{{TRUE}}
}
void strcmp_2() {
char *x = "123";
char *y = "234";
- if (strcmp(x, y) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
}
void strcmp_null_0() {
void strcmp_diff_length_0() {
char *x = "12345";
char *y = "234";
- if (strcmp(x, y) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
}
void strcmp_diff_length_1() {
char *x = "123";
char *y = "23456";
- if (strcmp(x, y) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
}
void strcmp_diff_length_2() {
char *x = "12345";
char *y = "123";
- if (strcmp(x, y) != 1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcmp(x, y) == 1); // expected-warning{{TRUE}}
}
void strcmp_diff_length_3() {
char *x = "123";
char *y = "12345";
- if (strcmp(x, y) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcmp(x, y) == -1); // expected-warning{{TRUE}}
}
void strcmp_embedded_null () {
- if (strcmp("\0z", "\0y") != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcmp("\0z", "\0y") == 0); // expected-warning{{TRUE}}
}
void strcmp_unknown_arg (char *unknown) {
- if (strcmp(unknown, unknown) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcmp(unknown, unknown) == 0); // expected-warning{{TRUE}}
}
//===----------------------------------------------------------------------===
int strncmp(const char *s1, const char *s2, size_t n);
void strncmp_constant0() {
- if (strncmp("123", "123", 3) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp("123", "123", 3) == 0); // expected-warning{{TRUE}}
}
void strncmp_constant_and_var_0() {
char *x = "123";
- if (strncmp(x, "123", 3) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp(x, "123", 3) == 0); // expected-warning{{TRUE}}
}
void strncmp_constant_and_var_1() {
char *x = "123";
- if (strncmp("123", x, 3) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp("123", x, 3) == 0); // expected-warning{{TRUE}}
}
void strncmp_0() {
char *x = "123";
char *y = "123";
- if (strncmp(x, y, 3) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}}
}
void strncmp_1() {
char *x = "234";
char *y = "123";
- if (strncmp(x, y, 3) != 1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp(x, y, 3) == 1); // expected-warning{{TRUE}}
}
void strncmp_2() {
char *x = "123";
char *y = "234";
- if (strncmp(x, y, 3) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp(x, y, 3) == -1); // expected-warning{{TRUE}}
}
void strncmp_null_0() {
void strncmp_diff_length_0() {
char *x = "12345";
char *y = "234";
- if (strncmp(x, y, 5) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}}
}
void strncmp_diff_length_1() {
char *x = "123";
char *y = "23456";
- if (strncmp(x, y, 5) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}}
}
void strncmp_diff_length_2() {
char *x = "12345";
char *y = "123";
- if (strncmp(x, y, 5) != 1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp(x, y, 5) == 1); // expected-warning{{TRUE}}
}
void strncmp_diff_length_3() {
char *x = "123";
char *y = "12345";
- if (strncmp(x, y, 5) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp(x, y, 5) == -1); // expected-warning{{TRUE}}
}
void strncmp_diff_length_4() {
char *x = "123";
char *y = "12345";
- if (strncmp(x, y, 3) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp(x, y, 3) == 0); // expected-warning{{TRUE}}
}
void strncmp_diff_length_5() {
char *x = "012";
char *y = "12345";
- if (strncmp(x, y, 3) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp(x, y, 3) == -1); // expected-warning{{TRUE}}
}
void strncmp_diff_length_6() {
char *x = "234";
char *y = "12345";
- if (strncmp(x, y, 3) != 1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp(x, y, 3) == 1); // expected-warning{{TRUE}}
}
void strncmp_embedded_null () {
- if (strncmp("ab\0zz", "ab\0yy", 4) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}}
}
//===----------------------------------------------------------------------===
int strcasecmp(const char *s1, const char *s2);
void strcasecmp_constant0() {
- if (strcasecmp("abc", "Abc") != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcasecmp("abc", "Abc") == 0); // expected-warning{{TRUE}}
}
void strcasecmp_constant_and_var_0() {
char *x = "abc";
- if (strcasecmp(x, "Abc") != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcasecmp(x, "Abc") == 0); // expected-warning{{TRUE}}
}
void strcasecmp_constant_and_var_1() {
char *x = "abc";
- if (strcasecmp("Abc", x) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcasecmp("Abc", x) == 0); // expected-warning{{TRUE}}
}
void strcasecmp_0() {
char *x = "abc";
char *y = "Abc";
- if (strcasecmp(x, y) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcasecmp(x, y) == 0); // expected-warning{{TRUE}}
}
void strcasecmp_1() {
char *x = "Bcd";
char *y = "abc";
- if (strcasecmp(x, y) != 1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcasecmp(x, y) == 1); // expected-warning{{TRUE}}
}
void strcasecmp_2() {
char *x = "abc";
char *y = "Bcd";
- if (strcasecmp(x, y) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
}
void strcasecmp_null_0() {
void strcasecmp_diff_length_0() {
char *x = "abcde";
char *y = "aBd";
- if (strcasecmp(x, y) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
}
void strcasecmp_diff_length_1() {
char *x = "abc";
char *y = "aBdef";
- if (strcasecmp(x, y) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
}
void strcasecmp_diff_length_2() {
char *x = "aBcDe";
char *y = "abc";
- if (strcasecmp(x, y) != 1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcasecmp(x, y) == 1); // expected-warning{{TRUE}}
}
void strcasecmp_diff_length_3() {
char *x = "aBc";
char *y = "abcde";
- if (strcasecmp(x, y) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcasecmp(x, y) == -1); // expected-warning{{TRUE}}
}
void strcasecmp_embedded_null () {
- if (strcasecmp("ab\0zz", "ab\0yy") != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strcasecmp("ab\0zz", "ab\0yy") == 0); // expected-warning{{TRUE}}
}
//===----------------------------------------------------------------------===
int strncasecmp(const char *s1, const char *s2, size_t n);
void strncasecmp_constant0() {
- if (strncasecmp("abc", "Abc", 3) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp("abc", "Abc", 3) == 0); // expected-warning{{TRUE}}
}
void strncasecmp_constant_and_var_0() {
char *x = "abc";
- if (strncasecmp(x, "Abc", 3) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp(x, "Abc", 3) == 0); // expected-warning{{TRUE}}
}
void strncasecmp_constant_and_var_1() {
char *x = "abc";
- if (strncasecmp("Abc", x, 3) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp("Abc", x, 3) == 0); // expected-warning{{TRUE}}
}
void strncasecmp_0() {
char *x = "abc";
char *y = "Abc";
- if (strncasecmp(x, y, 3) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}}
}
void strncasecmp_1() {
char *x = "Bcd";
char *y = "abc";
- if (strncasecmp(x, y, 3) != 1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp(x, y, 3) == 1); // expected-warning{{TRUE}}
}
void strncasecmp_2() {
char *x = "abc";
char *y = "Bcd";
- if (strncasecmp(x, y, 3) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp(x, y, 3) == -1); // expected-warning{{TRUE}}
}
void strncasecmp_null_0() {
void strncasecmp_diff_length_0() {
char *x = "abcde";
char *y = "aBd";
- if (strncasecmp(x, y, 5) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}}
}
void strncasecmp_diff_length_1() {
char *x = "abc";
char *y = "aBdef";
- if (strncasecmp(x, y, 5) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}}
}
void strncasecmp_diff_length_2() {
char *x = "aBcDe";
char *y = "abc";
- if (strncasecmp(x, y, 5) != 1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp(x, y, 5) == 1); // expected-warning{{TRUE}}
}
void strncasecmp_diff_length_3() {
char *x = "aBc";
char *y = "abcde";
- if (strncasecmp(x, y, 5) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp(x, y, 5) == -1); // expected-warning{{TRUE}}
}
void strncasecmp_diff_length_4() {
char *x = "abcde";
char *y = "aBc";
- if (strncasecmp(x, y, 3) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp(x, y, 3) == 0); // expected-warning{{TRUE}}
}
void strncasecmp_diff_length_5() {
char *x = "abcde";
char *y = "aBd";
- if (strncasecmp(x, y, 3) != -1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp(x, y, 3) == -1); // expected-warning{{TRUE}}
}
void strncasecmp_diff_length_6() {
char *x = "aBDe";
char *y = "abc";
- if (strncasecmp(x, y, 3) != 1)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp(x, y, 3) == 1); // expected-warning{{TRUE}}
}
void strncasecmp_embedded_null () {
- if (strncasecmp("ab\0zz", "ab\0yy", 4) != 0)
- (void)*(char*)0; // no-warning
+ clang_analyzer_eval(strncasecmp("ab\0zz", "ab\0yy", 4) == 0); // expected-warning{{TRUE}}
}
//===----------------------------------------------------------------------===
if (strlen(x) != value) return;
// Test relational operators.
- if (strlen(x) < 2) { (void)*(char*)0; } // no-warning
- if (2 > strlen(x)) { (void)*(char*)0; } // no-warning
+ clang_analyzer_eval(strlen(x) >= 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval(2 <= strlen(x)); // expected-warning{{TRUE}}
// Test equality operators.
- if (strlen(x) == 1) { (void)*(char*)0; } // no-warning
- if (1 == strlen(x)) { (void)*(char*)0; } // no-warning
+ clang_analyzer_eval(strlen(x) != 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(1 != strlen(x)); // expected-warning{{TRUE}}
}