1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
// RUN: %clang_analyze_cc1 \
// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
// RUN: -verify=logic %s
// RUN: %clang_analyze_cc1 \
// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue \
// RUN: -analyzer-output=text -verify %s
void clang_analyzer_numTimesReached();
void clang_analyzer_warnIfReached();
void clang_analyzer_eval(bool);
namespace llvm {
template <class X, class Y>
const X *cast(Y Value);
template <class X, class Y>
const X *dyn_cast(Y Value);
template <class X, class Y>
const X *cast_or_null(Y Value);
template <class X, class Y>
const X *dyn_cast_or_null(Y Value);
} // namespace llvm
using namespace llvm;
class Shape {};
class Triangle : public Shape {};
class Circle : public Shape {};
namespace test_cast {
void evalLogic(const Shape *S) {
const Circle *C = cast<Circle>(S);
clang_analyzer_numTimesReached(); // logic-warning {{1}}
if (S && C)
clang_analyzer_eval(C == S); // logic-warning {{TRUE}}
if (S && !C)
clang_analyzer_warnIfReached(); // no-warning
if (!S)
clang_analyzer_warnIfReached(); // no-warning
}
} // namespace test_cast
namespace test_dyn_cast {
void evalLogic(const Shape *S) {
const Circle *C = dyn_cast<Circle>(S);
clang_analyzer_numTimesReached(); // logic-warning {{2}}
if (S && C)
clang_analyzer_eval(C == S); // logic-warning {{TRUE}}
if (S && !C)
clang_analyzer_warnIfReached(); // logic-warning {{REACHABLE}}
if (!S)
clang_analyzer_warnIfReached(); // no-warning
}
} // namespace test_dyn_cast
namespace test_cast_or_null {
void evalLogic(const Shape *S) {
const Circle *C = cast_or_null<Circle>(S);
clang_analyzer_numTimesReached(); // logic-warning {{2}}
if (S && C)
clang_analyzer_eval(C == S); // logic-warning {{TRUE}}
if (S && !C)
clang_analyzer_warnIfReached(); // no-warning
if (!S)
clang_analyzer_eval(!C); // logic-warning {{TRUE}}
}
} // namespace test_cast_or_null
namespace test_dyn_cast_or_null {
void evalLogic(const Shape *S) {
const Circle *C = dyn_cast_or_null<Circle>(S);
clang_analyzer_numTimesReached(); // logic-warning {{3}}
if (S && C)
clang_analyzer_eval(C == S); // logic-warning {{TRUE}}
if (S && !C)
clang_analyzer_warnIfReached(); // logic-warning {{REACHABLE}}
if (!S)
clang_analyzer_eval(!C); // logic-warning {{TRUE}}
}
void evalNonNullParamNonNullReturn(const Shape *S) {
const auto *C = dyn_cast_or_null<Circle>(S);
// expected-note@-1 {{Assuming dynamic cast from 'Shape' to 'Circle' succeeds}}
// expected-note@-2 {{Assuming pointer value is null}}
// expected-note@-3 {{'C' initialized here}}
(void)(1 / !(bool)C);
// expected-note@-1 {{'C' is non-null}}
// expected-note@-2 {{Division by zero}}
// expected-warning@-3 {{Division by zero}}
// logic-warning@-4 {{Division by zero}}
}
void evalNonNullParamNullReturn(const Shape *S) {
const auto *C = dyn_cast_or_null<Circle>(S);
// expected-note@-1 {{Assuming dynamic cast from 'Shape' to 'Circle' fails}}
// expected-note@-2 {{Assuming pointer value is null}}
if (const auto *T = dyn_cast_or_null<Triangle>(S)) {
// expected-note@-1 {{Assuming dynamic cast from 'Shape' to 'Triangle' succeeds}}
// expected-note@-2 {{'T' initialized here}}
// expected-note@-3 {{'T' is non-null}}
// expected-note@-4 {{Taking true branch}}
(void)(1 / !T);
// expected-note@-1 {{'T' is non-null}}
// expected-note@-2 {{Division by zero}}
// expected-warning@-3 {{Division by zero}}
// logic-warning@-4 {{Division by zero}}
}
}
void evalNullParamNullReturn(const Shape *S) {
const auto *C = dyn_cast_or_null<Circle>(S);
// expected-note@-1 {{Assuming null pointer is passed into cast}}
// expected-note@-2 {{'C' initialized to a null pointer value}}
(void)(1 / (bool)C);
// expected-note@-1 {{Division by zero}}
// expected-warning@-2 {{Division by zero}}
// logic-warning@-3 {{Division by zero}}
}
} // namespace test_dyn_cast_or_null
|