From: Jordy Rose Date: Wed, 16 May 2012 16:01:10 +0000 (+0000) Subject: [analyzer] Convert many existing tests to use clang_analyzer_eval. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=43d9f0d4e9b88dcab473a359a7b5579c2a619b22;p=clang [analyzer] Convert many existing tests to use clang_analyzer_eval. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156920 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/Analysis/additive-folding-range-constraints.c b/test/Analysis/additive-folding-range-constraints.c index a64c9102fc..7eb55ab1e1 100644 --- a/test/Analysis/additive-folding-range-constraints.c +++ b/test/Analysis/additive-folding-range-constraints.c @@ -1,10 +1,7 @@ -// 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) @@ -14,43 +11,27 @@ void free(void *); // 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}} } @@ -58,154 +39,102 @@ void smallAdjustmentLE (unsigned a) { // 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}} } } @@ -213,30 +142,21 @@ void mixedComparisons7(signed char a) { // 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}} } } @@ -244,14 +164,9 @@ void mixedComparisons9(signed char a) { // 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}} } diff --git a/test/Analysis/additive-folding.cpp b/test/Analysis/additive-folding.cpp index 136dc08f16..8c132fb4a9 100644 --- a/test/Analysis/additive-folding.cpp +++ b/test/Analysis/additive-folding.cpp @@ -1,11 +1,8 @@ -// 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) @@ -18,10 +15,7 @@ void separateExpressions (int a) { 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) { @@ -29,26 +23,17 @@ 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}} } //--------------- @@ -57,206 +42,101 @@ void mixedTypes (int a) { // 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}} } @@ -267,64 +147,32 @@ void mixedWraparoundSanityCheck(int a) { 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}} } @@ -332,10 +180,9 @@ void mixedWraparoundNE(int a) { 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}} } @@ -365,16 +212,12 @@ void PR12206(int x) { // 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) { @@ -393,24 +236,19 @@ 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}} } diff --git a/test/Analysis/array-struct-region.c b/test/Analysis/array-struct-region.c index 18d5b2a375..c1eddcdd21 100644 --- a/test/Analysis/array-struct-region.c +++ b/test/Analysis/array-struct-region.c @@ -1,25 +1,21 @@ -// 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; } @@ -48,13 +44,16 @@ void nested_compound_literals_float(float rad) { 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}} } diff --git a/test/Analysis/base-init.cpp b/test/Analysis/base-init.cpp index 8fd7abcc37..ae99d53e20 100644 --- a/test/Analysis/base-init.cpp +++ b/test/Analysis/base-init.cpp @@ -1,6 +1,8 @@ -// 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: @@ -24,8 +26,5 @@ B::B() { void f() { B b; - if (b.getx() != 0) { - int *p = 0; - *p = 0; // no-warning - } + clang_analyzer_eval(b.getx() == 0); // expected-warning{{TRUE}} } diff --git a/test/Analysis/bstring.c b/test/Analysis/bstring.c index 87c91613a5..d383d421d4 100644 --- a/test/Analysis/bstring.c +++ b/test/Analysis/bstring.c @@ -1,7 +1,7 @@ -// 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 @@ -26,6 +26,8 @@ typedef typeof(sizeof(int)) size_t; +void clang_analyzer_eval(int); + //===----------------------------------------------------------------------=== // memcpy() //===----------------------------------------------------------------------=== @@ -52,12 +54,11 @@ void memcpy0 () { 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 () { @@ -138,14 +139,13 @@ void memcpy13() { 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) } //===----------------------------------------------------------------------=== @@ -174,12 +174,11 @@ void mempcpy0 () { 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 () { @@ -260,8 +259,8 @@ void mempcpy13() { 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) { @@ -295,12 +294,11 @@ void memmove0 () { 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 () { @@ -327,7 +325,7 @@ void memmove2 () { // __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) @@ -360,34 +358,32 @@ void memcmp2 () { 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) { @@ -411,8 +407,9 @@ void bcopy0 () { 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 () { diff --git a/test/Analysis/constant-folding.c b/test/Analysis/constant-folding.c index c650473c96..81d1193926 100644 --- a/test/Analysis/constant-folding.c +++ b/test/Analysis/constant-folding.c @@ -1,7 +1,6 @@ -// 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. @@ -9,73 +8,71 @@ void testComparisons (int a) { // 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); // 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); // 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}} } diff --git a/test/Analysis/initializer.cpp b/test/Analysis/initializer.cpp index 656a8bf8ee..6640e1fc49 100644 --- a/test/Analysis/initializer.cpp +++ b/test/Analysis/initializer.cpp @@ -1,4 +1,6 @@ -// 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; @@ -7,8 +9,5 @@ public: }; A::A() : x(0) { - if (x != 0) { - int *p = 0; - *p = 0; // no-warning - } + clang_analyzer_eval(x == 0); // expected-warning{{TRUE}} } diff --git a/test/Analysis/method-call.cpp b/test/Analysis/method-call.cpp index 323fffebcd..91da532456 100644 --- a/test/Analysis/method-call.cpp +++ b/test/Analysis/method-call.cpp @@ -1,6 +1,8 @@ -// 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; } @@ -9,33 +11,15 @@ struct 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}} } diff --git a/test/Analysis/ptr-arith.c b/test/Analysis/ptr-arith.c index fb37f1c791..6567000c73 100644 --- a/test/Analysis/ptr-arith.c +++ b/test/Analysis/ptr-arith.c @@ -1,8 +1,7 @@ -// 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]; @@ -67,111 +66,48 @@ void f6(int *p, int *q) { 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=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() { @@ -179,20 +115,10 @@ 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=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() @@ -201,49 +127,22 @@ void array_different_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=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() { @@ -251,35 +150,17 @@ 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) { diff --git a/test/Analysis/string-fail.c b/test/Analysis/string-fail.c index 3bff6d40dd..ac5c6d0572 100644 --- a/test/Analysis/string-fail.c +++ b/test/Analysis/string-fail.c @@ -1,5 +1,5 @@ -// 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 @@ -32,6 +32,7 @@ #define NULL 0 typedef typeof(sizeof(int)) size_t; +void clang_analyzer_eval(int); //===----------------------------------------------------------------------=== // strnlen() @@ -43,8 +44,7 @@ size_t strnlen(const char *s, size_t maxlen); 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() { @@ -57,43 +57,43 @@ 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) { @@ -101,13 +101,13 @@ 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}} } diff --git a/test/Analysis/string.c b/test/Analysis/string.c index dc38681b35..4e9d51f4c1 100644 --- a/test/Analysis/string.c +++ b/test/Analysis/string.c @@ -1,7 +1,7 @@ -// 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 @@ -26,6 +26,9 @@ #define NULL 0 typedef typeof(sizeof(int)) size_t; + +void clang_analyzer_eval(int); + int scanf(const char *restrict format, ...); //===----------------------------------------------------------------------=== @@ -36,23 +39,20 @@ 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() { @@ -78,43 +78,46 @@ void strlen_subregion() { 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) { @@ -122,15 +125,15 @@ 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) { @@ -141,15 +144,14 @@ 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}} } //===----------------------------------------------------------------------=== @@ -159,43 +161,35 @@ void strlen_liveness(const char *x) { 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() { @@ -212,10 +206,8 @@ label: } 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() { @@ -230,40 +222,26 @@ size_t strnlen_unknown_limit(float f) { } 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}} + } } //===----------------------------------------------------------------------=== @@ -304,14 +282,9 @@ void strcpy_fn_const(char *x) { 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) { @@ -348,14 +321,9 @@ char *stpcpy(char *restrict s1, const char *restrict s2); 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) { @@ -409,11 +377,8 @@ void strcat_effects(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) { @@ -442,29 +407,25 @@ void strcat_no_overflow(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 @@ -513,14 +474,9 @@ void strncpy_fn(char *x) { 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) { @@ -562,8 +518,7 @@ void strncpy_exactly_matching_buffer(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) { @@ -574,8 +529,7 @@ 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) { @@ -628,11 +582,8 @@ void strncat_effects(char *y) { 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) { @@ -672,15 +623,13 @@ void strncat_no_overflow_2(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}} @@ -689,8 +638,7 @@ void strncat_symbolic_src_length(char *src) { 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}} @@ -703,20 +651,18 @@ void strncat_symbolic_limit(unsigned limit) { 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) { @@ -746,41 +692,35 @@ void strncat_empty() { 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() { @@ -798,39 +738,33 @@ void strcmp_null_1() { 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}} } //===----------------------------------------------------------------------=== @@ -841,41 +775,35 @@ void strcmp_unknown_arg (char *unknown) { 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() { @@ -893,55 +821,47 @@ void strncmp_null_1() { 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}} } //===----------------------------------------------------------------------=== @@ -952,41 +872,35 @@ void strncmp_embedded_null () { 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() { @@ -1004,34 +918,29 @@ void strcasecmp_null_1() { 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}} } //===----------------------------------------------------------------------=== @@ -1042,41 +951,35 @@ void strcasecmp_embedded_null () { 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() { @@ -1094,55 +997,47 @@ void strncasecmp_null_1() { 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}} } //===----------------------------------------------------------------------=== @@ -1169,10 +1064,10 @@ void PR12206(const char *x) { 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}} }