1 // RUN: %clang_analyze_cc1 -std=c++14 \
2 // RUN:  -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection\
3 // RUN:  -analyzer-output=text -verify %s
4 
5 #include "Inputs/llvm.h"
6 
7 namespace clang {
8 struct Shape {
9   template <typename T>
10   const T *castAs() const;
11 
12   template <typename T>
13   const T *getAs() const;
14 };
15 class Triangle : public Shape {};
16 class Rectangle : public Shape {};
17 class Hexagon : public Shape {};
18 class Circle : public Shape {};
19 } // namespace clang
20 
21 using namespace llvm;
22 using namespace clang;
23 
evalReferences(const Shape & S)24 void evalReferences(const Shape &S) {
25   const auto &C = dyn_cast<Circle>(S);
26   // expected-note@-1 {{Assuming 'S' is not a 'Circle'}}
27   // expected-note@-2 {{Dereference of null pointer}}
28   // expected-warning@-3 {{Dereference of null pointer}}
29 }
30 
evalNonNullParamNonNullReturnReference(const Shape & S)31 void evalNonNullParamNonNullReturnReference(const Shape &S) {
32   const auto *C = dyn_cast_or_null<Circle>(S);
33   // expected-note@-1 {{'C' initialized here}}
34 
35   if (!dyn_cast_or_null<Circle>(C)) {
36     // expected-note@-1 {{'C' is a 'Circle'}}
37     // expected-note@-2 {{Taking false branch}}
38     return;
39   }
40 
41   if (dyn_cast_or_null<Triangle>(C)) {
42     // expected-note@-1 {{Assuming 'C' is not a 'Triangle'}}
43     // expected-note@-2 {{Taking false branch}}
44     return;
45   }
46 
47   if (dyn_cast_or_null<Rectangle>(C)) {
48     // expected-note@-1 {{Assuming 'C' is not a 'Rectangle'}}
49     // expected-note@-2 {{Taking false branch}}
50     return;
51   }
52 
53   if (dyn_cast_or_null<Hexagon>(C)) {
54     // expected-note@-1 {{Assuming 'C' is not a 'Hexagon'}}
55     // expected-note@-2 {{Taking false branch}}
56     return;
57   }
58 
59   if (isa<Triangle>(C)) {
60     // expected-note@-1 {{'C' is not a 'Triangle'}}
61     // expected-note@-2 {{Taking false branch}}
62     return;
63   }
64 
65   if (isa<Triangle, Rectangle>(C)) {
66     // expected-note@-1 {{'C' is neither a 'Triangle' nor a 'Rectangle'}}
67     // expected-note@-2 {{Taking false branch}}
68     return;
69   }
70 
71   if (isa<Triangle, Rectangle, Hexagon>(C)) {
72     // expected-note@-1 {{'C' is neither a 'Triangle' nor a 'Rectangle' nor a 'Hexagon'}}
73     // expected-note@-2 {{Taking false branch}}
74     return;
75   }
76 
77   if (isa<Circle, Rectangle, Hexagon>(C)) {
78     // expected-note@-1 {{'C' is a 'Circle'}}
79     // expected-note@-2 {{Taking true branch}}
80 
81     (void)(1 / !C);
82     // expected-note@-1 {{'C' is non-null}}
83     // expected-note@-2 {{Division by zero}}
84     // expected-warning@-3 {{Division by zero}}
85   }
86 }
87 
evalNonNullParamNonNullReturn(const Shape * S)88 void evalNonNullParamNonNullReturn(const Shape *S) {
89   const auto *C = cast<Circle>(S);
90   // expected-note@-1 {{'S' is a 'Circle'}}
91   // expected-note@-2 {{'C' initialized here}}
92 
93   if (!dyn_cast_or_null<Circle>(C)) {
94     // expected-note@-1 {{'C' is a 'Circle'}}
95     // expected-note@-2 {{Taking false branch}}
96     return;
97   }
98 
99   if (dyn_cast_or_null<Triangle>(C)) {
100     // expected-note@-1 {{Assuming 'C' is not a 'Triangle'}}
101     // expected-note@-2 {{Taking false branch}}
102     return;
103   }
104 
105   if (dyn_cast_or_null<Rectangle>(C)) {
106     // expected-note@-1 {{Assuming 'C' is not a 'Rectangle'}}
107     // expected-note@-2 {{Taking false branch}}
108     return;
109   }
110 
111   if (dyn_cast_or_null<Hexagon>(C)) {
112     // expected-note@-1 {{Assuming 'C' is not a 'Hexagon'}}
113     // expected-note@-2 {{Taking false branch}}
114     return;
115   }
116 
117   if (isa<Triangle>(C)) {
118     // expected-note@-1 {{'C' is not a 'Triangle'}}
119     // expected-note@-2 {{Taking false branch}}
120     return;
121   }
122 
123   if (isa<Triangle, Rectangle>(C)) {
124     // expected-note@-1 {{'C' is neither a 'Triangle' nor a 'Rectangle'}}
125     // expected-note@-2 {{Taking false branch}}
126     return;
127   }
128 
129   if (isa<Triangle, Rectangle, Hexagon>(C)) {
130     // expected-note@-1 {{'C' is neither a 'Triangle' nor a 'Rectangle' nor a 'Hexagon'}}
131     // expected-note@-2 {{Taking false branch}}
132     return;
133   }
134 
135   if (isa<Circle, Rectangle, Hexagon>(C)) {
136     // expected-note@-1 {{'C' is a 'Circle'}}
137     // expected-note@-2 {{Taking true branch}}
138 
139     (void)(1 / !C);
140     // expected-note@-1 {{'C' is non-null}}
141     // expected-note@-2 {{Division by zero}}
142     // expected-warning@-3 {{Division by zero}}
143   }
144 }
145 
evalNonNullParamNullReturn(const Shape * S)146 void evalNonNullParamNullReturn(const Shape *S) {
147   const auto *C = dyn_cast_or_null<Circle>(S);
148   // expected-note@-1 {{Assuming 'S' is not a 'Circle'}}
149 
150   if (const auto *T = dyn_cast_or_null<Triangle>(S)) {
151     // expected-note@-1 {{Assuming 'S' is a 'Triangle'}}
152     // expected-note@-2 {{'T' initialized here}}
153     // expected-note@-3 {{'T' is non-null}}
154     // expected-note@-4 {{Taking true branch}}
155 
156     (void)(1 / !T);
157     // expected-note@-1 {{'T' is non-null}}
158     // expected-note@-2 {{Division by zero}}
159     // expected-warning@-3 {{Division by zero}}
160   }
161 }
162 
evalNullParamNullReturn(const Shape * S)163 void evalNullParamNullReturn(const Shape *S) {
164   const auto *C = dyn_cast_or_null<Circle>(S);
165   // expected-note@-1 {{Assuming null pointer is passed into cast}}
166   // expected-note@-2 {{'C' initialized to a null pointer value}}
167 
168   (void)(1 / (bool)C);
169   // expected-note@-1 {{Division by zero}}
170   // expected-warning@-2 {{Division by zero}}
171 }
172 
evalZeroParamNonNullReturnPointer(const Shape * S)173 void evalZeroParamNonNullReturnPointer(const Shape *S) {
174   const auto *C = S->castAs<Circle>();
175   // expected-note@-1 {{'S' is a 'Circle'}}
176   // expected-note@-2 {{'C' initialized here}}
177 
178   (void)(1 / !C);
179   // expected-note@-1 {{'C' is non-null}}
180   // expected-note@-2 {{Division by zero}}
181   // expected-warning@-3 {{Division by zero}}
182 }
183 
evalZeroParamNonNullReturn(const Shape & S)184 void evalZeroParamNonNullReturn(const Shape &S) {
185   const auto *C = S.castAs<Circle>();
186   // expected-note@-1 {{'C' initialized here}}
187 
188   (void)(1 / !C);
189   // expected-note@-1 {{'C' is non-null}}
190   // expected-note@-2 {{Division by zero}}
191   // expected-warning@-3 {{Division by zero}}
192 }
193 
evalZeroParamNullReturn(const Shape * S)194 void evalZeroParamNullReturn(const Shape *S) {
195   const auto &C = S->getAs<Circle>();
196   // expected-note@-1 {{Assuming 'S' is not a 'Circle'}}
197   // expected-note@-2 {{Storing null pointer value}}
198   // expected-note@-3 {{'C' initialized here}}
199 
200   if (!dyn_cast_or_null<Triangle>(S)) {
201     // expected-note@-1 {{Assuming 'S' is a 'Triangle'}}
202     // expected-note@-2 {{Taking false branch}}
203     return;
204   }
205 
206   if (!dyn_cast_or_null<Triangle>(S)) {
207     // expected-note@-1 {{'S' is a 'Triangle'}}
208     // expected-note@-2 {{Taking false branch}}
209     return;
210   }
211 
212   (void)(1 / (bool)C);
213   // expected-note@-1 {{Division by zero}}
214   // expected-warning@-2 {{Division by zero}}
215 }
216