blob: 1411ede92e36641d4c2c72b72e4717527e3f792c [file] [log] [blame]
Artem Dergachevb0914e72019-10-19 00:08:17 +00001// RUN: %clang_analyze_cc1 -std=c++14 \
Csaba Dabis0202c352019-08-22 00:20:36 +00002// RUN: -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
3// RUN: -verify %s
4
5#include "Inputs/llvm.h"
6
7void clang_analyzer_numTimesReached();
8void clang_analyzer_warnIfReached();
9void clang_analyzer_eval(bool);
10
11namespace clang {
12struct Shape {
13 template <typename T>
14 const T *castAs() const;
15
16 template <typename T>
17 const T *getAs() const;
Artem Dergachev62a76d02019-08-23 03:24:01 +000018
19 virtual double area();
Csaba Dabis0202c352019-08-22 00:20:36 +000020};
21class Triangle : public Shape {};
Artem Dergachev85f72942019-08-23 03:24:04 +000022class Circle : public Shape {
23public:
24 ~Circle();
25};
26class SuspiciouslySpecificCircle : public Circle {};
Csaba Dabis0202c352019-08-22 00:20:36 +000027} // namespace clang
28
29using namespace llvm;
30using namespace clang;
31
Csaba Dabis4d716002019-08-22 02:57:59 +000032void test_regions_dyn_cast(const Shape *A, const Shape *B) {
Csaba Dabis0202c352019-08-22 00:20:36 +000033 if (dyn_cast<Circle>(A) && !dyn_cast<Circle>(B))
34 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
35}
36
Csaba Dabis4d716002019-08-22 02:57:59 +000037void test_regions_isa(const Shape *A, const Shape *B) {
38 if (isa<Circle>(A) && !isa<Circle>(B))
39 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
40}
41
Csaba Dabis0202c352019-08-22 00:20:36 +000042namespace test_cast {
43void evalLogic(const Shape *S) {
44 const Circle *C = cast<Circle>(S);
45 clang_analyzer_numTimesReached(); // expected-warning {{1}}
46
47 if (S && C)
48 clang_analyzer_eval(C == S); // expected-warning {{TRUE}}
49
50 if (S && !C)
51 clang_analyzer_warnIfReached(); // no-warning
52
53 if (!S)
54 clang_analyzer_warnIfReached(); // no-warning
55}
56} // namespace test_cast
57
58namespace test_dyn_cast {
59void evalLogic(const Shape *S) {
60 const Circle *C = dyn_cast<Circle>(S);
61 clang_analyzer_numTimesReached(); // expected-warning {{2}}
62
63 if (S && C)
64 clang_analyzer_eval(C == S); // expected-warning {{TRUE}}
65
66 if (S && !C)
67 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
68
69 if (!S)
70 clang_analyzer_warnIfReached(); // no-warning
71}
72} // namespace test_dyn_cast
73
74namespace test_cast_or_null {
75void evalLogic(const Shape *S) {
76 const Circle *C = cast_or_null<Circle>(S);
77 clang_analyzer_numTimesReached(); // expected-warning {{2}}
78
79 if (S && C)
80 clang_analyzer_eval(C == S); // expected-warning {{TRUE}}
81
82 if (S && !C)
83 clang_analyzer_warnIfReached(); // no-warning
84
85 if (!S)
86 clang_analyzer_eval(!C); // expected-warning {{TRUE}}
87}
88} // namespace test_cast_or_null
89
90namespace test_dyn_cast_or_null {
91void evalLogic(const Shape *S) {
92 const Circle *C = dyn_cast_or_null<Circle>(S);
93 clang_analyzer_numTimesReached(); // expected-warning {{3}}
94
95 if (S && C)
96 clang_analyzer_eval(C == S); // expected-warning {{TRUE}}
97
98 if (S && !C)
99 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
100
101 if (!S)
102 clang_analyzer_eval(!C); // expected-warning {{TRUE}}
103}
104} // namespace test_dyn_cast_or_null
105
106namespace test_cast_as {
107void evalLogic(const Shape *S) {
108 const Circle *C = S->castAs<Circle>();
109 clang_analyzer_numTimesReached(); // expected-warning {{1}}
110
111 if (S && C)
112 clang_analyzer_eval(C == S);
113 // expected-warning@-1 {{TRUE}}
114
115 if (S && !C)
116 clang_analyzer_warnIfReached(); // no-warning
117
118 if (!S)
119 clang_analyzer_warnIfReached(); // no-warning
120}
121} // namespace test_cast_as
122
123namespace test_get_as {
124void evalLogic(const Shape *S) {
125 const Circle *C = S->getAs<Circle>();
126 clang_analyzer_numTimesReached(); // expected-warning {{2}}
127
128 if (S && C)
129 clang_analyzer_eval(C == S);
130 // expected-warning@-1 {{TRUE}}
131
132 if (S && !C)
133 clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
134
135 if (!S)
136 clang_analyzer_warnIfReached(); // no-warning
137}
138} // namespace test_get_as
139
Artem Dergachev0900b772019-08-23 03:23:55 +0000140namespace crashes {
141void test_non_reference_null_region_crash(Shape s) {
142 cast<Circle>(s); // no-crash
143}
Artem Dergachevaf992e62019-08-23 03:23:58 +0000144
145void test_non_reference_temporary_crash() {
146 extern std::unique_ptr<Shape> foo();
147 auto P = foo();
148 auto Q = cast<Circle>(std::move(P)); // no-crash
149}
Artem Dergachev62a76d02019-08-23 03:24:01 +0000150
151double test_virtual_method_after_call(Shape *S) {
152 if (isa<Circle>(S))
153 return S->area();
154 return S->area() / 2;
155}
Artem Dergachev85f72942019-08-23 03:24:04 +0000156
157void test_delete_crash() {
158 extern Circle *makeCircle();
159 Shape *S = makeCircle();
160 delete cast<SuspiciouslySpecificCircle>(S);
161}
Artem Dergachev0900b772019-08-23 03:23:55 +0000162} // namespace crashes