// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,debug.ExprInspection -triple i386-apple-darwin9 -verify %s // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,debug.ExprInspection -triple x86_64-apple-darwin9 -verify %s // This file runs in C++ mode so that the comparison type is 'bool', not 'int'. void clang_analyzer_eval(int); typedef typeof(sizeof(int)) size_t; // PR12206/12510 - When SimpleSValBuilder figures out that a symbol is fully // constrained, it should cast the value to the result type in a binary // operation...unless the binary operation is a comparison, in which case the // two arguments should be the same type, but won't match the result type. // // This is not directly related to additive folding, but we use SValBuilder's // additive folding to tickle the bug. ExprEngine will simplify fully-constrained // symbols, so SValBuilder will only see them if they are (a) part of an evaluated // SymExpr (e.g. with additive folding) or (b) generated by a checker (e.g. // unix.cstring's strlen() modelling). void PR12206(int x) { size_t comparisonSize = sizeof(1 == 1); // Sanity check. This test is useless if size_t isn't bigger than bool. clang_analyzer_eval(sizeof(size_t) > comparisonSize); // expected-warning{{TRUE}} // Build a SymIntExpr, dependent on x. int local = x - 1; // Create a value that requires more bits to store than a comparison result. int value = 1; value <<= 8 * comparisonSize; value += 1; // Constrain the value of x. if (x != value) return; // Constant-folding will turn (local+1) back into the symbol for x. // The point of this dance is to make SValBuilder be responsible for // turning the symbol into a ConcreteInt, rather than ExprEngine. // Test relational operators. clang_analyzer_eval((local + 1) >= 2); // expected-warning{{TRUE}} clang_analyzer_eval(2 <= (local + 1)); // expected-warning{{TRUE}} // Test equality operators. clang_analyzer_eval((local + 1) != 1); // expected-warning{{TRUE}} clang_analyzer_eval(1 != (local + 1)); // expected-warning{{TRUE}} } void PR12206_truncation(signed char x) { // Build a SymIntExpr, dependent on x. signed char local = x - 1; // Constrain the value of x. if (x != 1) return; // Constant-folding will turn (local+1) back into the symbol for x. // The point of this dance is to make SValBuilder be responsible for // turning the symbol into a ConcreteInt, rather than ExprEngine. // Construct a value that cannot be represented by 'char', // but that has the same lower bits as x. signed int value = 1 + (1 << 8); // Test relational operators. clang_analyzer_eval((local + 1) < value); // expected-warning{{TRUE}} clang_analyzer_eval(value > (local + 1)); // expected-warning{{TRUE}} // Test equality operators. clang_analyzer_eval((local + 1) != value); // expected-warning{{TRUE}} clang_analyzer_eval(value != (local + 1)); // expected-warning{{TRUE}} } // This test is insurance in case we significantly change how SymExprs are // evaluated. size_t strlen(const char *s); void PR12206_strlen(const char *x) { size_t comparisonSize = sizeof(1 == 1); // Sanity check. This test is useless if size_t isn't bigger than bool. clang_analyzer_eval(sizeof(size_t) > comparisonSize); // expected-warning{{TRUE}} // Create a value that requires more bits to store than a comparison result. size_t value = 1UL; value <<= 8 * comparisonSize; value += 1; // Constrain the length of x. if (strlen(x) != value) return; // Test relational operators. clang_analyzer_eval(strlen(x) >= 2); // expected-warning{{TRUE}} clang_analyzer_eval(2 <= strlen(x)); // expected-warning{{TRUE}} // Test equality operators. clang_analyzer_eval(strlen(x) != 1); // expected-warning{{TRUE}} clang_analyzer_eval(1 != strlen(x)); // expected-warning{{TRUE}} }