1 // RUN: %clang_analyze_cc1 -std=c++14 \
2 // RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
5 #include "Inputs/llvm.h"
7 void clang_analyzer_numTimesReached();
8 void clang_analyzer_warnIfReached();
9 void clang_analyzer_eval(bool);
14 const T
*castAs() const;
17 const T
*getAs() const;
19 virtual double area();
21 class Triangle
: public Shape
{};
22 class Rectangle
: public Shape
{};
23 class Hexagon
: public Shape
{};
24 class Circle
: public Shape
{
28 class SuspiciouslySpecificCircle
: public Circle
{};
32 using namespace clang
;
34 void test_regions_dyn_cast(const Shape
*A
, const Shape
*B
) {
35 if (dyn_cast
<Circle
>(A
) && !dyn_cast
<Circle
>(B
))
36 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
39 void test_regions_isa(const Shape
*A
, const Shape
*B
) {
40 if (isa
<Circle
>(A
) && !isa
<Circle
>(B
))
41 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
44 void test_regions_isa_variadic(const Shape
*A
, const Shape
*B
) {
45 if (isa
<Triangle
, Rectangle
, Hexagon
>(A
) &&
46 !isa
<Rectangle
, Hexagon
, Circle
>(B
))
47 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
50 void test_regions_isa_and_nonnull(const Shape
*A
, const Shape
*B
) {
51 if (isa_and_nonnull
<Circle
>(A
) && !isa_and_nonnull
<Circle
>(B
))
52 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
55 void test_regions_isa_and_nonnull_variadic(const Shape
*A
, const Shape
*B
) {
56 if (isa_and_nonnull
<Triangle
, Rectangle
, Hexagon
>(A
) &&
57 !isa_and_nonnull
<Rectangle
, Hexagon
, Circle
>(B
))
58 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
62 void evalLogic(const Shape
*S
) {
63 const Circle
*C
= cast
<Circle
>(S
);
64 clang_analyzer_numTimesReached(); // expected-warning {{1}}
67 clang_analyzer_eval(C
== S
); // expected-warning {{TRUE}}
70 clang_analyzer_warnIfReached(); // no-warning
73 clang_analyzer_warnIfReached(); // no-warning
75 } // namespace test_cast
77 namespace test_dyn_cast
{
78 void evalLogic(const Shape
*S
) {
79 const Circle
*C
= dyn_cast
<Circle
>(S
);
80 clang_analyzer_numTimesReached(); // expected-warning {{2}}
83 clang_analyzer_eval(C
== S
); // expected-warning {{TRUE}}
86 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
89 clang_analyzer_warnIfReached(); // no-warning
91 } // namespace test_dyn_cast
93 namespace test_cast_or_null
{
94 void evalLogic(const Shape
*S
) {
95 const Circle
*C
= cast_or_null
<Circle
>(S
);
96 clang_analyzer_numTimesReached(); // expected-warning {{2}}
99 clang_analyzer_eval(C
== S
); // expected-warning {{TRUE}}
102 clang_analyzer_warnIfReached(); // no-warning
105 clang_analyzer_eval(!C
); // expected-warning {{TRUE}}
107 } // namespace test_cast_or_null
109 namespace test_dyn_cast_or_null
{
110 void evalLogic(const Shape
*S
) {
111 const Circle
*C
= dyn_cast_or_null
<Circle
>(S
);
112 clang_analyzer_numTimesReached(); // expected-warning {{3}}
115 clang_analyzer_eval(C
== S
); // expected-warning {{TRUE}}
118 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
121 clang_analyzer_eval(!C
); // expected-warning {{TRUE}}
123 } // namespace test_dyn_cast_or_null
125 namespace test_cast_as
{
126 void evalLogic(const Shape
*S
) {
127 const Circle
*C
= S
->castAs
<Circle
>();
128 clang_analyzer_numTimesReached(); // expected-warning {{1}}
131 clang_analyzer_eval(C
== S
);
132 // expected-warning@-1 {{TRUE}}
135 clang_analyzer_warnIfReached(); // no-warning
138 clang_analyzer_warnIfReached(); // no-warning
140 } // namespace test_cast_as
142 namespace test_get_as
{
143 void evalLogic(const Shape
*S
) {
144 const Circle
*C
= S
->getAs
<Circle
>();
145 clang_analyzer_numTimesReached(); // expected-warning {{2}}
148 clang_analyzer_eval(C
== S
);
149 // expected-warning@-1 {{TRUE}}
152 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
155 clang_analyzer_warnIfReached(); // no-warning
157 } // namespace test_get_as
160 void test_non_reference_null_region_crash(Shape s
) {
161 cast
<Circle
>(s
); // no-crash
164 void test_non_reference_temporary_crash() {
165 extern std::unique_ptr
<Shape
> foo();
167 auto Q
= cast
<Circle
>(std::move(P
)); // no-crash
170 double test_virtual_method_after_call(Shape
*S
) {
173 return S
->area() / 2;
176 void test_delete_crash() {
177 extern Circle
*makeCircle();
178 Shape
*S
= makeCircle();
179 delete cast
<SuspiciouslySpecificCircle
>(S
);
181 } // namespace crashes