2018-08-30 04:29:17 +08:00
|
|
|
//RUN: %clang_analyze_cc1 -cc1 -std=c++11 -analyzer-checker=core,apiModeling.google.GTest,debug.ExprInspection %s -verify
|
|
|
|
//RUN: %clang_analyze_cc1 -cc1 -std=c++11 -analyzer-checker=core,apiModeling.google.GTest,debug.ExprInspection -DGTEST_VERSION_1_8_AND_LATER=1 %s -verify
|
2016-12-20 06:50:31 +08:00
|
|
|
|
2016-12-23 01:52:57 +08:00
|
|
|
void clang_analyzer_eval(int);
|
|
|
|
void clang_analyzer_warnIfReached();
|
2016-12-20 06:50:31 +08:00
|
|
|
|
|
|
|
namespace std {
|
|
|
|
class string {
|
|
|
|
public:
|
|
|
|
~string();
|
|
|
|
const char *c_str();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace testing {
|
|
|
|
|
|
|
|
class Message { };
|
|
|
|
class TestPartResult {
|
|
|
|
public:
|
|
|
|
enum Type {
|
|
|
|
kSuccess,
|
|
|
|
kNonFatalFailure,
|
|
|
|
kFatalFailure
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
class AssertHelper {
|
|
|
|
public:
|
|
|
|
AssertHelper(TestPartResult::Type type, const char* file, int line,
|
|
|
|
const char* message);
|
|
|
|
~AssertHelper();
|
|
|
|
void operator=(const Message& message) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct AddReference { typedef T& type; };
|
|
|
|
template <typename T>
|
|
|
|
struct AddReference<T&> { typedef T& type; };
|
|
|
|
template <typename From, typename To>
|
|
|
|
class ImplicitlyConvertible {
|
|
|
|
private:
|
|
|
|
static typename AddReference<From>::type MakeFrom();
|
|
|
|
static char Helper(To);
|
|
|
|
static char (&Helper(...))[2];
|
|
|
|
public:
|
|
|
|
static const bool value =
|
|
|
|
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
|
|
|
|
};
|
|
|
|
template <typename From, typename To>
|
|
|
|
const bool ImplicitlyConvertible<From, To>::value;
|
|
|
|
template<bool> struct EnableIf;
|
|
|
|
template<> struct EnableIf<true> { typedef void type; };
|
|
|
|
|
|
|
|
} // end internal
|
|
|
|
|
|
|
|
|
|
|
|
class AssertionResult {
|
|
|
|
public:
|
|
|
|
|
|
|
|
// The implementation for the copy constructor is not exposed in the
|
|
|
|
// interface.
|
|
|
|
AssertionResult(const AssertionResult& other);
|
|
|
|
|
|
|
|
#if defined(GTEST_VERSION_1_8_AND_LATER)
|
|
|
|
template <typename T>
|
|
|
|
explicit AssertionResult(
|
|
|
|
const T& success,
|
|
|
|
typename internal::EnableIf<
|
|
|
|
!internal::ImplicitlyConvertible<T, AssertionResult>::value>::type*
|
|
|
|
/*enabler*/ = 0)
|
|
|
|
: success_(success) {}
|
|
|
|
#else
|
|
|
|
explicit AssertionResult(bool success) : success_(success) {}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
operator bool() const { return success_; }
|
|
|
|
|
|
|
|
// The actual AssertionResult does not have an explicit destructor, but
|
|
|
|
// it does have a non-trivial member veriable, so we add a destructor here
|
|
|
|
// to force temporary cleanups.
|
|
|
|
~AssertionResult();
|
|
|
|
private:
|
|
|
|
|
|
|
|
bool success_;
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace internal {
|
|
|
|
std::string GetBoolAssertionFailureMessage(
|
|
|
|
const AssertionResult& assertion_result,
|
|
|
|
const char* expression_text,
|
|
|
|
const char* actual_predicate_value,
|
|
|
|
const char* expected_predicate_value);
|
|
|
|
} // end internal
|
|
|
|
|
|
|
|
} // end testing
|
|
|
|
|
|
|
|
#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
|
|
|
|
::testing::internal::AssertHelper(result_type, file, line, message) \
|
|
|
|
= ::testing::Message()
|
|
|
|
|
|
|
|
#define GTEST_MESSAGE_(message, result_type) \
|
|
|
|
GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
|
|
|
|
|
|
|
|
#define GTEST_FATAL_FAILURE_(message) \
|
|
|
|
return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
|
|
|
|
|
|
|
|
#define GTEST_NONFATAL_FAILURE_(message) \
|
|
|
|
GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
|
|
|
|
|
|
|
|
# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default:
|
|
|
|
|
|
|
|
#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
|
|
|
|
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
|
|
|
|
if (const ::testing::AssertionResult gtest_ar_ = \
|
|
|
|
::testing::AssertionResult(expression)) \
|
|
|
|
; \
|
|
|
|
else \
|
|
|
|
fail(::testing::internal::GetBoolAssertionFailureMessage(\
|
|
|
|
gtest_ar_, text, #actual, #expected).c_str())
|
|
|
|
|
|
|
|
#define EXPECT_TRUE(condition) \
|
|
|
|
GTEST_TEST_BOOLEAN_((condition), #condition, false, true, \
|
|
|
|
GTEST_NONFATAL_FAILURE_)
|
|
|
|
#define ASSERT_TRUE(condition) \
|
|
|
|
GTEST_TEST_BOOLEAN_((condition), #condition, false, true, \
|
|
|
|
GTEST_FATAL_FAILURE_)
|
|
|
|
|
|
|
|
#define ASSERT_FALSE(condition) \
|
|
|
|
GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
|
|
|
|
GTEST_FATAL_FAILURE_)
|
|
|
|
|
|
|
|
void testAssertTrue(int *p) {
|
|
|
|
ASSERT_TRUE(p != nullptr);
|
|
|
|
EXPECT_TRUE(1 == *p); // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
void testAssertFalse(int *p) {
|
|
|
|
ASSERT_FALSE(p == nullptr);
|
|
|
|
EXPECT_TRUE(1 == *p); // no-warning
|
|
|
|
}
|
2016-12-23 01:52:57 +08:00
|
|
|
|
|
|
|
void testConstrainState(int p) {
|
|
|
|
ASSERT_TRUE(p == 7);
|
|
|
|
|
|
|
|
clang_analyzer_eval(p == 7); // expected-warning {{TRUE}}
|
|
|
|
|
|
|
|
ASSERT_TRUE(false);
|
|
|
|
clang_analyzer_warnIfReached(); // no-warning
|
|
|
|
}
|
2017-10-04 23:59:40 +08:00
|
|
|
|
|
|
|
void testAssertSymbolicPtr(const bool *b) {
|
|
|
|
ASSERT_TRUE(*b); // no-crash
|
|
|
|
|
2018-06-28 08:30:18 +08:00
|
|
|
clang_analyzer_eval(*b); // expected-warning{{TRUE}}
|
2017-10-04 23:59:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void testAssertSymbolicRef(const bool &b) {
|
|
|
|
ASSERT_TRUE(b); // no-crash
|
|
|
|
|
2018-06-28 08:30:18 +08:00
|
|
|
clang_analyzer_eval(b); // expected-warning{{TRUE}}
|
2017-10-04 23:59:40 +08:00
|
|
|
}
|