/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- CallEvent.h - Wrapper for all function and method calls --*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | /// \file This file defines CallEvent and its subclasses, which represent path- |
10 | | /// sensitive instances of different kinds of function and method calls |
11 | | /// (C, C++, and Objective-C). |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H |
16 | | #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H |
17 | | |
18 | | #include "clang/AST/Decl.h" |
19 | | #include "clang/AST/DeclBase.h" |
20 | | #include "clang/AST/DeclCXX.h" |
21 | | #include "clang/AST/DeclObjC.h" |
22 | | #include "clang/AST/Expr.h" |
23 | | #include "clang/AST/ExprCXX.h" |
24 | | #include "clang/AST/ExprObjC.h" |
25 | | #include "clang/AST/Stmt.h" |
26 | | #include "clang/AST/Type.h" |
27 | | #include "clang/Basic/IdentifierTable.h" |
28 | | #include "clang/Basic/LLVM.h" |
29 | | #include "clang/Basic/SourceLocation.h" |
30 | | #include "clang/Basic/SourceManager.h" |
31 | | #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" |
32 | | #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" |
33 | | #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" |
34 | | #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" |
35 | | #include "llvm/ADT/ArrayRef.h" |
36 | | #include "llvm/ADT/IntrusiveRefCntPtr.h" |
37 | | #include "llvm/ADT/PointerIntPair.h" |
38 | | #include "llvm/ADT/PointerUnion.h" |
39 | | #include "llvm/ADT/STLExtras.h" |
40 | | #include "llvm/ADT/SmallVector.h" |
41 | | #include "llvm/ADT/StringRef.h" |
42 | | #include "llvm/ADT/iterator_range.h" |
43 | | #include "llvm/Support/Allocator.h" |
44 | | #include "llvm/Support/Casting.h" |
45 | | #include "llvm/Support/ErrorHandling.h" |
46 | | #include <cassert> |
47 | | #include <limits> |
48 | | #include <utility> |
49 | | |
50 | | namespace clang { |
51 | | |
52 | | class LocationContext; |
53 | | class ProgramPoint; |
54 | | class ProgramPointTag; |
55 | | class StackFrameContext; |
56 | | |
57 | | namespace ento { |
58 | | |
59 | | enum CallEventKind { |
60 | | CE_Function, |
61 | | CE_CXXMember, |
62 | | CE_CXXMemberOperator, |
63 | | CE_CXXDestructor, |
64 | | CE_BEG_CXX_INSTANCE_CALLS = CE_CXXMember, |
65 | | CE_END_CXX_INSTANCE_CALLS = CE_CXXDestructor, |
66 | | CE_CXXConstructor, |
67 | | CE_CXXInheritedConstructor, |
68 | | CE_BEG_CXX_CONSTRUCTOR_CALLS = CE_CXXConstructor, |
69 | | CE_END_CXX_CONSTRUCTOR_CALLS = CE_CXXInheritedConstructor, |
70 | | CE_CXXAllocator, |
71 | | CE_CXXDeallocator, |
72 | | CE_BEG_FUNCTION_CALLS = CE_Function, |
73 | | CE_END_FUNCTION_CALLS = CE_CXXDeallocator, |
74 | | CE_Block, |
75 | | CE_ObjCMessage |
76 | | }; |
77 | | |
78 | | class CallEvent; |
79 | | class CallDescription; |
80 | | |
81 | | template<typename T = CallEvent> |
82 | | class CallEventRef : public IntrusiveRefCntPtr<const T> { |
83 | | public: |
84 | 1.27M | CallEventRef(const T *Call) : IntrusiveRefCntPtr<const T>(Call) {} clang::ento::CallEventRef<clang::ento::ObjCMethodCall>::CallEventRef(clang::ento::ObjCMethodCall const*) Line | Count | Source | 84 | 28.3k | CallEventRef(const T *Call) : IntrusiveRefCntPtr<const T>(Call) {} |
clang::ento::CallEventRef<clang::ento::CallEvent>::CallEventRef(clang::ento::CallEvent const*) Line | Count | Source | 84 | 1.19M | CallEventRef(const T *Call) : IntrusiveRefCntPtr<const T>(Call) {} |
clang::ento::CallEventRef<clang::ento::CXXConstructorCall>::CallEventRef(clang::ento::CXXConstructorCall const*) Line | Count | Source | 84 | 41.0k | CallEventRef(const T *Call) : IntrusiveRefCntPtr<const T>(Call) {} |
clang::ento::CallEventRef<clang::ento::CXXInheritedConstructorCall>::CallEventRef(clang::ento::CXXInheritedConstructorCall const*) Line | Count | Source | 84 | 13 | CallEventRef(const T *Call) : IntrusiveRefCntPtr<const T>(Call) {} |
clang::ento::CallEventRef<clang::ento::CXXDestructorCall>::CallEventRef(clang::ento::CXXDestructorCall const*) Line | Count | Source | 84 | 2.97k | CallEventRef(const T *Call) : IntrusiveRefCntPtr<const T>(Call) {} |
clang::ento::CallEventRef<clang::ento::CXXAllocatorCall>::CallEventRef(clang::ento::CXXAllocatorCall const*) Line | Count | Source | 84 | 2.83k | CallEventRef(const T *Call) : IntrusiveRefCntPtr<const T>(Call) {} |
clang::ento::CallEventRef<clang::ento::CXXDeallocatorCall>::CallEventRef(clang::ento::CXXDeallocatorCall const*) Line | Count | Source | 84 | 436 | CallEventRef(const T *Call) : IntrusiveRefCntPtr<const T>(Call) {} |
|
85 | 72.0k | CallEventRef(const CallEventRef &Orig) : IntrusiveRefCntPtr<const T>(Orig) {} |
86 | | |
87 | 43.4k | CallEventRef<T> cloneWithState(ProgramStateRef State) const { |
88 | 43.4k | return this->get()->template cloneWithState<T>(State); |
89 | 43.4k | } clang::ento::CallEventRef<clang::ento::CallEvent>::cloneWithState(llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>) const Line | Count | Source | 87 | 39.4k | CallEventRef<T> cloneWithState(ProgramStateRef State) const { | 88 | 39.4k | return this->get()->template cloneWithState<T>(State); | 89 | 39.4k | } |
clang::ento::CallEventRef<clang::ento::ObjCMethodCall>::cloneWithState(llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>) const Line | Count | Source | 87 | 4.00k | CallEventRef<T> cloneWithState(ProgramStateRef State) const { | 88 | 4.00k | return this->get()->template cloneWithState<T>(State); | 89 | 4.00k | } |
|
90 | | |
91 | | // Allow implicit conversions to a superclass type, since CallEventRef |
92 | | // behaves like a pointer-to-const. |
93 | | template <typename SuperT> |
94 | 45.1k | operator CallEventRef<SuperT> () const { |
95 | 45.1k | return this->get(); |
96 | 45.1k | } clang::ento::CallEventRef<clang::ento::CXXDestructorCall>::operator clang::ento::CallEventRef<clang::ento::CallEvent><clang::ento::CallEvent>() const Line | Count | Source | 94 | 1.47k | operator CallEventRef<SuperT> () const { | 95 | 1.47k | return this->get(); | 96 | 1.47k | } |
clang::ento::CallEventRef<clang::ento::CXXAllocatorCall>::operator clang::ento::CallEventRef<clang::ento::CallEvent><clang::ento::CallEvent>() const Line | Count | Source | 94 | 817 | operator CallEventRef<SuperT> () const { | 95 | 817 | return this->get(); | 96 | 817 | } |
clang::ento::CallEventRef<clang::ento::CXXConstructorCall>::operator clang::ento::CallEventRef<clang::ento::CallEvent><clang::ento::CallEvent>() const Line | Count | Source | 94 | 41.0k | operator CallEventRef<SuperT> () const { | 95 | 41.0k | return this->get(); | 96 | 41.0k | } |
clang::ento::CallEventRef<clang::ento::ObjCMethodCall>::operator clang::ento::CallEventRef<clang::ento::CallEvent><clang::ento::CallEvent>() const Line | Count | Source | 94 | 1.77k | operator CallEventRef<SuperT> () const { | 95 | 1.77k | return this->get(); | 96 | 1.77k | } |
clang::ento::CallEventRef<clang::ento::CXXInheritedConstructorCall>::operator clang::ento::CallEventRef<clang::ento::CallEvent><clang::ento::CallEvent>() const Line | Count | Source | 94 | 13 | operator CallEventRef<SuperT> () const { | 95 | 13 | return this->get(); | 96 | 13 | } |
|
97 | | }; |
98 | | |
99 | | /// \class RuntimeDefinition |
100 | | /// Defines the runtime definition of the called function. |
101 | | /// |
102 | | /// Encapsulates the information we have about which Decl will be used |
103 | | /// when the call is executed on the given path. When dealing with dynamic |
104 | | /// dispatch, the information is based on DynamicTypeInfo and might not be |
105 | | /// precise. |
106 | | class RuntimeDefinition { |
107 | | /// The Declaration of the function which could be called at runtime. |
108 | | /// NULL if not available. |
109 | | const Decl *D = nullptr; |
110 | | |
111 | | /// The region representing an object (ObjC/C++) on which the method is |
112 | | /// called. With dynamic dispatch, the method definition depends on the |
113 | | /// runtime type of this object. NULL when the DynamicTypeInfo is |
114 | | /// precise. |
115 | | const MemRegion *R = nullptr; |
116 | | |
117 | | public: |
118 | 25.4k | RuntimeDefinition() = default; |
119 | 37.7k | RuntimeDefinition(const Decl *InD): D(InD) {} |
120 | 2.85k | RuntimeDefinition(const Decl *InD, const MemRegion *InR): D(InD), R(InR) {} |
121 | | |
122 | 66.0k | const Decl *getDecl() { return D; } |
123 | | |
124 | | /// Check if the definition we have is precise. |
125 | | /// If not, it is possible that the call dispatches to another definition at |
126 | | /// execution time. |
127 | 33.8k | bool mayHaveOtherDefinitions() { return R != nullptr; } |
128 | | |
129 | | /// When other definitions are possible, returns the region whose runtime type |
130 | | /// determines the method definition. |
131 | 15 | const MemRegion *getDispatchRegion() { return R; } |
132 | | }; |
133 | | |
134 | | /// Represents an abstract call to a function or method along a |
135 | | /// particular path. |
136 | | /// |
137 | | /// CallEvents are created through the factory methods of CallEventManager. |
138 | | /// |
139 | | /// CallEvents should always be cheap to create and destroy. In order for |
140 | | /// CallEventManager to be able to re-use CallEvent-sized memory blocks, |
141 | | /// subclasses of CallEvent may not add any data members to the base class. |
142 | | /// Use the "Data" and "Location" fields instead. |
143 | | class CallEvent { |
144 | | public: |
145 | | using Kind = CallEventKind; |
146 | | |
147 | | private: |
148 | | ProgramStateRef State; |
149 | | const LocationContext *LCtx; |
150 | | llvm::PointerUnion<const Expr *, const Decl *> Origin; |
151 | | |
152 | | protected: |
153 | | // This is user data for subclasses. |
154 | | const void *Data; |
155 | | |
156 | | // This is user data for subclasses. |
157 | | // This should come right before RefCount, so that the two fields can be |
158 | | // packed together on LP64 platforms. |
159 | | SourceLocation Location; |
160 | | |
161 | | private: |
162 | | template <typename T> friend struct llvm::IntrusiveRefCntPtrInfo; |
163 | | |
164 | | mutable unsigned RefCount = 0; |
165 | | |
166 | 1.32M | void Retain() const { ++RefCount; } |
167 | | void Release() const; |
168 | | |
169 | | protected: |
170 | | friend class CallEventManager; |
171 | | |
172 | | CallEvent(const Expr *E, ProgramStateRef state, const LocationContext *lctx) |
173 | 194k | : State(std::move(state)), LCtx(lctx), Origin(E) {} |
174 | | |
175 | | CallEvent(const Decl *D, ProgramStateRef state, const LocationContext *lctx) |
176 | 2.97k | : State(std::move(state)), LCtx(lctx), Origin(D) {} |
177 | | |
178 | | // DO NOT MAKE PUBLIC |
179 | | CallEvent(const CallEvent &Original) |
180 | | : State(Original.State), LCtx(Original.LCtx), Origin(Original.Origin), |
181 | 272k | Data(Original.Data), Location(Original.Location) {} |
182 | | |
183 | | /// Copies this CallEvent, with vtable intact, into a new block of memory. |
184 | | virtual void cloneTo(void *Dest) const = 0; |
185 | | |
186 | | /// Get the value of arbitrary expressions at this point in the path. |
187 | 431k | SVal getSVal(const Stmt *S) const { |
188 | 431k | return getState()->getSVal(S, getLocationContext()); |
189 | 431k | } |
190 | | |
191 | | using ValueList = SmallVectorImpl<SVal>; |
192 | | |
193 | | /// Used to specify non-argument regions that will be invalidated as a |
194 | | /// result of this call. |
195 | | virtual void getExtraInvalidatedValues(ValueList &Values, |
196 | 20.5k | RegionAndSymbolInvalidationTraits *ETraits) const {} |
197 | | |
198 | | public: |
199 | | CallEvent &operator=(const CallEvent &) = delete; |
200 | 470k | virtual ~CallEvent() = default; |
201 | | |
202 | | /// Returns the kind of call this is. |
203 | | virtual Kind getKind() const = 0; |
204 | | virtual StringRef getKindAsString() const = 0; |
205 | | |
206 | | /// Returns the declaration of the function or method that will be |
207 | | /// called. May be null. |
208 | 42.4k | virtual const Decl *getDecl() const { |
209 | 42.4k | return Origin.dyn_cast<const Decl *>(); |
210 | 42.4k | } |
211 | | |
212 | | /// The state in which the call is being evaluated. |
213 | 661k | const ProgramStateRef &getState() const { |
214 | 661k | return State; |
215 | 661k | } |
216 | | |
217 | | /// The context in which the call is being evaluated. |
218 | 1.62M | const LocationContext *getLocationContext() const { |
219 | 1.62M | return LCtx; |
220 | 1.62M | } |
221 | | |
222 | | /// Returns the definition of the function or method that will be |
223 | | /// called. |
224 | | virtual RuntimeDefinition getRuntimeDefinition() const = 0; |
225 | | |
226 | | /// Returns the expression whose value will be the result of this call. |
227 | | /// May be null. |
228 | 8.90M | virtual const Expr *getOriginExpr() const { |
229 | 8.90M | return Origin.dyn_cast<const Expr *>(); |
230 | 8.90M | } |
231 | | |
232 | | /// Returns the number of arguments (explicit and implicit). |
233 | | /// |
234 | | /// Note that this may be greater than the number of parameters in the |
235 | | /// callee's declaration, and that it may include arguments not written in |
236 | | /// the source. |
237 | | virtual unsigned getNumArgs() const = 0; |
238 | | |
239 | | /// Returns true if the callee is known to be from a system header. |
240 | 38.5k | bool isInSystemHeader() const { |
241 | 38.5k | const Decl *D = getDecl(); |
242 | 38.5k | if (!D) |
243 | 78 | return false; |
244 | | |
245 | 38.4k | SourceLocation Loc = D->getLocation(); |
246 | 38.4k | if (Loc.isValid()) { |
247 | 38.2k | const SourceManager &SM = |
248 | 38.2k | getState()->getStateManager().getContext().getSourceManager(); |
249 | 38.2k | return SM.isInSystemHeader(D->getLocation()); |
250 | 38.2k | } |
251 | | |
252 | | // Special case for implicitly-declared global operator new/delete. |
253 | | // These should be considered system functions. |
254 | 289 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) |
255 | 289 | return FD->isOverloadedOperator() && FD->isImplicit()288 && FD->isGlobal()288 ; |
256 | | |
257 | 0 | return false; |
258 | 0 | } |
259 | | |
260 | | /// Returns true if the CallEvent is a call to a function that matches |
261 | | /// the CallDescription. |
262 | | /// |
263 | | /// Note that this function is not intended to be used to match Obj-C method |
264 | | /// calls. |
265 | | bool isCalled(const CallDescription &CD) const; |
266 | | |
267 | | /// Returns true whether the CallEvent is any of the CallDescriptions supplied |
268 | | /// as a parameter. |
269 | | template <typename FirstCallDesc, typename... CallDescs> |
270 | | bool isCalled(const FirstCallDesc &First, const CallDescs &... Rest) const { |
271 | | return isCalled(First) || isCalled(Rest...); |
272 | | } |
273 | | |
274 | | /// Returns a source range for the entire call, suitable for |
275 | | /// outputting in diagnostics. |
276 | 68 | virtual SourceRange getSourceRange() const { |
277 | 68 | return getOriginExpr()->getSourceRange(); |
278 | 68 | } |
279 | | |
280 | | /// Returns the value of a given argument at the time of the call. |
281 | | virtual SVal getArgSVal(unsigned Index) const; |
282 | | |
283 | | /// Returns the expression associated with a given argument. |
284 | | /// May be null if this expression does not appear in the source. |
285 | 0 | virtual const Expr *getArgExpr(unsigned Index) const { return nullptr; } |
286 | | |
287 | | /// Returns the source range for errors associated with this argument. |
288 | | /// |
289 | | /// May be invalid if the argument is not written in the source. |
290 | | virtual SourceRange getArgSourceRange(unsigned Index) const; |
291 | | |
292 | | /// Returns the result type, adjusted for references. |
293 | | QualType getResultType() const; |
294 | | |
295 | | /// Returns the return value of the call. |
296 | | /// |
297 | | /// This should only be called if the CallEvent was created using a state in |
298 | | /// which the return value has already been bound to the origin expression. |
299 | | SVal getReturnValue() const; |
300 | | |
301 | | /// Returns true if the type of any of the non-null arguments satisfies |
302 | | /// the condition. |
303 | | bool hasNonNullArgumentsWithType(bool (*Condition)(QualType)) const; |
304 | | |
305 | | /// Returns true if any of the arguments appear to represent callbacks. |
306 | | bool hasNonZeroCallbackArg() const; |
307 | | |
308 | | /// Returns true if any of the arguments is void*. |
309 | | bool hasVoidPointerToNonConstArg() const; |
310 | | |
311 | | /// Returns true if any of the arguments are known to escape to long- |
312 | | /// term storage, even if this method will not modify them. |
313 | | // NOTE: The exact semantics of this are still being defined! |
314 | | // We don't really want a list of hardcoded exceptions in the long run, |
315 | | // but we don't want duplicated lists of known APIs in the short term either. |
316 | 31.4k | virtual bool argumentsMayEscape() const { |
317 | 31.4k | return hasNonZeroCallbackArg(); |
318 | 31.4k | } |
319 | | |
320 | | /// Returns true if the callee is an externally-visible function in the |
321 | | /// top-level namespace, such as \c malloc. |
322 | | /// |
323 | | /// You can use this call to determine that a particular function really is |
324 | | /// a library function and not, say, a C++ member function with the same name. |
325 | | /// |
326 | | /// If a name is provided, the function must additionally match the given |
327 | | /// name. |
328 | | /// |
329 | | /// Note that this deliberately excludes C++ library functions in the \c std |
330 | | /// namespace, but will include C library functions accessed through the |
331 | | /// \c std namespace. This also does not check if the function is declared |
332 | | /// as 'extern "C"', or if it uses C++ name mangling. |
333 | | // FIXME: Add a helper for checking namespaces. |
334 | | // FIXME: Move this down to AnyFunctionCall once checkers have more |
335 | | // precise callbacks. |
336 | | bool isGlobalCFunction(StringRef SpecificName = StringRef()) const; |
337 | | |
338 | | /// Returns the name of the callee, if its name is a simple identifier. |
339 | | /// |
340 | | /// Note that this will fail for Objective-C methods, blocks, and C++ |
341 | | /// overloaded operators. The former is named by a Selector rather than a |
342 | | /// simple identifier, and the latter two do not have names. |
343 | | // FIXME: Move this down to AnyFunctionCall once checkers have more |
344 | | // precise callbacks. |
345 | 1.84M | const IdentifierInfo *getCalleeIdentifier() const { |
346 | 1.84M | const auto *ND = dyn_cast_or_null<NamedDecl>(getDecl()); |
347 | 1.84M | if (!ND) |
348 | 343 | return nullptr; |
349 | 1.84M | return ND->getIdentifier(); |
350 | 1.84M | } |
351 | | |
352 | | /// Returns an appropriate ProgramPoint for this call. |
353 | | ProgramPoint getProgramPoint(bool IsPreVisit = false, |
354 | | const ProgramPointTag *Tag = nullptr) const; |
355 | | |
356 | | /// Returns a new state with all argument regions invalidated. |
357 | | /// |
358 | | /// This accepts an alternate state in case some processing has already |
359 | | /// occurred. |
360 | | ProgramStateRef invalidateRegions(unsigned BlockCount, |
361 | | ProgramStateRef Orig = nullptr) const; |
362 | | |
363 | | using FrameBindingTy = std::pair<SVal, SVal>; |
364 | | using BindingsTy = SmallVectorImpl<FrameBindingTy>; |
365 | | |
366 | | /// Populates the given SmallVector with the bindings in the callee's stack |
367 | | /// frame at the start of this call. |
368 | | virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, |
369 | | BindingsTy &Bindings) const = 0; |
370 | | |
371 | | /// Returns a copy of this CallEvent, but using the given state. |
372 | | template <typename T> |
373 | | CallEventRef<T> cloneWithState(ProgramStateRef NewState) const; |
374 | | |
375 | | /// Returns a copy of this CallEvent, but using the given state. |
376 | 951k | CallEventRef<> cloneWithState(ProgramStateRef NewState) const { |
377 | 951k | return cloneWithState<CallEvent>(NewState); |
378 | 951k | } |
379 | | |
380 | | /// Returns true if this is a statement is a function or method call |
381 | | /// of some kind. |
382 | | static bool isCallStmt(const Stmt *S); |
383 | | |
384 | | /// Returns the result type of a function or method declaration. |
385 | | /// |
386 | | /// This will return a null QualType if the result type cannot be determined. |
387 | | static QualType getDeclaredResultType(const Decl *D); |
388 | | |
389 | | /// Returns true if the given decl is known to be variadic. |
390 | | /// |
391 | | /// \p D must not be null. |
392 | | static bool isVariadic(const Decl *D); |
393 | | |
394 | | /// Returns AnalysisDeclContext for the callee stack frame. |
395 | | /// Currently may fail; returns null on failure. |
396 | | AnalysisDeclContext *getCalleeAnalysisDeclContext() const; |
397 | | |
398 | | /// Returns the callee stack frame. That stack frame will only be entered |
399 | | /// during analysis if the call is inlined, but it may still be useful |
400 | | /// in intermediate calculations even if the call isn't inlined. |
401 | | /// May fail; returns null on failure. |
402 | | const StackFrameContext *getCalleeStackFrame(unsigned BlockCount) const; |
403 | | |
404 | | /// Returns memory location for a parameter variable within the callee stack |
405 | | /// frame. The behavior is undefined if the block count is different from the |
406 | | /// one that is there when call happens. May fail; returns null on failure. |
407 | | const ParamVarRegion *getParameterLocation(unsigned Index, |
408 | | unsigned BlockCount) const; |
409 | | |
410 | | /// Returns true if on the current path, the argument was constructed by |
411 | | /// calling a C++ constructor over it. This is an internal detail of the |
412 | | /// analysis which doesn't necessarily represent the program semantics: |
413 | | /// if we are supposed to construct an argument directly, we may still |
414 | | /// not do that because we don't know how (i.e., construction context is |
415 | | /// unavailable in the CFG or not supported by the analyzer). |
416 | 50.2k | bool isArgumentConstructedDirectly(unsigned Index) const { |
417 | | // This assumes that the object was not yet removed from the state. |
418 | 50.2k | return ExprEngine::getObjectUnderConstruction( |
419 | 50.2k | getState(), {getOriginExpr(), Index}, getLocationContext()).hasValue(); |
420 | 50.2k | } |
421 | | |
422 | | /// Some calls have parameter numbering mismatched from argument numbering. |
423 | | /// This function converts an argument index to the corresponding |
424 | | /// parameter index. Returns None is the argument doesn't correspond |
425 | | /// to any parameter variable. |
426 | | virtual Optional<unsigned> |
427 | 21.1k | getAdjustedParameterIndex(unsigned ASTArgumentIndex) const { |
428 | 21.1k | return ASTArgumentIndex; |
429 | 21.1k | } |
430 | | |
431 | | /// Some call event sub-classes conveniently adjust mismatching AST indices |
432 | | /// to match parameter indices. This function converts an argument index |
433 | | /// as understood by CallEvent to the argument index as understood by the AST. |
434 | 109k | virtual unsigned getASTArgumentIndex(unsigned CallArgumentIndex) const { |
435 | 109k | return CallArgumentIndex; |
436 | 109k | } |
437 | | |
438 | | /// Returns the construction context of the call, if it is a C++ constructor |
439 | | /// call or a call of a function returning a C++ class instance. Otherwise |
440 | | /// return nullptr. |
441 | | const ConstructionContext *getConstructionContext() const; |
442 | | |
443 | | /// If the call returns a C++ record type then the region of its return value |
444 | | /// can be retrieved from its construction context. |
445 | | Optional<SVal> getReturnValueUnderConstruction() const; |
446 | | |
447 | | // Iterator access to formal parameters and their types. |
448 | | private: |
449 | | struct GetTypeFn { |
450 | 73.1k | QualType operator()(ParmVarDecl *PD) const { return PD->getType(); } |
451 | | }; |
452 | | |
453 | | public: |
454 | | /// Return call's formal parameters. |
455 | | /// |
456 | | /// Remember that the number of formal parameters may not match the number |
457 | | /// of arguments for all calls. However, the first parameter will always |
458 | | /// correspond with the argument value returned by \c getArgSVal(0). |
459 | | virtual ArrayRef<ParmVarDecl *> parameters() const = 0; |
460 | | |
461 | | using param_type_iterator = |
462 | | llvm::mapped_iterator<ArrayRef<ParmVarDecl *>::iterator, GetTypeFn>; |
463 | | |
464 | | /// Returns an iterator over the types of the call's formal parameters. |
465 | | /// |
466 | | /// This uses the callee decl found by default name lookup rather than the |
467 | | /// definition because it represents a public interface, and probably has |
468 | | /// more annotations. |
469 | 93.9k | param_type_iterator param_type_begin() const { |
470 | 93.9k | return llvm::map_iterator(parameters().begin(), GetTypeFn()); |
471 | 93.9k | } |
472 | | /// \sa param_type_begin() |
473 | 93.9k | param_type_iterator param_type_end() const { |
474 | 93.9k | return llvm::map_iterator(parameters().end(), GetTypeFn()); |
475 | 93.9k | } |
476 | | |
477 | | // For debugging purposes only |
478 | | void dump(raw_ostream &Out) const; |
479 | | void dump() const; |
480 | | }; |
481 | | |
482 | | /// Represents a call to any sort of function that might have a |
483 | | /// FunctionDecl. |
484 | | class AnyFunctionCall : public CallEvent { |
485 | | protected: |
486 | | AnyFunctionCall(const Expr *E, ProgramStateRef St, |
487 | | const LocationContext *LCtx) |
488 | 187k | : CallEvent(E, St, LCtx) {} |
489 | | AnyFunctionCall(const Decl *D, ProgramStateRef St, |
490 | | const LocationContext *LCtx) |
491 | 2.97k | : CallEvent(D, St, LCtx) {} |
492 | 241k | AnyFunctionCall(const AnyFunctionCall &Other) = default; |
493 | | |
494 | | public: |
495 | | // This function is overridden by subclasses, but they must return |
496 | | // a FunctionDecl. |
497 | 42.4k | const FunctionDecl *getDecl() const override { |
498 | 42.4k | return cast<FunctionDecl>(CallEvent::getDecl()); |
499 | 42.4k | } |
500 | | |
501 | | RuntimeDefinition getRuntimeDefinition() const override; |
502 | | |
503 | | bool argumentsMayEscape() const override; |
504 | | |
505 | | void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, |
506 | | BindingsTy &Bindings) const override; |
507 | | |
508 | | ArrayRef<ParmVarDecl *> parameters() const override; |
509 | | |
510 | 236k | static bool classof(const CallEvent *CA) { |
511 | 236k | return CA->getKind() >= CE_BEG_FUNCTION_CALLS && |
512 | 236k | CA->getKind() <= CE_END_FUNCTION_CALLS; |
513 | 236k | } |
514 | | }; |
515 | | |
516 | | /// Represents a C function or static C++ member function call. |
517 | | /// |
518 | | /// Example: \c fun() |
519 | | class SimpleFunctionCall : public AnyFunctionCall { |
520 | | friend class CallEventManager; |
521 | | |
522 | | protected: |
523 | | SimpleFunctionCall(const CallExpr *CE, ProgramStateRef St, |
524 | | const LocationContext *LCtx) |
525 | 115k | : AnyFunctionCall(CE, St, LCtx) {} |
526 | 128k | SimpleFunctionCall(const SimpleFunctionCall &Other) = default; |
527 | | |
528 | 128k | void cloneTo(void *Dest) const override { |
529 | 128k | new (Dest) SimpleFunctionCall(*this); |
530 | 128k | } |
531 | | |
532 | | public: |
533 | 5.75M | const CallExpr *getOriginExpr() const override { |
534 | 5.75M | return cast<CallExpr>(AnyFunctionCall::getOriginExpr()); |
535 | 5.75M | } |
536 | | |
537 | | const FunctionDecl *getDecl() const override; |
538 | | |
539 | 399k | unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); } |
540 | | |
541 | 321k | const Expr *getArgExpr(unsigned Index) const override { |
542 | 321k | return getOriginExpr()->getArg(Index); |
543 | 321k | } |
544 | | |
545 | 2.55M | Kind getKind() const override { return CE_Function; } |
546 | 46 | StringRef getKindAsString() const override { return "SimpleFunctionCall"; } |
547 | | |
548 | 3.65k | static bool classof(const CallEvent *CA) { |
549 | 3.65k | return CA->getKind() == CE_Function; |
550 | 3.65k | } |
551 | | }; |
552 | | |
553 | | /// Represents a call to a block. |
554 | | /// |
555 | | /// Example: <tt>^{ statement-body }()</tt> |
556 | | class BlockCall : public CallEvent { |
557 | | friend class CallEventManager; |
558 | | |
559 | | protected: |
560 | | BlockCall(const CallExpr *CE, ProgramStateRef St, |
561 | | const LocationContext *LCtx) |
562 | 585 | : CallEvent(CE, St, LCtx) {} |
563 | 231 | BlockCall(const BlockCall &Other) = default; |
564 | | |
565 | 231 | void cloneTo(void *Dest) const override { new (Dest) BlockCall(*this); } |
566 | | |
567 | | void getExtraInvalidatedValues(ValueList &Values, |
568 | | RegionAndSymbolInvalidationTraits *ETraits) const override; |
569 | | |
570 | | public: |
571 | 7.44k | const CallExpr *getOriginExpr() const override { |
572 | 7.44k | return cast<CallExpr>(CallEvent::getOriginExpr()); |
573 | 7.44k | } |
574 | | |
575 | 1.20k | unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); } |
576 | | |
577 | 339 | const Expr *getArgExpr(unsigned Index) const override { |
578 | 339 | return getOriginExpr()->getArg(Index); |
579 | 339 | } |
580 | | |
581 | | /// Returns the region associated with this instance of the block. |
582 | | /// |
583 | | /// This may be NULL if the block's origin is unknown. |
584 | | const BlockDataRegion *getBlockRegion() const; |
585 | | |
586 | 2.96k | const BlockDecl *getDecl() const override { |
587 | 2.96k | const BlockDataRegion *BR = getBlockRegion(); |
588 | 2.96k | if (!BR) |
589 | 124 | return nullptr; |
590 | 2.83k | return BR->getDecl(); |
591 | 2.83k | } |
592 | | |
593 | 566 | bool isConversionFromLambda() const { |
594 | 566 | const BlockDecl *BD = getDecl(); |
595 | 566 | if (!BD) |
596 | 10 | return false; |
597 | | |
598 | 556 | return BD->isConversionFromLambda(); |
599 | 556 | } |
600 | | |
601 | | /// For a block converted from a C++ lambda, returns the block |
602 | | /// VarRegion for the variable holding the captured C++ lambda record. |
603 | 14 | const VarRegion *getRegionStoringCapturedLambda() const { |
604 | 14 | assert(isConversionFromLambda()); |
605 | 14 | const BlockDataRegion *BR = getBlockRegion(); |
606 | 14 | assert(BR && "Block converted from lambda must have a block region"); |
607 | | |
608 | 14 | auto I = BR->referenced_vars_begin(); |
609 | 14 | assert(I != BR->referenced_vars_end()); |
610 | | |
611 | 14 | return I.getCapturedRegion(); |
612 | 14 | } |
613 | | |
614 | 198 | RuntimeDefinition getRuntimeDefinition() const override { |
615 | 198 | if (!isConversionFromLambda()) |
616 | 191 | return RuntimeDefinition(getDecl()); |
617 | | |
618 | | // Clang converts lambdas to blocks with an implicit user-defined |
619 | | // conversion operator method on the lambda record that looks (roughly) |
620 | | // like: |
621 | | // |
622 | | // typedef R(^block_type)(P1, P2, ...); |
623 | | // operator block_type() const { |
624 | | // auto Lambda = *this; |
625 | | // return ^(P1 p1, P2 p2, ...){ |
626 | | // /* return Lambda(p1, p2, ...); */ |
627 | | // }; |
628 | | // } |
629 | | // |
630 | | // Here R is the return type of the lambda and P1, P2, ... are |
631 | | // its parameter types. 'Lambda' is a fake VarDecl captured by the block |
632 | | // that is initialized to a copy of the lambda. |
633 | | // |
634 | | // Sema leaves the body of a lambda-converted block empty (it is |
635 | | // produced by CodeGen), so we can't analyze it directly. Instead, we skip |
636 | | // the block body and analyze the operator() method on the captured lambda. |
637 | 7 | const VarDecl *LambdaVD = getRegionStoringCapturedLambda()->getDecl(); |
638 | 7 | const CXXRecordDecl *LambdaDecl = LambdaVD->getType()->getAsCXXRecordDecl(); |
639 | 7 | CXXMethodDecl* LambdaCallOperator = LambdaDecl->getLambdaCallOperator(); |
640 | | |
641 | 7 | return RuntimeDefinition(LambdaCallOperator); |
642 | 7 | } |
643 | | |
644 | 18 | bool argumentsMayEscape() const override { |
645 | 18 | return true; |
646 | 18 | } |
647 | | |
648 | | void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, |
649 | | BindingsTy &Bindings) const override; |
650 | | |
651 | | ArrayRef<ParmVarDecl *> parameters() const override; |
652 | | |
653 | 3.55k | Kind getKind() const override { return CE_Block; } |
654 | 0 | StringRef getKindAsString() const override { return "BlockCall"; } |
655 | | |
656 | 349 | static bool classof(const CallEvent *CA) { return CA->getKind() == CE_Block; } |
657 | | }; |
658 | | |
659 | | /// Represents a non-static C++ member function call, no matter how |
660 | | /// it is written. |
661 | | class CXXInstanceCall : public AnyFunctionCall { |
662 | | protected: |
663 | | CXXInstanceCall(const CallExpr *CE, ProgramStateRef St, |
664 | | const LocationContext *LCtx) |
665 | 27.3k | : AnyFunctionCall(CE, St, LCtx) {} |
666 | | CXXInstanceCall(const FunctionDecl *D, ProgramStateRef St, |
667 | | const LocationContext *LCtx) |
668 | 2.97k | : AnyFunctionCall(D, St, LCtx) {} |
669 | 38.6k | CXXInstanceCall(const CXXInstanceCall &Other) = default; |
670 | | |
671 | | void getExtraInvalidatedValues(ValueList &Values, |
672 | | RegionAndSymbolInvalidationTraits *ETraits) const override; |
673 | | |
674 | | public: |
675 | | /// Returns the expression representing the implicit 'this' object. |
676 | 48 | virtual const Expr *getCXXThisExpr() const { return nullptr; } |
677 | | |
678 | | /// Returns the value of the implicit 'this' object. |
679 | | virtual SVal getCXXThisVal() const; |
680 | | |
681 | | const FunctionDecl *getDecl() const override; |
682 | | |
683 | | RuntimeDefinition getRuntimeDefinition() const override; |
684 | | |
685 | | void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, |
686 | | BindingsTy &Bindings) const override; |
687 | | |
688 | 364k | static bool classof(const CallEvent *CA) { |
689 | 364k | return CA->getKind() >= CE_BEG_CXX_INSTANCE_CALLS && |
690 | 188k | CA->getKind() <= CE_END_CXX_INSTANCE_CALLS; |
691 | 364k | } |
692 | | }; |
693 | | |
694 | | /// Represents a non-static C++ member function call. |
695 | | /// |
696 | | /// Example: \c obj.fun() |
697 | | class CXXMemberCall : public CXXInstanceCall { |
698 | | friend class CallEventManager; |
699 | | |
700 | | protected: |
701 | | CXXMemberCall(const CXXMemberCallExpr *CE, ProgramStateRef St, |
702 | | const LocationContext *LCtx) |
703 | 19.1k | : CXXInstanceCall(CE, St, LCtx) {} |
704 | 26.5k | CXXMemberCall(const CXXMemberCall &Other) = default; |
705 | | |
706 | 26.5k | void cloneTo(void *Dest) const override { new (Dest) CXXMemberCall(*this); } |
707 | | |
708 | | public: |
709 | 1.05M | const CXXMemberCallExpr *getOriginExpr() const override { |
710 | 1.05M | return cast<CXXMemberCallExpr>(CXXInstanceCall::getOriginExpr()); |
711 | 1.05M | } |
712 | | |
713 | 64.8k | unsigned getNumArgs() const override { |
714 | 64.8k | if (const CallExpr *CE = getOriginExpr()) |
715 | 64.8k | return CE->getNumArgs(); |
716 | 0 | return 0; |
717 | 0 | } |
718 | | |
719 | 22.7k | const Expr *getArgExpr(unsigned Index) const override { |
720 | 22.7k | return getOriginExpr()->getArg(Index); |
721 | 22.7k | } |
722 | | |
723 | | const Expr *getCXXThisExpr() const override; |
724 | | |
725 | | RuntimeDefinition getRuntimeDefinition() const override; |
726 | | |
727 | 589k | Kind getKind() const override { return CE_CXXMember; } |
728 | 0 | StringRef getKindAsString() const override { return "CXXMemberCall"; } |
729 | | |
730 | 36.7k | static bool classof(const CallEvent *CA) { |
731 | 36.7k | return CA->getKind() == CE_CXXMember; |
732 | 36.7k | } |
733 | | }; |
734 | | |
735 | | /// Represents a C++ overloaded operator call where the operator is |
736 | | /// implemented as a non-static member function. |
737 | | /// |
738 | | /// Example: <tt>iter + 1</tt> |
739 | | class CXXMemberOperatorCall : public CXXInstanceCall { |
740 | | friend class CallEventManager; |
741 | | |
742 | | protected: |
743 | | CXXMemberOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St, |
744 | | const LocationContext *LCtx) |
745 | 8.22k | : CXXInstanceCall(CE, St, LCtx) {} |
746 | 9.02k | CXXMemberOperatorCall(const CXXMemberOperatorCall &Other) = default; |
747 | | |
748 | 9.02k | void cloneTo(void *Dest) const override { |
749 | 9.02k | new (Dest) CXXMemberOperatorCall(*this); |
750 | 9.02k | } |
751 | | |
752 | | public: |
753 | 250k | const CXXOperatorCallExpr *getOriginExpr() const override { |
754 | 250k | return cast<CXXOperatorCallExpr>(CXXInstanceCall::getOriginExpr()); |
755 | 250k | } |
756 | | |
757 | 22.4k | unsigned getNumArgs() const override { |
758 | 22.4k | return getOriginExpr()->getNumArgs() - 1; |
759 | 22.4k | } |
760 | | |
761 | 19.8k | const Expr *getArgExpr(unsigned Index) const override { |
762 | 19.8k | return getOriginExpr()->getArg(Index + 1); |
763 | 19.8k | } |
764 | | |
765 | | const Expr *getCXXThisExpr() const override; |
766 | | |
767 | 179k | Kind getKind() const override { return CE_CXXMemberOperator; } |
768 | 0 | StringRef getKindAsString() const override { return "CXXMemberOperatorCall"; } |
769 | | |
770 | 4.26k | static bool classof(const CallEvent *CA) { |
771 | 4.26k | return CA->getKind() == CE_CXXMemberOperator; |
772 | 4.26k | } |
773 | | |
774 | | Optional<unsigned> |
775 | 41 | getAdjustedParameterIndex(unsigned ASTArgumentIndex) const override { |
776 | | // For member operator calls argument 0 on the expression corresponds |
777 | | // to implicit this-parameter on the declaration. |
778 | 41 | return (ASTArgumentIndex > 0) ? Optional<unsigned>(ASTArgumentIndex - 1) |
779 | 0 | : None; |
780 | 41 | } |
781 | | |
782 | 4.13k | unsigned getASTArgumentIndex(unsigned CallArgumentIndex) const override { |
783 | | // For member operator calls argument 0 on the expression corresponds |
784 | | // to implicit this-parameter on the declaration. |
785 | 4.13k | return CallArgumentIndex + 1; |
786 | 4.13k | } |
787 | | |
788 | 148 | OverloadedOperatorKind getOverloadedOperator() const { |
789 | 148 | return getOriginExpr()->getOperator(); |
790 | 148 | } |
791 | | }; |
792 | | |
793 | | /// Represents an implicit call to a C++ destructor. |
794 | | /// |
795 | | /// This can occur at the end of a scope (for automatic objects), at the end |
796 | | /// of a full-expression (for temporaries), or as part of a delete. |
797 | | class CXXDestructorCall : public CXXInstanceCall { |
798 | | friend class CallEventManager; |
799 | | |
800 | | protected: |
801 | | using DtorDataTy = llvm::PointerIntPair<const MemRegion *, 1, bool>; |
802 | | |
803 | | /// Creates an implicit destructor. |
804 | | /// |
805 | | /// \param DD The destructor that will be called. |
806 | | /// \param Trigger The statement whose completion causes this destructor call. |
807 | | /// \param Target The object region to be destructed. |
808 | | /// \param St The path-sensitive state at this point in the program. |
809 | | /// \param LCtx The location context at this point in the program. |
810 | | CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, |
811 | | const MemRegion *Target, bool IsBaseDestructor, |
812 | | ProgramStateRef St, const LocationContext *LCtx) |
813 | 2.97k | : CXXInstanceCall(DD, St, LCtx) { |
814 | 2.97k | Data = DtorDataTy(Target, IsBaseDestructor).getOpaqueValue(); |
815 | 2.97k | Location = Trigger->getEndLoc(); |
816 | 2.97k | } |
817 | | |
818 | 3.10k | CXXDestructorCall(const CXXDestructorCall &Other) = default; |
819 | | |
820 | 3.10k | void cloneTo(void *Dest) const override {new (Dest) CXXDestructorCall(*this);} |
821 | | |
822 | | public: |
823 | 14.3k | SourceRange getSourceRange() const override { return Location; } |
824 | 8.90k | unsigned getNumArgs() const override { return 0; } |
825 | | |
826 | | RuntimeDefinition getRuntimeDefinition() const override; |
827 | | |
828 | | /// Returns the value of the implicit 'this' object. |
829 | | SVal getCXXThisVal() const override; |
830 | | |
831 | | /// Returns true if this is a call to a base class destructor. |
832 | 2.94k | bool isBaseDestructor() const { |
833 | 2.94k | return DtorDataTy::getFromOpaqueValue(Data).getInt(); |
834 | 2.94k | } |
835 | | |
836 | 43.2k | Kind getKind() const override { return CE_CXXDestructor; } |
837 | 0 | StringRef getKindAsString() const override { return "CXXDestructorCall"; } |
838 | | |
839 | 124k | static bool classof(const CallEvent *CA) { |
840 | 124k | return CA->getKind() == CE_CXXDestructor; |
841 | 124k | } |
842 | | }; |
843 | | |
844 | | /// Represents any constructor invocation. This includes regular constructors |
845 | | /// and inherited constructors. |
846 | | class AnyCXXConstructorCall : public AnyFunctionCall { |
847 | | protected: |
848 | | AnyCXXConstructorCall(const Expr *E, const MemRegion *Target, |
849 | | ProgramStateRef St, const LocationContext *LCtx) |
850 | 41.0k | : AnyFunctionCall(E, St, LCtx) { |
851 | 41.0k | assert(E && (isa<CXXConstructExpr>(E) || isa<CXXInheritedCtorInitExpr>(E))); |
852 | | // Target may be null when the region is unknown. |
853 | 41.0k | Data = Target; |
854 | 41.0k | } |
855 | | |
856 | | void getExtraInvalidatedValues(ValueList &Values, |
857 | | RegionAndSymbolInvalidationTraits *ETraits) const override; |
858 | | |
859 | | void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, |
860 | | BindingsTy &Bindings) const override; |
861 | | |
862 | | public: |
863 | | /// Returns the value of the implicit 'this' object. |
864 | | SVal getCXXThisVal() const; |
865 | | |
866 | 0 | static bool classof(const CallEvent *Call) { |
867 | 0 | return Call->getKind() >= CE_BEG_CXX_CONSTRUCTOR_CALLS && |
868 | 0 | Call->getKind() <= CE_END_CXX_CONSTRUCTOR_CALLS; |
869 | 0 | } |
870 | | }; |
871 | | |
872 | | /// Represents a call to a C++ constructor. |
873 | | /// |
874 | | /// Example: \c T(1) |
875 | | class CXXConstructorCall : public AnyCXXConstructorCall { |
876 | | friend class CallEventManager; |
877 | | |
878 | | protected: |
879 | | /// Creates a constructor call. |
880 | | /// |
881 | | /// \param CE The constructor expression as written in the source. |
882 | | /// \param Target The region where the object should be constructed. If NULL, |
883 | | /// a new symbolic region will be used. |
884 | | /// \param St The path-sensitive state at this point in the program. |
885 | | /// \param LCtx The location context at this point in the program. |
886 | | CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *Target, |
887 | | ProgramStateRef St, const LocationContext *LCtx) |
888 | 41.0k | : AnyCXXConstructorCall(CE, Target, St, LCtx) {} |
889 | | |
890 | 70.3k | CXXConstructorCall(const CXXConstructorCall &Other) = default; |
891 | | |
892 | 70.3k | void cloneTo(void *Dest) const override { new (Dest) CXXConstructorCall(*this); } |
893 | | |
894 | | public: |
895 | 1.35M | const CXXConstructExpr *getOriginExpr() const override { |
896 | 1.35M | return cast<CXXConstructExpr>(AnyFunctionCall::getOriginExpr()); |
897 | 1.35M | } |
898 | | |
899 | 599k | const CXXConstructorDecl *getDecl() const override { |
900 | 599k | return getOriginExpr()->getConstructor(); |
901 | 599k | } |
902 | | |
903 | 142k | unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); } |
904 | | |
905 | 138k | const Expr *getArgExpr(unsigned Index) const override { |
906 | 138k | return getOriginExpr()->getArg(Index); |
907 | 138k | } |
908 | | |
909 | 942k | Kind getKind() const override { return CE_CXXConstructor; } |
910 | 13 | StringRef getKindAsString() const override { return "CXXConstructorCall"; } |
911 | | |
912 | 393k | static bool classof(const CallEvent *CA) { |
913 | 393k | return CA->getKind() == CE_CXXConstructor; |
914 | 393k | } |
915 | | }; |
916 | | |
917 | | /// Represents a call to a C++ inherited constructor. |
918 | | /// |
919 | | /// Example: \c class T : public S { using S::S; }; T(1); |
920 | | /// |
921 | | // Note, it is difficult to model the parameters. This is one of the reasons |
922 | | // why we skip analysis of inheriting constructors as top-level functions. |
923 | | // CXXInheritedCtorInitExpr doesn't take arguments and doesn't model parameter |
924 | | // initialization because there is none: the arguments in the outer |
925 | | // CXXConstructExpr directly initialize the parameters of the base class |
926 | | // constructor, and no copies are made. (Making a copy of the parameter is |
927 | | // incorrect, at least if it's done in an observable way.) The derived class |
928 | | // constructor doesn't even exist in the formal model. |
929 | | /// E.g., in: |
930 | | /// |
931 | | /// struct X { X *p = this; ~X() {} }; |
932 | | /// struct A { A(X x) : b(x.p == &x) {} bool b; }; |
933 | | /// struct B : A { using A::A; }; |
934 | | /// B b = X{}; |
935 | | /// |
936 | | /// ... b.b is initialized to true. |
937 | | class CXXInheritedConstructorCall : public AnyCXXConstructorCall { |
938 | | friend class CallEventManager; |
939 | | |
940 | | protected: |
941 | | CXXInheritedConstructorCall(const CXXInheritedCtorInitExpr *CE, |
942 | | const MemRegion *Target, ProgramStateRef St, |
943 | | const LocationContext *LCtx) |
944 | 13 | : AnyCXXConstructorCall(CE, Target, St, LCtx) {} |
945 | | |
946 | | CXXInheritedConstructorCall(const CXXInheritedConstructorCall &Other) = |
947 | 9 | default; |
948 | | |
949 | 9 | void cloneTo(void *Dest) const override { |
950 | 9 | new (Dest) CXXInheritedConstructorCall(*this); |
951 | 9 | } |
952 | | |
953 | | public: |
954 | 174 | const CXXInheritedCtorInitExpr *getOriginExpr() const override { |
955 | 174 | return cast<CXXInheritedCtorInitExpr>(AnyFunctionCall::getOriginExpr()); |
956 | 174 | } |
957 | | |
958 | 73 | const CXXConstructorDecl *getDecl() const override { |
959 | 73 | return getOriginExpr()->getConstructor(); |
960 | 73 | } |
961 | | |
962 | | /// Obtain the stack frame of the inheriting constructor. Argument expressions |
963 | | /// can be found on the call site of that stack frame. |
964 | | const StackFrameContext *getInheritingStackFrame() const; |
965 | | |
966 | | /// Obtain the CXXConstructExpr for the sub-class that inherited the current |
967 | | /// constructor (possibly indirectly). It's the statement that contains |
968 | | /// argument expressions. |
969 | 66 | const CXXConstructExpr *getInheritingConstructor() const { |
970 | 66 | return cast<CXXConstructExpr>(getInheritingStackFrame()->getCallSite()); |
971 | 66 | } |
972 | | |
973 | 36 | unsigned getNumArgs() const override { |
974 | 36 | return getInheritingConstructor()->getNumArgs(); |
975 | 36 | } |
976 | | |
977 | 30 | const Expr *getArgExpr(unsigned Index) const override { |
978 | 30 | return getInheritingConstructor()->getArg(Index); |
979 | 30 | } |
980 | | |
981 | 18 | SVal getArgSVal(unsigned Index) const override { |
982 | 18 | return getState()->getSVal( |
983 | 18 | getArgExpr(Index), |
984 | 18 | getInheritingStackFrame()->getParent()->getStackFrame()); |
985 | 18 | } |
986 | | |
987 | 93 | Kind getKind() const override { return CE_CXXInheritedConstructor; } |
988 | 0 | StringRef getKindAsString() const override { |
989 | 0 | return "CXXInheritedConstructorCall"; |
990 | 0 | } |
991 | | |
992 | 0 | static bool classof(const CallEvent *CA) { |
993 | 0 | return CA->getKind() == CE_CXXInheritedConstructor; |
994 | 0 | } |
995 | | }; |
996 | | |
997 | | /// Represents the memory allocation call in a C++ new-expression. |
998 | | /// |
999 | | /// This is a call to "operator new". |
1000 | | class CXXAllocatorCall : public AnyFunctionCall { |
1001 | | friend class CallEventManager; |
1002 | | |
1003 | | protected: |
1004 | | CXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef St, |
1005 | | const LocationContext *LCtx) |
1006 | 2.83k | : AnyFunctionCall(E, St, LCtx) {} |
1007 | 2.80k | CXXAllocatorCall(const CXXAllocatorCall &Other) = default; |
1008 | | |
1009 | 2.80k | void cloneTo(void *Dest) const override { new (Dest) CXXAllocatorCall(*this); } |
1010 | | |
1011 | | public: |
1012 | 81.1k | const CXXNewExpr *getOriginExpr() const override { |
1013 | 81.1k | return cast<CXXNewExpr>(AnyFunctionCall::getOriginExpr()); |
1014 | 81.1k | } |
1015 | | |
1016 | 37.1k | const FunctionDecl *getDecl() const override { |
1017 | 37.1k | return getOriginExpr()->getOperatorNew(); |
1018 | 37.1k | } |
1019 | | |
1020 | 429 | SVal getObjectUnderConstruction() const { |
1021 | 429 | return ExprEngine::getObjectUnderConstruction(getState(), getOriginExpr(), |
1022 | 429 | getLocationContext()) |
1023 | 429 | .getValue(); |
1024 | 429 | } |
1025 | | |
1026 | | /// Number of non-placement arguments to the call. It is equal to 2 for |
1027 | | /// C++17 aligned operator new() calls that have alignment implicitly |
1028 | | /// passed as the second argument, and to 1 for other operator new() calls. |
1029 | 16.9k | unsigned getNumImplicitArgs() const { |
1030 | 16.9k | return getOriginExpr()->passAlignment() ? 219 : 1; |
1031 | 16.9k | } |
1032 | | |
1033 | 7.03k | unsigned getNumArgs() const override { |
1034 | 7.03k | return getOriginExpr()->getNumPlacementArgs() + getNumImplicitArgs(); |
1035 | 7.03k | } |
1036 | | |
1037 | 7.97k | const Expr *getArgExpr(unsigned Index) const override { |
1038 | | // The first argument of an allocator call is the size of the allocation. |
1039 | 7.97k | if (Index < getNumImplicitArgs()) |
1040 | 6.06k | return nullptr; |
1041 | 1.91k | return getOriginExpr()->getPlacementArg(Index - getNumImplicitArgs()); |
1042 | 1.91k | } |
1043 | | |
1044 | | /// Number of placement arguments to the operator new() call. For example, |
1045 | | /// standard std::nothrow operator new and standard placement new both have |
1046 | | /// 1 implicit argument (size) and 1 placement argument, while regular |
1047 | | /// operator new() has 1 implicit argument and 0 placement arguments. |
1048 | 0 | const Expr *getPlacementArgExpr(unsigned Index) const { |
1049 | 0 | return getOriginExpr()->getPlacementArg(Index); |
1050 | 0 | } |
1051 | | |
1052 | 42.2k | Kind getKind() const override { return CE_CXXAllocator; } |
1053 | 16 | StringRef getKindAsString() const override { return "CXXAllocatorCall"; } |
1054 | | |
1055 | 920 | static bool classof(const CallEvent *CE) { |
1056 | 920 | return CE->getKind() == CE_CXXAllocator; |
1057 | 920 | } |
1058 | | }; |
1059 | | |
1060 | | /// Represents the memory deallocation call in a C++ delete-expression. |
1061 | | /// |
1062 | | /// This is a call to "operator delete". |
1063 | | // FIXME: CXXDeleteExpr isn't present for custom delete operators, or even for |
1064 | | // some those that are in the standard library, like the no-throw or align_val |
1065 | | // versions. |
1066 | | // Some pointers: |
1067 | | // http://lists.llvm.org/pipermail/cfe-dev/2020-April/065080.html |
1068 | | // clang/test/Analysis/cxx-dynamic-memory-analysis-order.cpp |
1069 | | // clang/unittests/StaticAnalyzer/CallEventTest.cpp |
1070 | | class CXXDeallocatorCall : public AnyFunctionCall { |
1071 | | friend class CallEventManager; |
1072 | | |
1073 | | protected: |
1074 | | CXXDeallocatorCall(const CXXDeleteExpr *E, ProgramStateRef St, |
1075 | | const LocationContext *LCtx) |
1076 | 436 | : AnyFunctionCall(E, St, LCtx) {} |
1077 | 805 | CXXDeallocatorCall(const CXXDeallocatorCall &Other) = default; |
1078 | | |
1079 | 805 | void cloneTo(void *Dest) const override { |
1080 | 805 | new (Dest) CXXDeallocatorCall(*this); |
1081 | 805 | } |
1082 | | |
1083 | | public: |
1084 | 20.6k | const CXXDeleteExpr *getOriginExpr() const override { |
1085 | 20.6k | return cast<CXXDeleteExpr>(AnyFunctionCall::getOriginExpr()); |
1086 | 20.6k | } |
1087 | | |
1088 | 14.3k | const FunctionDecl *getDecl() const override { |
1089 | 14.3k | return getOriginExpr()->getOperatorDelete(); |
1090 | 14.3k | } |
1091 | | |
1092 | 1.51k | unsigned getNumArgs() const override { return getDecl()->getNumParams(); } |
1093 | | |
1094 | 1.14k | const Expr *getArgExpr(unsigned Index) const override { |
1095 | | // CXXDeleteExpr's only have a single argument. |
1096 | 1.14k | return getOriginExpr()->getArgument(); |
1097 | 1.14k | } |
1098 | | |
1099 | 14.5k | Kind getKind() const override { return CE_CXXDeallocator; } |
1100 | 4 | StringRef getKindAsString() const override { return "CXXDeallocatorCall"; } |
1101 | | |
1102 | 136k | static bool classof(const CallEvent *CE) { |
1103 | 136k | return CE->getKind() == CE_CXXDeallocator; |
1104 | 136k | } |
1105 | | }; |
1106 | | |
1107 | | /// Represents the ways an Objective-C message send can occur. |
1108 | | // |
1109 | | // Note to maintainers: OCM_Message should always be last, since it does not |
1110 | | // need to fit in the Data field's low bits. |
1111 | | enum ObjCMessageKind { |
1112 | | OCM_PropertyAccess, |
1113 | | OCM_Subscript, |
1114 | | OCM_Message |
1115 | | }; |
1116 | | |
1117 | | /// Represents any expression that calls an Objective-C method. |
1118 | | /// |
1119 | | /// This includes all of the kinds listed in ObjCMessageKind. |
1120 | | class ObjCMethodCall : public CallEvent { |
1121 | | friend class CallEventManager; |
1122 | | |
1123 | | const PseudoObjectExpr *getContainingPseudoObjectExpr() const; |
1124 | | |
1125 | | protected: |
1126 | | ObjCMethodCall(const ObjCMessageExpr *Msg, ProgramStateRef St, |
1127 | | const LocationContext *LCtx) |
1128 | 6.18k | : CallEvent(Msg, St, LCtx) { |
1129 | 6.18k | Data = nullptr; |
1130 | 6.18k | } |
1131 | | |
1132 | 31.1k | ObjCMethodCall(const ObjCMethodCall &Other) = default; |
1133 | | |
1134 | 31.1k | void cloneTo(void *Dest) const override { new (Dest) ObjCMethodCall(*this); } |
1135 | | |
1136 | | void getExtraInvalidatedValues(ValueList &Values, |
1137 | | RegionAndSymbolInvalidationTraits *ETraits) const override; |
1138 | | |
1139 | | /// Check if the selector may have multiple definitions (may have overrides). |
1140 | | virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl, |
1141 | | Selector Sel) const; |
1142 | | |
1143 | | public: |
1144 | 312k | const ObjCMessageExpr *getOriginExpr() const override { |
1145 | 312k | return cast<ObjCMessageExpr>(CallEvent::getOriginExpr()); |
1146 | 312k | } |
1147 | | |
1148 | 81.6k | const ObjCMethodDecl *getDecl() const override { |
1149 | 81.6k | return getOriginExpr()->getMethodDecl(); |
1150 | 81.6k | } |
1151 | | |
1152 | 33.0k | unsigned getNumArgs() const override { |
1153 | 33.0k | return getOriginExpr()->getNumArgs(); |
1154 | 33.0k | } |
1155 | | |
1156 | 7.44k | const Expr *getArgExpr(unsigned Index) const override { |
1157 | 7.44k | return getOriginExpr()->getArg(Index); |
1158 | 7.44k | } |
1159 | | |
1160 | 44.3k | bool isInstanceMessage() const { |
1161 | 44.3k | return getOriginExpr()->isInstanceMessage(); |
1162 | 44.3k | } |
1163 | | |
1164 | 7.47k | ObjCMethodFamily getMethodFamily() const { |
1165 | 7.47k | return getOriginExpr()->getMethodFamily(); |
1166 | 7.47k | } |
1167 | | |
1168 | 2.13k | Selector getSelector() const { |
1169 | 2.13k | return getOriginExpr()->getSelector(); |
1170 | 2.13k | } |
1171 | | |
1172 | | SourceRange getSourceRange() const override; |
1173 | | |
1174 | | /// Returns the value of the receiver at the time of this call. |
1175 | | SVal getReceiverSVal() const; |
1176 | | |
1177 | | /// Get the interface for the receiver. |
1178 | | /// |
1179 | | /// This works whether this is an instance message or a class message. |
1180 | | /// However, it currently just uses the static type of the receiver. |
1181 | 3.86k | const ObjCInterfaceDecl *getReceiverInterface() const { |
1182 | 3.86k | return getOriginExpr()->getReceiverInterface(); |
1183 | 3.86k | } |
1184 | | |
1185 | | /// Checks if the receiver refers to 'self' or 'super'. |
1186 | | bool isReceiverSelfOrSuper() const; |
1187 | | |
1188 | | /// Returns how the message was written in the source (property access, |
1189 | | /// subscript, or explicit message send). |
1190 | | ObjCMessageKind getMessageKind() const; |
1191 | | |
1192 | | /// Returns true if this property access or subscript is a setter (has the |
1193 | | /// form of an assignment). |
1194 | 7 | bool isSetter() const { |
1195 | 7 | switch (getMessageKind()) { |
1196 | 0 | case OCM_Message: |
1197 | 0 | llvm_unreachable("This is not a pseudo-object access!"); |
1198 | 1 | case OCM_PropertyAccess: |
1199 | 1 | return getNumArgs() > 0; |
1200 | 6 | case OCM_Subscript: |
1201 | 6 | return getNumArgs() > 1; |
1202 | 0 | } |
1203 | 0 | llvm_unreachable("Unknown message kind"); |
1204 | 0 | } |
1205 | | |
1206 | | // Returns the property accessed by this method, either explicitly via |
1207 | | // property syntax or implicitly via a getter or setter method. Returns |
1208 | | // nullptr if the call is not a prooperty access. |
1209 | | const ObjCPropertyDecl *getAccessedProperty() const; |
1210 | | |
1211 | | RuntimeDefinition getRuntimeDefinition() const override; |
1212 | | |
1213 | | bool argumentsMayEscape() const override; |
1214 | | |
1215 | | void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, |
1216 | | BindingsTy &Bindings) const override; |
1217 | | |
1218 | | ArrayRef<ParmVarDecl*> parameters() const override; |
1219 | | |
1220 | 156k | Kind getKind() const override { return CE_ObjCMessage; } |
1221 | 0 | StringRef getKindAsString() const override { return "ObjCMethodCall"; } |
1222 | | |
1223 | 337k | static bool classof(const CallEvent *CA) { |
1224 | 337k | return CA->getKind() == CE_ObjCMessage; |
1225 | 337k | } |
1226 | | }; |
1227 | | |
1228 | | enum CallDescriptionFlags : int { |
1229 | | /// Describes a C standard function that is sometimes implemented as a macro |
1230 | | /// that expands to a compiler builtin with some __builtin prefix. |
1231 | | /// The builtin may as well have a few extra arguments on top of the requested |
1232 | | /// number of arguments. |
1233 | | CDF_MaybeBuiltin = 1 << 0, |
1234 | | }; |
1235 | | |
1236 | | /// This class represents a description of a function call using the number of |
1237 | | /// arguments and the name of the function. |
1238 | | class CallDescription { |
1239 | | friend CallEvent; |
1240 | | |
1241 | | mutable IdentifierInfo *II = nullptr; |
1242 | | mutable bool IsLookupDone = false; |
1243 | | // The list of the qualified names used to identify the specified CallEvent, |
1244 | | // e.g. "{a, b}" represent the qualified names, like "a::b". |
1245 | | std::vector<const char *> QualifiedName; |
1246 | | Optional<unsigned> RequiredArgs; |
1247 | | Optional<size_t> RequiredParams; |
1248 | | int Flags; |
1249 | | |
1250 | | // A constructor helper. |
1251 | | static Optional<size_t> readRequiredParams(Optional<unsigned> RequiredArgs, |
1252 | 821k | Optional<size_t> RequiredParams) { |
1253 | 821k | if (RequiredParams) |
1254 | 50.1k | return RequiredParams; |
1255 | 771k | if (RequiredArgs) |
1256 | 770k | return static_cast<size_t>(*RequiredArgs); |
1257 | 1.59k | return None; |
1258 | 1.59k | } |
1259 | | |
1260 | | public: |
1261 | | /// Constructs a CallDescription object. |
1262 | | /// |
1263 | | /// @param QualifiedName The list of the name qualifiers of the function that |
1264 | | /// will be matched. The user is allowed to skip any of the qualifiers. |
1265 | | /// For example, {"std", "basic_string", "c_str"} would match both |
1266 | | /// std::basic_string<...>::c_str() and std::__1::basic_string<...>::c_str(). |
1267 | | /// |
1268 | | /// @param RequiredArgs The number of arguments that is expected to match a |
1269 | | /// call. Omit this parameter to match every occurrence of call with a given |
1270 | | /// name regardless the number of arguments. |
1271 | | CallDescription(int Flags, ArrayRef<const char *> QualifiedName, |
1272 | | Optional<unsigned> RequiredArgs = None, |
1273 | | Optional<size_t> RequiredParams = None) |
1274 | | : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs), |
1275 | | RequiredParams(readRequiredParams(RequiredArgs, RequiredParams)), |
1276 | 821k | Flags(Flags) {} |
1277 | | |
1278 | | /// Construct a CallDescription with default flags. |
1279 | | CallDescription(ArrayRef<const char *> QualifiedName, |
1280 | | Optional<unsigned> RequiredArgs = None, |
1281 | | Optional<size_t> RequiredParams = None) |
1282 | 815k | : CallDescription(0, QualifiedName, RequiredArgs, RequiredParams) {} clang::ento::CallDescription::CallDescription(llvm::ArrayRef<char const*>, llvm::Optional<unsigned int>, llvm::Optional<unsigned long>) Line | Count | Source | 1282 | 815k | : CallDescription(0, QualifiedName, RequiredArgs, RequiredParams) {} |
Unexecuted instantiation: clang::ento::CallDescription::CallDescription(llvm::ArrayRef<char const*>, llvm::Optional<unsigned int>, llvm::Optional<unsigned long>) |
1283 | | |
1284 | | /// Get the name of the function that this object matches. |
1285 | 523k | StringRef getFunctionName() const { return QualifiedName.back(); } |
1286 | | }; |
1287 | | |
1288 | | /// An immutable map from CallDescriptions to arbitrary data. Provides a unified |
1289 | | /// way for checkers to react on function calls. |
1290 | | template <typename T> class CallDescriptionMap { |
1291 | | // Some call descriptions aren't easily hashable (eg., the ones with qualified |
1292 | | // names in which some sections are omitted), so let's put them |
1293 | | // in a simple vector and use linear lookup. |
1294 | | // TODO: Implement an actual map for fast lookup for "hashable" call |
1295 | | // descriptions (eg., the ones for C functions that just match the name). |
1296 | | std::vector<std::pair<CallDescription, T>> LinearMap; |
1297 | | |
1298 | | public: |
1299 | | CallDescriptionMap( |
1300 | | std::initializer_list<std::pair<CallDescription, T>> &&List) |
1301 | 1.35k | : LinearMap(List) {} CStringChecker.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::CStringChecker::*)(clang::ento::CheckerContext&, clang::CallExpr const*) const>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, void ((anonymous namespace)::CStringChecker::*)(clang::ento::CheckerContext&, clang::CallExpr const*) const> >&&) Line | Count | Source | 1301 | 233 | : LinearMap(List) {} |
CastValueChecker.cpp:clang::ento::CallDescriptionMap<std::__1::pair<std::__1::function<void ((anonymous namespace)::CastValueChecker const*, clang::ento::CallEvent const&, clang::ento::DefinedOrUnknownSVal, clang::ento::CheckerContext&)>, (anonymous namespace)::CastValueChecker::CallKind> >::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, std::__1::pair<std::__1::function<void ((anonymous namespace)::CastValueChecker const*, clang::ento::CallEvent const&, clang::ento::DefinedOrUnknownSVal, clang::ento::CheckerContext&)>, (anonymous namespace)::CastValueChecker::CallKind> > >&&) Line | Count | Source | 1301 | 30 | : LinearMap(List) {} |
ContainerModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::ContainerModeling::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::Expr const*) const>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, void ((anonymous namespace)::ContainerModeling::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::Expr const*) const> >&&) Line | Count | Source | 1301 | 21 | : LinearMap(List) {} |
ContainerModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::ContainerModeling::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::ento::SVal) const>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, void ((anonymous namespace)::ContainerModeling::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::ento::SVal) const> >&&) Line | Count | Source | 1301 | 21 | : LinearMap(List) {} |
ContainerModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::ContainerModeling::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::ento::SVal, clang::ento::SVal) const>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, void ((anonymous namespace)::ContainerModeling::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::ento::SVal, clang::ento::SVal) const> >&&) Line | Count | Source | 1301 | 21 | : LinearMap(List) {} |
DebugContainerModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::DebugContainerModeling::*)(clang::CallExpr const*, clang::ento::CheckerContext&) const>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, void ((anonymous namespace)::DebugContainerModeling::*)(clang::CallExpr const*, clang::ento::CheckerContext&) const> >&&) Line | Count | Source | 1301 | 13 | : LinearMap(List) {} |
DebugIteratorModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::DebugIteratorModeling::*)(clang::CallExpr const*, clang::ento::CheckerContext&) const>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, void ((anonymous namespace)::DebugIteratorModeling::*)(clang::CallExpr const*, clang::ento::CheckerContext&) const> >&&) Line | Count | Source | 1301 | 11 | : LinearMap(List) {} |
IteratorModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::IteratorModeling::*)(clang::ento::CheckerContext&, clang::Expr const*, clang::ento::SVal, clang::ento::SVal, clang::ento::SVal) const>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, void ((anonymous namespace)::IteratorModeling::*)(clang::ento::CheckerContext&, clang::Expr const*, clang::ento::SVal, clang::ento::SVal, clang::ento::SVal) const> >&&) Line | Count | Source | 1301 | 19 | : LinearMap(List) {} |
IteratorRangeChecker.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::IteratorRangeChecker::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::ento::SVal) const>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, void ((anonymous namespace)::IteratorRangeChecker::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::ento::SVal) const> >&&) Line | Count | Source | 1301 | 2 | : LinearMap(List) {} |
MallocChecker.cpp:clang::ento::CallDescriptionMap<std::__1::function<void ((anonymous namespace)::MallocChecker const*, clang::ento::CallEvent const&, clang::ento::CheckerContext&)> >::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, std::__1::function<void ((anonymous namespace)::MallocChecker const*, clang::ento::CallEvent const&, clang::ento::CheckerContext&)> > >&&) Line | Count | Source | 1301 | 636 | : LinearMap(List) {} |
PthreadLockChecker.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::PthreadLockChecker::*)(clang::ento::CallEvent const&, clang::ento::CheckerContext&, (anonymous namespace)::PthreadLockChecker::CheckerKind) const>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, void ((anonymous namespace)::PthreadLockChecker::*)(clang::ento::CallEvent const&, clang::ento::CheckerContext&, (anonymous namespace)::PthreadLockChecker::CheckerKind) const> >&&) Line | Count | Source | 1301 | 219 | : LinearMap(List) {} |
clang::ento::CallDescriptionMap<bool>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, bool> >&&) Line | Count | Source | 1301 | 34 | : LinearMap(List) {} |
SmartPtrModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::SmartPtrModeling::*)(clang::ento::CallEvent const&, clang::ento::CheckerContext&) const>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, void ((anonymous namespace)::SmartPtrModeling::*)(clang::ento::CallEvent const&, clang::ento::CheckerContext&) const> >&&) Line | Count | Source | 1301 | 69 | : LinearMap(List) {} |
STLAlgorithmModeling.cpp:clang::ento::CallDescriptionMap<bool ((anonymous namespace)::STLAlgorithmModeling::*)(clang::ento::CheckerContext&, clang::CallExpr const*) const>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, bool ((anonymous namespace)::STLAlgorithmModeling::*)(clang::ento::CheckerContext&, clang::CallExpr const*) const> >&&) Line | Count | Source | 1301 | 2 | : LinearMap(List) {} |
StreamChecker.cpp:clang::ento::CallDescriptionMap<(anonymous namespace)::FnDescription>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, (anonymous namespace)::FnDescription> >&&) Line | Count | Source | 1301 | 22 | : LinearMap(List) {} |
|
1302 | | |
1303 | 1.35k | ~CallDescriptionMap() = default; CStringChecker.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::CStringChecker::*)(clang::ento::CheckerContext&, clang::CallExpr const*) const>::~CallDescriptionMap() Line | Count | Source | 1303 | 233 | ~CallDescriptionMap() = default; |
CastValueChecker.cpp:clang::ento::CallDescriptionMap<std::__1::pair<std::__1::function<void ((anonymous namespace)::CastValueChecker const*, clang::ento::CallEvent const&, clang::ento::DefinedOrUnknownSVal, clang::ento::CheckerContext&)>, (anonymous namespace)::CastValueChecker::CallKind> >::~CallDescriptionMap() Line | Count | Source | 1303 | 30 | ~CallDescriptionMap() = default; |
ContainerModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::ContainerModeling::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::ento::SVal, clang::ento::SVal) const>::~CallDescriptionMap() Line | Count | Source | 1303 | 21 | ~CallDescriptionMap() = default; |
ContainerModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::ContainerModeling::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::ento::SVal) const>::~CallDescriptionMap() Line | Count | Source | 1303 | 21 | ~CallDescriptionMap() = default; |
ContainerModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::ContainerModeling::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::Expr const*) const>::~CallDescriptionMap() Line | Count | Source | 1303 | 21 | ~CallDescriptionMap() = default; |
DebugContainerModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::DebugContainerModeling::*)(clang::CallExpr const*, clang::ento::CheckerContext&) const>::~CallDescriptionMap() Line | Count | Source | 1303 | 13 | ~CallDescriptionMap() = default; |
DebugIteratorModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::DebugIteratorModeling::*)(clang::CallExpr const*, clang::ento::CheckerContext&) const>::~CallDescriptionMap() Line | Count | Source | 1303 | 11 | ~CallDescriptionMap() = default; |
IteratorModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::IteratorModeling::*)(clang::ento::CheckerContext&, clang::Expr const*, clang::ento::SVal, clang::ento::SVal, clang::ento::SVal) const>::~CallDescriptionMap() Line | Count | Source | 1303 | 19 | ~CallDescriptionMap() = default; |
IteratorRangeChecker.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::IteratorRangeChecker::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::ento::SVal) const>::~CallDescriptionMap() Line | Count | Source | 1303 | 2 | ~CallDescriptionMap() = default; |
MallocChecker.cpp:clang::ento::CallDescriptionMap<std::__1::function<void ((anonymous namespace)::MallocChecker const*, clang::ento::CallEvent const&, clang::ento::CheckerContext&)> >::~CallDescriptionMap() Line | Count | Source | 1303 | 636 | ~CallDescriptionMap() = default; |
PthreadLockChecker.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::PthreadLockChecker::*)(clang::ento::CallEvent const&, clang::ento::CheckerContext&, (anonymous namespace)::PthreadLockChecker::CheckerKind) const>::~CallDescriptionMap() Line | Count | Source | 1303 | 219 | ~CallDescriptionMap() = default; |
clang::ento::CallDescriptionMap<bool>::~CallDescriptionMap() Line | Count | Source | 1303 | 34 | ~CallDescriptionMap() = default; |
SmartPtrModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::SmartPtrModeling::*)(clang::ento::CallEvent const&, clang::ento::CheckerContext&) const>::~CallDescriptionMap() Line | Count | Source | 1303 | 69 | ~CallDescriptionMap() = default; |
STLAlgorithmModeling.cpp:clang::ento::CallDescriptionMap<bool ((anonymous namespace)::STLAlgorithmModeling::*)(clang::ento::CheckerContext&, clang::CallExpr const*) const>::~CallDescriptionMap() Line | Count | Source | 1303 | 2 | ~CallDescriptionMap() = default; |
StreamChecker.cpp:clang::ento::CallDescriptionMap<(anonymous namespace)::FnDescription>::~CallDescriptionMap() Line | Count | Source | 1303 | 22 | ~CallDescriptionMap() = default; |
|
1304 | | |
1305 | | // These maps are usually stored once per checker, so let's make sure |
1306 | | // we don't do redundant copies. |
1307 | | CallDescriptionMap(const CallDescriptionMap &) = delete; |
1308 | | CallDescriptionMap &operator=(const CallDescription &) = delete; |
1309 | | |
1310 | 182k | const T *lookup(const CallEvent &Call) const { |
1311 | | // Slow path: linear lookup. |
1312 | | // TODO: Implement some sort of fast path. |
1313 | 182k | for (const std::pair<CallDescription, T> &I : LinearMap) |
1314 | 1.72M | if (Call.isCalled(I.first)) |
1315 | 10.2k | return &I.second; |
1316 | | |
1317 | 172k | return nullptr; |
1318 | 182k | } CStringChecker.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::CStringChecker::*)(clang::ento::CheckerContext&, clang::CallExpr const*) const>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 19.0k | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 19.0k | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 431k | if (Call.isCalled(I.first)) | 1315 | 2.06k | return &I.second; | 1316 | | | 1317 | 16.9k | return nullptr; | 1318 | 19.0k | } |
CastValueChecker.cpp:clang::ento::CallDescriptionMap<std::__1::pair<std::__1::function<void ((anonymous namespace)::CastValueChecker const*, clang::ento::CallEvent const&, clang::ento::DefinedOrUnknownSVal, clang::ento::CheckerContext&)>, (anonymous namespace)::CastValueChecker::CallKind> >::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 245 | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 245 | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 1.77k | if (Call.isCalled(I.first)) | 1315 | 55 | return &I.second; | 1316 | | | 1317 | 190 | return nullptr; | 1318 | 245 | } |
ContainerModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::ContainerModeling::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::Expr const*) const>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 3.28k | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 3.28k | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 25.5k | if (Call.isCalled(I.first)) | 1315 | 187 | return &I.second; | 1316 | | | 1317 | 3.09k | return nullptr; | 1318 | 3.28k | } |
ContainerModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::ContainerModeling::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::ento::SVal) const>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 3.09k | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 3.09k | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 11.7k | if (Call.isCalled(I.first)) | 1315 | 326 | return &I.second; | 1316 | | | 1317 | 2.76k | return nullptr; | 1318 | 3.09k | } |
ContainerModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::ContainerModeling::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::ento::SVal, clang::ento::SVal) const>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 2.76k | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 2.76k | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 5.53k | if (Call.isCalled(I.first)) | 1315 | 8 | return &I.second; | 1316 | | | 1317 | 2.76k | return nullptr; | 1318 | 2.76k | } |
DebugContainerModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::DebugContainerModeling::*)(clang::CallExpr const*, clang::ento::CheckerContext&) const>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 10.6k | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 10.6k | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 20.7k | if (Call.isCalled(I.first)) | 1315 | 1.08k | return &I.second; | 1316 | | | 1317 | 9.52k | return nullptr; | 1318 | 10.6k | } |
DebugIteratorModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::DebugIteratorModeling::*)(clang::CallExpr const*, clang::ento::CheckerContext&) const>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 10.5k | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 10.5k | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 28.8k | if (Call.isCalled(I.first)) | 1315 | 2.68k | return &I.second; | 1316 | | | 1317 | 7.90k | return nullptr; | 1318 | 10.5k | } |
IteratorModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::IteratorModeling::*)(clang::ento::CheckerContext&, clang::Expr const*, clang::ento::SVal, clang::ento::SVal, clang::ento::SVal) const>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 16.0k | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 16.0k | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 47.9k | if (Call.isCalled(I.first)) | 1315 | 248 | return &I.second; | 1316 | | | 1317 | 15.8k | return nullptr; | 1318 | 16.0k | } |
IteratorRangeChecker.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::IteratorRangeChecker::*)(clang::ento::CheckerContext&, clang::ento::SVal, clang::ento::SVal) const>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 1.39k | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 1.39k | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 3.89k | if (Call.isCalled(I.first)) | 1315 | 228 | return &I.second; | 1316 | | | 1317 | 1.17k | return nullptr; | 1318 | 1.39k | } |
MallocChecker.cpp:clang::ento::CallDescriptionMap<std::__1::function<void ((anonymous namespace)::MallocChecker const*, clang::ento::CallEvent const&, clang::ento::CheckerContext&)> >::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 107k | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 107k | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 1.03M | if (Call.isCalled(I.first)) | 1315 | 2.20k | return &I.second; | 1316 | | | 1317 | 105k | return nullptr; | 1318 | 107k | } |
PthreadLockChecker.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::PthreadLockChecker::*)(clang::ento::CallEvent const&, clang::ento::CheckerContext&, (anonymous namespace)::PthreadLockChecker::CheckerKind) const>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 5.57k | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 5.57k | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 69.6k | if (Call.isCalled(I.first)) | 1315 | 507 | return &I.second; | 1316 | | | 1317 | 5.07k | return nullptr; | 1318 | 5.57k | } |
clang::ento::CallDescriptionMap<bool>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 182 | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 182 | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 2.76k | if (Call.isCalled(I.first)) | 1315 | 12 | return &I.second; | 1316 | | | 1317 | 170 | return nullptr; | 1318 | 182 | } |
SmartPtrModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::SmartPtrModeling::*)(clang::ento::CallEvent const&, clang::ento::CheckerContext&) const>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 79 | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 79 | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 249 | if (Call.isCalled(I.first)) | 1315 | 51 | return &I.second; | 1316 | | | 1317 | 28 | return nullptr; | 1318 | 79 | } |
STLAlgorithmModeling.cpp:clang::ento::CallDescriptionMap<bool ((anonymous namespace)::STLAlgorithmModeling::*)(clang::ento::CheckerContext&, clang::CallExpr const*) const>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 1.23k | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 1.23k | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 27.9k | if (Call.isCalled(I.first)) | 1315 | 54 | return &I.second; | 1316 | | | 1317 | 1.18k | return nullptr; | 1318 | 1.23k | } |
StreamChecker.cpp:clang::ento::CallDescriptionMap<(anonymous namespace)::FnDescription>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 1310 | 716 | const T *lookup(const CallEvent &Call) const { | 1311 | | // Slow path: linear lookup. | 1312 | | // TODO: Implement some sort of fast path. | 1313 | 716 | for (const std::pair<CallDescription, T> &I : LinearMap) | 1314 | 5.91k | if (Call.isCalled(I.first)) | 1315 | 497 | return &I.second; | 1316 | | | 1317 | 219 | return nullptr; | 1318 | 716 | } |
|
1319 | | }; |
1320 | | |
1321 | | /// Manages the lifetime of CallEvent objects. |
1322 | | /// |
1323 | | /// CallEventManager provides a way to create arbitrary CallEvents "on the |
1324 | | /// stack" as if they were value objects by keeping a cache of CallEvent-sized |
1325 | | /// memory blocks. The CallEvents created by CallEventManager are only valid |
1326 | | /// for the lifetime of the OwnedCallEvent that holds them; right now these |
1327 | | /// objects cannot be copied and ownership cannot be transferred. |
1328 | | class CallEventManager { |
1329 | | friend class CallEvent; |
1330 | | |
1331 | | llvm::BumpPtrAllocator &Alloc; |
1332 | | SmallVector<void *, 8> Cache; |
1333 | | |
1334 | | using CallEventTemplateTy = SimpleFunctionCall; |
1335 | | |
1336 | 470k | void reclaim(const void *Memory) { |
1337 | 470k | Cache.push_back(const_cast<void *>(Memory)); |
1338 | 470k | } |
1339 | | |
1340 | | /// Returns memory that can be initialized as a CallEvent. |
1341 | 470k | void *allocate() { |
1342 | 470k | if (Cache.empty()) |
1343 | 21.6k | return Alloc.Allocate<CallEventTemplateTy>(); |
1344 | 448k | else |
1345 | 448k | return Cache.pop_back_val(); |
1346 | 470k | } |
1347 | | |
1348 | | template <typename T, typename Arg> |
1349 | 153k | T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) { |
1350 | 153k | static_assert(sizeof(T) == sizeof(CallEventTemplateTy), |
1351 | 153k | "CallEvent subclasses are not all the same size"); |
1352 | 153k | return new (allocate()) T(A, St, LCtx); |
1353 | 153k | } clang::ento::CXXMemberCall* clang::ento::CallEventManager::create<clang::ento::CXXMemberCall, clang::CXXMemberCallExpr const*>(clang::CXXMemberCallExpr const*, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>, clang::LocationContext const*) Line | Count | Source | 1349 | 19.1k | T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) { | 1350 | 19.1k | static_assert(sizeof(T) == sizeof(CallEventTemplateTy), | 1351 | 19.1k | "CallEvent subclasses are not all the same size"); | 1352 | 19.1k | return new (allocate()) T(A, St, LCtx); | 1353 | 19.1k | } |
clang::ento::CXXMemberOperatorCall* clang::ento::CallEventManager::create<clang::ento::CXXMemberOperatorCall, clang::CXXOperatorCallExpr const*>(clang::CXXOperatorCallExpr const*, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>, clang::LocationContext const*) Line | Count | Source | 1349 | 8.22k | T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) { | 1350 | 8.22k | static_assert(sizeof(T) == sizeof(CallEventTemplateTy), | 1351 | 8.22k | "CallEvent subclasses are not all the same size"); | 1352 | 8.22k | return new (allocate()) T(A, St, LCtx); | 1353 | 8.22k | } |
clang::ento::BlockCall* clang::ento::CallEventManager::create<clang::ento::BlockCall, clang::CallExpr const*>(clang::CallExpr const*, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>, clang::LocationContext const*) Line | Count | Source | 1349 | 585 | T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) { | 1350 | 585 | static_assert(sizeof(T) == sizeof(CallEventTemplateTy), | 1351 | 585 | "CallEvent subclasses are not all the same size"); | 1352 | 585 | return new (allocate()) T(A, St, LCtx); | 1353 | 585 | } |
clang::ento::SimpleFunctionCall* clang::ento::CallEventManager::create<clang::ento::SimpleFunctionCall, clang::CallExpr const*>(clang::CallExpr const*, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>, clang::LocationContext const*) Line | Count | Source | 1349 | 115k | T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) { | 1350 | 115k | static_assert(sizeof(T) == sizeof(CallEventTemplateTy), | 1351 | 115k | "CallEvent subclasses are not all the same size"); | 1352 | 115k | return new (allocate()) T(A, St, LCtx); | 1353 | 115k | } |
clang::ento::ObjCMethodCall* clang::ento::CallEventManager::create<clang::ento::ObjCMethodCall, clang::ObjCMessageExpr const*>(clang::ObjCMessageExpr const*, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>, clang::LocationContext const*) Line | Count | Source | 1349 | 6.18k | T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) { | 1350 | 6.18k | static_assert(sizeof(T) == sizeof(CallEventTemplateTy), | 1351 | 6.18k | "CallEvent subclasses are not all the same size"); | 1352 | 6.18k | return new (allocate()) T(A, St, LCtx); | 1353 | 6.18k | } |
clang::ento::CXXAllocatorCall* clang::ento::CallEventManager::create<clang::ento::CXXAllocatorCall, clang::CXXNewExpr const*>(clang::CXXNewExpr const*, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>, clang::LocationContext const*) Line | Count | Source | 1349 | 2.83k | T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) { | 1350 | 2.83k | static_assert(sizeof(T) == sizeof(CallEventTemplateTy), | 1351 | 2.83k | "CallEvent subclasses are not all the same size"); | 1352 | 2.83k | return new (allocate()) T(A, St, LCtx); | 1353 | 2.83k | } |
clang::ento::CXXDeallocatorCall* clang::ento::CallEventManager::create<clang::ento::CXXDeallocatorCall, clang::CXXDeleteExpr const*>(clang::CXXDeleteExpr const*, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>, clang::LocationContext const*) Line | Count | Source | 1349 | 436 | T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) { | 1350 | 436 | static_assert(sizeof(T) == sizeof(CallEventTemplateTy), | 1351 | 436 | "CallEvent subclasses are not all the same size"); | 1352 | 436 | return new (allocate()) T(A, St, LCtx); | 1353 | 436 | } |
|
1354 | | |
1355 | | template <typename T, typename Arg1, typename Arg2> |
1356 | 41.0k | T *create(Arg1 A1, Arg2 A2, ProgramStateRef St, const LocationContext *LCtx) { |
1357 | 41.0k | static_assert(sizeof(T) == sizeof(CallEventTemplateTy), |
1358 | 41.0k | "CallEvent subclasses are not all the same size"); |
1359 | 41.0k | return new (allocate()) T(A1, A2, St, LCtx); |
1360 | 41.0k | } clang::ento::CXXConstructorCall* clang::ento::CallEventManager::create<clang::ento::CXXConstructorCall, clang::CXXConstructExpr const*, clang::ento::MemRegion const*>(clang::CXXConstructExpr const*, clang::ento::MemRegion const*, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>, clang::LocationContext const*) Line | Count | Source | 1356 | 41.0k | T *create(Arg1 A1, Arg2 A2, ProgramStateRef St, const LocationContext *LCtx) { | 1357 | 41.0k | static_assert(sizeof(T) == sizeof(CallEventTemplateTy), | 1358 | 41.0k | "CallEvent subclasses are not all the same size"); | 1359 | 41.0k | return new (allocate()) T(A1, A2, St, LCtx); | 1360 | 41.0k | } |
clang::ento::CXXInheritedConstructorCall* clang::ento::CallEventManager::create<clang::ento::CXXInheritedConstructorCall, clang::CXXInheritedCtorInitExpr const*, clang::ento::MemRegion const*>(clang::CXXInheritedCtorInitExpr const*, clang::ento::MemRegion const*, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>, clang::LocationContext const*) Line | Count | Source | 1356 | 13 | T *create(Arg1 A1, Arg2 A2, ProgramStateRef St, const LocationContext *LCtx) { | 1357 | 13 | static_assert(sizeof(T) == sizeof(CallEventTemplateTy), | 1358 | 13 | "CallEvent subclasses are not all the same size"); | 1359 | 13 | return new (allocate()) T(A1, A2, St, LCtx); | 1360 | 13 | } |
|
1361 | | |
1362 | | template <typename T, typename Arg1, typename Arg2, typename Arg3> |
1363 | | T *create(Arg1 A1, Arg2 A2, Arg3 A3, ProgramStateRef St, |
1364 | | const LocationContext *LCtx) { |
1365 | | static_assert(sizeof(T) == sizeof(CallEventTemplateTy), |
1366 | | "CallEvent subclasses are not all the same size"); |
1367 | | return new (allocate()) T(A1, A2, A3, St, LCtx); |
1368 | | } |
1369 | | |
1370 | | template <typename T, typename Arg1, typename Arg2, typename Arg3, |
1371 | | typename Arg4> |
1372 | | T *create(Arg1 A1, Arg2 A2, Arg3 A3, Arg4 A4, ProgramStateRef St, |
1373 | 2.97k | const LocationContext *LCtx) { |
1374 | 2.97k | static_assert(sizeof(T) == sizeof(CallEventTemplateTy), |
1375 | 2.97k | "CallEvent subclasses are not all the same size"); |
1376 | 2.97k | return new (allocate()) T(A1, A2, A3, A4, St, LCtx); |
1377 | 2.97k | } |
1378 | | |
1379 | | public: |
1380 | 13.7k | CallEventManager(llvm::BumpPtrAllocator &alloc) : Alloc(alloc) {} |
1381 | | |
1382 | | /// Gets an outside caller given a callee context. |
1383 | | CallEventRef<> |
1384 | | getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State); |
1385 | | |
1386 | | /// Gets a call event for a function call, Objective-C method call, |
1387 | | /// or a 'new' call. |
1388 | | CallEventRef<> |
1389 | | getCall(const Stmt *S, ProgramStateRef State, |
1390 | | const LocationContext *LC); |
1391 | | |
1392 | | CallEventRef<> |
1393 | | getSimpleCall(const CallExpr *E, ProgramStateRef State, |
1394 | | const LocationContext *LCtx); |
1395 | | |
1396 | | CallEventRef<ObjCMethodCall> |
1397 | | getObjCMethodCall(const ObjCMessageExpr *E, ProgramStateRef State, |
1398 | 6.18k | const LocationContext *LCtx) { |
1399 | 6.18k | return create<ObjCMethodCall>(E, State, LCtx); |
1400 | 6.18k | } |
1401 | | |
1402 | | CallEventRef<CXXConstructorCall> |
1403 | | getCXXConstructorCall(const CXXConstructExpr *E, const MemRegion *Target, |
1404 | 41.0k | ProgramStateRef State, const LocationContext *LCtx) { |
1405 | 41.0k | return create<CXXConstructorCall>(E, Target, State, LCtx); |
1406 | 41.0k | } |
1407 | | |
1408 | | CallEventRef<CXXInheritedConstructorCall> |
1409 | | getCXXInheritedConstructorCall(const CXXInheritedCtorInitExpr *E, |
1410 | | const MemRegion *Target, ProgramStateRef State, |
1411 | 13 | const LocationContext *LCtx) { |
1412 | 13 | return create<CXXInheritedConstructorCall>(E, Target, State, LCtx); |
1413 | 13 | } |
1414 | | |
1415 | | CallEventRef<CXXDestructorCall> |
1416 | | getCXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, |
1417 | | const MemRegion *Target, bool IsBase, |
1418 | 2.97k | ProgramStateRef State, const LocationContext *LCtx) { |
1419 | 2.97k | return create<CXXDestructorCall>(DD, Trigger, Target, IsBase, State, LCtx); |
1420 | 2.97k | } |
1421 | | |
1422 | | CallEventRef<CXXAllocatorCall> |
1423 | | getCXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef State, |
1424 | 2.83k | const LocationContext *LCtx) { |
1425 | 2.83k | return create<CXXAllocatorCall>(E, State, LCtx); |
1426 | 2.83k | } |
1427 | | |
1428 | | CallEventRef<CXXDeallocatorCall> |
1429 | | getCXXDeallocatorCall(const CXXDeleteExpr *E, ProgramStateRef State, |
1430 | 436 | const LocationContext *LCtx) { |
1431 | 436 | return create<CXXDeallocatorCall>(E, State, LCtx); |
1432 | 436 | } |
1433 | | }; |
1434 | | |
1435 | | template <typename T> |
1436 | 1.01M | CallEventRef<T> CallEvent::cloneWithState(ProgramStateRef NewState) const { |
1437 | 1.01M | assert(isa<T>(*this) && "Cloning to unrelated type"); |
1438 | 1.01M | static_assert(sizeof(T) == sizeof(CallEvent), |
1439 | 1.01M | "Subclasses may not add fields"); |
1440 | | |
1441 | 1.01M | if (NewState == State) |
1442 | 739k | return cast<T>(this); |
1443 | | |
1444 | 272k | CallEventManager &Mgr = State->getStateManager().getCallEventManager(); |
1445 | 272k | T *Copy = static_cast<T *>(Mgr.allocate()); |
1446 | 272k | cloneTo(Copy); |
1447 | 272k | assert(Copy->getKind() == this->getKind() && "Bad copy"); |
1448 | | |
1449 | 272k | Copy->State = NewState; |
1450 | 272k | return Copy; |
1451 | 272k | } clang::ento::CallEventRef<clang::ento::ObjCMethodCall> clang::ento::CallEvent::cloneWithState<clang::ento::ObjCMethodCall>(llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>) const Line | Count | Source | 1436 | 22.1k | CallEventRef<T> CallEvent::cloneWithState(ProgramStateRef NewState) const { | 1437 | 22.1k | assert(isa<T>(*this) && "Cloning to unrelated type"); | 1438 | 22.1k | static_assert(sizeof(T) == sizeof(CallEvent), | 1439 | 22.1k | "Subclasses may not add fields"); | 1440 | | | 1441 | 22.1k | if (NewState == State) | 1442 | 7.64k | return cast<T>(this); | 1443 | | | 1444 | 14.5k | CallEventManager &Mgr = State->getStateManager().getCallEventManager(); | 1445 | 14.5k | T *Copy = static_cast<T *>(Mgr.allocate()); | 1446 | 14.5k | cloneTo(Copy); | 1447 | 14.5k | assert(Copy->getKind() == this->getKind() && "Bad copy"); | 1448 | | | 1449 | 14.5k | Copy->State = NewState; | 1450 | 14.5k | return Copy; | 1451 | 14.5k | } |
clang::ento::CallEventRef<clang::ento::CallEvent> clang::ento::CallEvent::cloneWithState<clang::ento::CallEvent>(llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>) const Line | Count | Source | 1436 | 990k | CallEventRef<T> CallEvent::cloneWithState(ProgramStateRef NewState) const { | 1437 | 990k | assert(isa<T>(*this) && "Cloning to unrelated type"); | 1438 | 990k | static_assert(sizeof(T) == sizeof(CallEvent), | 1439 | 990k | "Subclasses may not add fields"); | 1440 | | | 1441 | 990k | if (NewState == State) | 1442 | 732k | return cast<T>(this); | 1443 | | | 1444 | 258k | CallEventManager &Mgr = State->getStateManager().getCallEventManager(); | 1445 | 258k | T *Copy = static_cast<T *>(Mgr.allocate()); | 1446 | 258k | cloneTo(Copy); | 1447 | 258k | assert(Copy->getKind() == this->getKind() && "Bad copy"); | 1448 | | | 1449 | 258k | Copy->State = NewState; | 1450 | 258k | return Copy; | 1451 | 258k | } |
|
1452 | | |
1453 | 1.32M | inline void CallEvent::Release() const { |
1454 | 1.32M | assert(RefCount > 0 && "Reference count is already zero."); |
1455 | 1.32M | --RefCount; |
1456 | | |
1457 | 1.32M | if (RefCount > 0) |
1458 | 856k | return; |
1459 | | |
1460 | 470k | CallEventManager &Mgr = State->getStateManager().getCallEventManager(); |
1461 | 470k | Mgr.reclaim(this); |
1462 | | |
1463 | 470k | this->~CallEvent(); |
1464 | 470k | } |
1465 | | |
1466 | | } // namespace ento |
1467 | | |
1468 | | } // namespace clang |
1469 | | |
1470 | | namespace llvm { |
1471 | | |
1472 | | // Support isa<>, cast<>, and dyn_cast<> for CallEventRef. |
1473 | | template<class T> struct simplify_type< clang::ento::CallEventRef<T>> { |
1474 | | using SimpleType = const T *; |
1475 | | |
1476 | | static SimpleType |
1477 | 42.9k | getSimplifiedValue(clang::ento::CallEventRef<T> Val) { |
1478 | 42.9k | return Val.get(); |
1479 | 42.9k | } |
1480 | | }; |
1481 | | |
1482 | | } // namespace llvm |
1483 | | |
1484 | | #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H |