/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- CallDescription.h - function/method call matching --*- 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 a generic mechanism for matching for function and |
10 | | /// method calls of C, C++, and Objective-C languages. Instances of these |
11 | | /// classes are frequently used together with the CallEvent classes. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLDESCRIPTION_H |
16 | | #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLDESCRIPTION_H |
17 | | |
18 | | #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" |
19 | | #include "llvm/ADT/ArrayRef.h" |
20 | | #include "llvm/ADT/Optional.h" |
21 | | #include "llvm/Support/Compiler.h" |
22 | | #include <vector> |
23 | | |
24 | | namespace clang { |
25 | | class IdentifierInfo; |
26 | | } // namespace clang |
27 | | |
28 | | namespace clang { |
29 | | namespace ento { |
30 | | |
31 | | enum CallDescriptionFlags : unsigned { |
32 | | CDF_None = 0, |
33 | | |
34 | | /// Describes a C standard function that is sometimes implemented as a macro |
35 | | /// that expands to a compiler builtin with some __builtin prefix. |
36 | | /// The builtin may as well have a few extra arguments on top of the requested |
37 | | /// number of arguments. |
38 | | CDF_MaybeBuiltin = 1 << 0, |
39 | | }; |
40 | | |
41 | | /// This class represents a description of a function call using the number of |
42 | | /// arguments and the name of the function. |
43 | | class CallDescription { |
44 | | friend class CallEvent; |
45 | | using MaybeCount = Optional<unsigned>; |
46 | | |
47 | | mutable Optional<const IdentifierInfo *> II; |
48 | | // The list of the qualified names used to identify the specified CallEvent, |
49 | | // e.g. "{a, b}" represent the qualified names, like "a::b". |
50 | | std::vector<std::string> QualifiedName; |
51 | | MaybeCount RequiredArgs; |
52 | | MaybeCount RequiredParams; |
53 | | int Flags; |
54 | | |
55 | | public: |
56 | | /// Constructs a CallDescription object. |
57 | | /// |
58 | | /// @param QualifiedName The list of the name qualifiers of the function that |
59 | | /// will be matched. The user is allowed to skip any of the qualifiers. |
60 | | /// For example, {"std", "basic_string", "c_str"} would match both |
61 | | /// std::basic_string<...>::c_str() and std::__1::basic_string<...>::c_str(). |
62 | | /// |
63 | | /// @param RequiredArgs The number of arguments that is expected to match a |
64 | | /// call. Omit this parameter to match every occurrence of call with a given |
65 | | /// name regardless the number of arguments. |
66 | | CallDescription(CallDescriptionFlags Flags, |
67 | | ArrayRef<const char *> QualifiedName, |
68 | | MaybeCount RequiredArgs = None, |
69 | | MaybeCount RequiredParams = None); |
70 | | |
71 | | /// Construct a CallDescription with default flags. |
72 | | CallDescription(ArrayRef<const char *> QualifiedName, |
73 | | MaybeCount RequiredArgs = None, |
74 | | MaybeCount RequiredParams = None); |
75 | | |
76 | | CallDescription(std::nullptr_t) = delete; |
77 | | |
78 | | /// Get the name of the function that this object matches. |
79 | 774k | StringRef getFunctionName() const { return QualifiedName.back(); } |
80 | | |
81 | | /// Get the qualified name parts in reversed order. |
82 | | /// E.g. { "std", "vector", "data" } -> "vector", "std" |
83 | 2.74k | auto begin_qualified_name_parts() const { |
84 | 2.74k | return std::next(QualifiedName.rbegin()); |
85 | 2.74k | } |
86 | 2.74k | auto end_qualified_name_parts() const { return QualifiedName.rend(); } |
87 | | |
88 | | /// It's false, if and only if we expect a single identifier, such as |
89 | | /// `getenv`. It's true for `std::swap`, or `my::detail::container::data`. |
90 | 12.8k | bool hasQualifiedNameParts() const { return QualifiedName.size() > 1; } |
91 | | |
92 | | /// @name Matching CallDescriptions against a CallEvent |
93 | | /// @{ |
94 | | |
95 | | /// Returns true if the CallEvent is a call to a function that matches |
96 | | /// the CallDescription. |
97 | | /// |
98 | | /// \note This function is not intended to be used to match Obj-C method |
99 | | /// calls. |
100 | | bool matches(const CallEvent &Call) const; |
101 | | |
102 | | /// Returns true whether the CallEvent matches on any of the CallDescriptions |
103 | | /// supplied. |
104 | | /// |
105 | | /// \note This function is not intended to be used to match Obj-C method |
106 | | /// calls. |
107 | 75.9k | friend bool matchesAny(const CallEvent &Call, const CallDescription &CD1) { |
108 | 75.9k | return CD1.matches(Call); |
109 | 75.9k | } |
110 | | |
111 | | /// \copydoc clang::ento::CallDescription::matchesAny(const CallEvent &, const CallDescription &) |
112 | | template <typename... Ts> |
113 | | friend bool matchesAny(const CallEvent &Call, const CallDescription &CD1, |
114 | 144k | const Ts &...CDs) { |
115 | 144k | return CD1.matches(Call) || matchesAny(Call, CDs...)144k ; |
116 | 144k | } bool clang::ento::matchesAny<clang::ento::CallDescription>(clang::ento::CallEvent const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&) Line | Count | Source | 114 | 75.9k | const Ts &...CDs) { | 115 | 75.9k | return CD1.matches(Call) || matchesAny(Call, CDs...)75.9k ; | 116 | 75.9k | } |
bool clang::ento::matchesAny<clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription>(clang::ento::CallEvent const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&) Line | Count | Source | 114 | 3.59k | const Ts &...CDs) { | 115 | 3.59k | return CD1.matches(Call) || matchesAny(Call, CDs...)3.59k ; | 116 | 3.59k | } |
bool clang::ento::matchesAny<clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription>(clang::ento::CallEvent const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&) Line | Count | Source | 114 | 3.59k | const Ts &...CDs) { | 115 | 3.59k | return CD1.matches(Call) || matchesAny(Call, CDs...)3.59k ; | 116 | 3.59k | } |
bool clang::ento::matchesAny<clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription>(clang::ento::CallEvent const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&) Line | Count | Source | 114 | 3.59k | const Ts &...CDs) { | 115 | 3.59k | return CD1.matches(Call) || matchesAny(Call, CDs...)3.59k ; | 116 | 3.59k | } |
bool clang::ento::matchesAny<clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription>(clang::ento::CallEvent const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&) Line | Count | Source | 114 | 3.59k | const Ts &...CDs) { | 115 | 3.59k | return CD1.matches(Call) || matchesAny(Call, CDs...)3.59k ; | 116 | 3.59k | } |
bool clang::ento::matchesAny<clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription>(clang::ento::CallEvent const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&) Line | Count | Source | 114 | 3.59k | const Ts &...CDs) { | 115 | 3.59k | return CD1.matches(Call) || matchesAny(Call, CDs...)3.59k ; | 116 | 3.59k | } |
bool clang::ento::matchesAny<clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription>(clang::ento::CallEvent const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&) Line | Count | Source | 114 | 3.59k | const Ts &...CDs) { | 115 | 3.59k | return CD1.matches(Call) || matchesAny(Call, CDs...)3.59k ; | 116 | 3.59k | } |
bool clang::ento::matchesAny<clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription>(clang::ento::CallEvent const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&) Line | Count | Source | 114 | 3.71k | const Ts &...CDs) { | 115 | 3.71k | return CD1.matches(Call) || matchesAny(Call, CDs...)3.69k ; | 116 | 3.71k | } |
bool clang::ento::matchesAny<clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription>(clang::ento::CallEvent const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&) Line | Count | Source | 114 | 3.80k | const Ts &...CDs) { | 115 | 3.80k | return CD1.matches(Call) || matchesAny(Call, CDs...)3.78k ; | 116 | 3.80k | } |
bool clang::ento::matchesAny<clang::ento::CallDescription, clang::ento::CallDescription, clang::ento::CallDescription>(clang::ento::CallEvent const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&) Line | Count | Source | 114 | 3.78k | const Ts &...CDs) { | 115 | 3.78k | return CD1.matches(Call) || matchesAny(Call, CDs...)3.77k ; | 116 | 3.78k | } |
bool clang::ento::matchesAny<clang::ento::CallDescription, clang::ento::CallDescription>(clang::ento::CallEvent const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&, clang::ento::CallDescription const&) Line | Count | Source | 114 | 36.0k | const Ts &...CDs) { | 115 | 36.0k | return CD1.matches(Call) || matchesAny(Call, CDs...)35.9k ; | 116 | 36.0k | } |
|
117 | | /// @} |
118 | | |
119 | | /// @name Matching CallDescriptions against a CallExpr |
120 | | /// @{ |
121 | | |
122 | | /// Returns true if the CallExpr is a call to a function that matches the |
123 | | /// CallDescription. |
124 | | /// |
125 | | /// When available, always prefer matching with a CallEvent! This function |
126 | | /// exists only when that is not available, for example, when _only_ |
127 | | /// syntactic check is done on a piece of code. |
128 | | /// |
129 | | /// Also, StdLibraryFunctionsChecker::Signature is likely a better candicade |
130 | | /// for syntactic only matching if you are writing a new checker. This is |
131 | | /// handy if a CallDescriptionMap is already there. |
132 | | /// |
133 | | /// The function is imprecise because CallEvent may know path sensitive |
134 | | /// information, such as the precise argument count (see comments for |
135 | | /// CallEvent::getNumArgs), the called function if it was called through a |
136 | | /// function pointer, and other information not available syntactically. |
137 | | bool matchesAsWritten(const CallExpr &CE) const; |
138 | | |
139 | | /// Returns true whether the CallExpr matches on any of the CallDescriptions |
140 | | /// supplied. |
141 | | /// |
142 | | /// \note This function is not intended to be used to match Obj-C method |
143 | | /// calls. |
144 | | friend bool matchesAnyAsWritten(const CallExpr &CE, |
145 | 0 | const CallDescription &CD1) { |
146 | 0 | return CD1.matchesAsWritten(CE); |
147 | 0 | } |
148 | | |
149 | | /// \copydoc clang::ento::CallDescription::matchesAnyAsWritten(const CallExpr &, const CallDescription &) |
150 | | template <typename... Ts> |
151 | | friend bool matchesAnyAsWritten(const CallExpr &CE, |
152 | | const CallDescription &CD1, |
153 | | const Ts &...CDs) { |
154 | | return CD1.matchesAsWritten(CE) || matchesAnyAsWritten(CE, CDs...); |
155 | | } |
156 | | /// @} |
157 | | |
158 | | private: |
159 | | bool matchesImpl(const FunctionDecl *Callee, size_t ArgCount, |
160 | | size_t ParamCount) const; |
161 | | }; |
162 | | |
163 | | /// An immutable map from CallDescriptions to arbitrary data. Provides a unified |
164 | | /// way for checkers to react on function calls. |
165 | | template <typename T> class CallDescriptionMap { |
166 | | friend class CallDescriptionSet; |
167 | | |
168 | | // Some call descriptions aren't easily hashable (eg., the ones with qualified |
169 | | // names in which some sections are omitted), so let's put them |
170 | | // in a simple vector and use linear lookup. |
171 | | // TODO: Implement an actual map for fast lookup for "hashable" call |
172 | | // descriptions (eg., the ones for C functions that just match the name). |
173 | | std::vector<std::pair<CallDescription, T>> LinearMap; |
174 | | |
175 | | public: |
176 | | CallDescriptionMap( |
177 | | std::initializer_list<std::pair<CallDescription, T>> &&List) |
178 | 1.70k | : 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 | 178 | 264 | : 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 | 178 | 53 | : 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 | 178 | 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 | 178 | 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 | 178 | 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 | 178 | 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 | 178 | 11 | : LinearMap(List) {} |
clang::ento::CallDescriptionMap<std::__1::function<void (clang::ento::CheckerContext&, clang::ento::CallEvent const&)> >::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, std::__1::function<void (clang::ento::CheckerContext&, clang::ento::CallEvent const&)> > >&&) Line | Count | Source | 178 | 6 | : LinearMap(List) {} |
GenericTaintChecker.cpp:clang::ento::CallDescriptionMap<(anonymous namespace)::GenericTaintRule>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, (anonymous namespace)::GenericTaintRule> >&&) Line | Count | Source | 178 | 22 | : LinearMap(List) {} |
InvalidPtrChecker.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::InvalidPtrChecker::*)(clang::ento::CallEvent const&, clang::ento::CheckerContext&) const>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, void ((anonymous namespace)::InvalidPtrChecker::*)(clang::ento::CallEvent const&, clang::ento::CheckerContext&) const> >&&) Line | Count | Source | 178 | 14 | : 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 | 178 | 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 | 178 | 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 | 178 | 723 | : 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 | 178 | 231 | : LinearMap(List) {} |
clang::ento::CallDescriptionMap<bool>::CallDescriptionMap(std::initializer_list<std::__1::pair<clang::ento::CallDescription, bool> >&&) Line | Count | Source | 178 | 181 | : 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 | 178 | 77 | : 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 | 178 | 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 | 178 | 22 | : LinearMap(List) {} |
|
179 | | |
180 | | template <typename InputIt> |
181 | 30 | CallDescriptionMap(InputIt First, InputIt Last) : LinearMap(First, Last) {} |
182 | | |
183 | 1.75k | ~CallDescriptionMap() = default; CStringChecker.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::CStringChecker::*)(clang::ento::CheckerContext&, clang::CallExpr const*) const>::~CallDescriptionMap() Line | Count | Source | 183 | 264 | ~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 | 183 | 53 | ~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 | 183 | 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 | 183 | 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 | 183 | 21 | ~CallDescriptionMap() = default; |
DebugContainerModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::DebugContainerModeling::*)(clang::CallExpr const*, clang::ento::CheckerContext&) const>::~CallDescriptionMap() Line | Count | Source | 183 | 13 | ~CallDescriptionMap() = default; |
DebugIteratorModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::DebugIteratorModeling::*)(clang::CallExpr const*, clang::ento::CheckerContext&) const>::~CallDescriptionMap() Line | Count | Source | 183 | 11 | ~CallDescriptionMap() = default; |
clang::ento::CallDescriptionMap<bool>::~CallDescriptionMap() Line | Count | Source | 183 | 181 | ~CallDescriptionMap() = default; |
clang::ento::CallDescriptionMap<std::__1::function<void (clang::ento::CheckerContext&, clang::ento::CallEvent const&)> >::~CallDescriptionMap() Line | Count | Source | 183 | 6 | ~CallDescriptionMap() = default; |
GenericTaintChecker.cpp:clang::ento::CallDescriptionMap<(anonymous namespace)::GenericTaintRule>::~CallDescriptionMap() Line | Count | Source | 183 | 74 | ~CallDescriptionMap() = default; |
InvalidPtrChecker.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::InvalidPtrChecker::*)(clang::ento::CallEvent const&, clang::ento::CheckerContext&) const>::~CallDescriptionMap() Line | Count | Source | 183 | 14 | ~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 | 183 | 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 | 183 | 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 | 183 | 723 | ~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 | 183 | 231 | ~CallDescriptionMap() = default; |
SmartPtrModeling.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::SmartPtrModeling::*)(clang::ento::CallEvent const&, clang::ento::CheckerContext&) const>::~CallDescriptionMap() Line | Count | Source | 183 | 77 | ~CallDescriptionMap() = default; |
STLAlgorithmModeling.cpp:clang::ento::CallDescriptionMap<bool ((anonymous namespace)::STLAlgorithmModeling::*)(clang::ento::CheckerContext&, clang::CallExpr const*) const>::~CallDescriptionMap() Line | Count | Source | 183 | 2 | ~CallDescriptionMap() = default; |
StreamChecker.cpp:clang::ento::CallDescriptionMap<(anonymous namespace)::FnDescription>::~CallDescriptionMap() Line | Count | Source | 183 | 22 | ~CallDescriptionMap() = default; |
|
184 | | |
185 | | // These maps are usually stored once per checker, so let's make sure |
186 | | // we don't do redundant copies. |
187 | | CallDescriptionMap(const CallDescriptionMap &) = delete; |
188 | | CallDescriptionMap &operator=(const CallDescription &) = delete; |
189 | | |
190 | 22 | CallDescriptionMap(CallDescriptionMap &&) = default; |
191 | 0 | CallDescriptionMap &operator=(CallDescriptionMap &&) = default; |
192 | | |
193 | 193k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { |
194 | | // Slow path: linear lookup. |
195 | | // TODO: Implement some sort of fast path. |
196 | 193k | for (const std::pair<CallDescription, T> &I : LinearMap) |
197 | 2.02M | if (I.first.matches(Call)) |
198 | 13.1k | return &I.second; |
199 | | |
200 | 180k | return nullptr; |
201 | 193k | } 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 | 193 | 19.9k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 19.9k | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 453k | if (I.first.matches(Call)) | 198 | 2.08k | return &I.second; | 199 | | | 200 | 17.8k | return nullptr; | 201 | 19.9k | } |
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 | 193 | 590 | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 590 | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 3.69k | if (I.first.matches(Call)) | 198 | 317 | return &I.second; | 199 | | | 200 | 273 | return nullptr; | 201 | 590 | } |
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 | 193 | 3.28k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 3.28k | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 25.5k | if (I.first.matches(Call)) | 198 | 187 | return &I.second; | 199 | | | 200 | 3.09k | return nullptr; | 201 | 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 | 193 | 3.09k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 3.09k | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 11.7k | if (I.first.matches(Call)) | 198 | 326 | return &I.second; | 199 | | | 200 | 2.76k | return nullptr; | 201 | 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 | 193 | 2.76k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 2.76k | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 5.53k | if (I.first.matches(Call)) | 198 | 8 | return &I.second; | 199 | | | 200 | 2.76k | return nullptr; | 201 | 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 | 193 | 10.6k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 10.6k | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 20.7k | if (I.first.matches(Call)) | 198 | 1.08k | return &I.second; | 199 | | | 200 | 9.52k | return nullptr; | 201 | 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 | 193 | 10.5k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 10.5k | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 28.8k | if (I.first.matches(Call)) | 198 | 2.68k | return &I.second; | 199 | | | 200 | 7.90k | return nullptr; | 201 | 10.5k | } |
clang::ento::CallDescriptionMap<std::__1::function<void (clang::ento::CheckerContext&, clang::ento::CallEvent const&)> >::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 193 | 258 | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 258 | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 1.18k | if (I.first.matches(Call)) | 198 | 122 | return &I.second; | 199 | | | 200 | 136 | return nullptr; | 201 | 258 | } |
GenericTaintChecker.cpp:clang::ento::CallDescriptionMap<(anonymous namespace)::GenericTaintRule>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 193 | 3.56k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 3.56k | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 235k | if (I.first.matches(Call)) | 198 | 1.53k | return &I.second; | 199 | | | 200 | 2.02k | return nullptr; | 201 | 3.56k | } |
InvalidPtrChecker.cpp:clang::ento::CallDescriptionMap<void ((anonymous namespace)::InvalidPtrChecker::*)(clang::ento::CallEvent const&, clang::ento::CheckerContext&) const>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 193 | 194 | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 194 | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 782 | if (I.first.matches(Call)) | 198 | 59 | return &I.second; | 199 | | | 200 | 135 | return nullptr; | 201 | 194 | } |
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 | 193 | 16.0k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 16.0k | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 47.9k | if (I.first.matches(Call)) | 198 | 248 | return &I.second; | 199 | | | 200 | 15.8k | return nullptr; | 201 | 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 | 193 | 1.39k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 1.39k | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 3.89k | if (I.first.matches(Call)) | 198 | 228 | return &I.second; | 199 | | | 200 | 1.17k | return nullptr; | 201 | 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 | 193 | 111k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 111k | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 1.06M | if (I.first.matches(Call)) | 198 | 2.66k | return &I.second; | 199 | | | 200 | 109k | return nullptr; | 201 | 111k | } |
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 | 193 | 5.69k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 5.69k | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 71.1k | if (I.first.matches(Call)) | 198 | 521 | return &I.second; | 199 | | | 200 | 5.17k | return nullptr; | 201 | 5.69k | } |
clang::ento::CallDescriptionMap<bool>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 193 | 1.89k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 1.89k | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 10.0k | if (I.first.matches(Call)) | 198 | 338 | return &I.second; | 199 | | | 200 | 1.56k | return nullptr; | 201 | 1.89k | } |
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 | 193 | 155 | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 155 | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 485 | if (I.first.matches(Call)) | 198 | 97 | return &I.second; | 199 | | | 200 | 58 | return nullptr; | 201 | 155 | } |
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 | 193 | 1.23k | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 1.23k | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 27.9k | if (I.first.matches(Call)) | 198 | 54 | return &I.second; | 199 | | | 200 | 1.18k | return nullptr; | 201 | 1.23k | } |
StreamChecker.cpp:clang::ento::CallDescriptionMap<(anonymous namespace)::FnDescription>::lookup(clang::ento::CallEvent const&) const Line | Count | Source | 193 | 795 | LLVM_NODISCARD const T *lookup(const CallEvent &Call) const { | 194 | | // Slow path: linear lookup. | 195 | | // TODO: Implement some sort of fast path. | 196 | 795 | for (const std::pair<CallDescription, T> &I : LinearMap) | 197 | 6.46k | if (I.first.matches(Call)) | 198 | 576 | return &I.second; | 199 | | | 200 | 219 | return nullptr; | 201 | 795 | } |
|
202 | | |
203 | | /// When available, always prefer lookup with a CallEvent! This function |
204 | | /// exists only when that is not available, for example, when _only_ |
205 | | /// syntactic check is done on a piece of code. |
206 | | /// |
207 | | /// Also, StdLibraryFunctionsChecker::Signature is likely a better candicade |
208 | | /// for syntactic only matching if you are writing a new checker. This is |
209 | | /// handy if a CallDescriptionMap is already there. |
210 | | /// |
211 | | /// The function is imprecise because CallEvent may know path sensitive |
212 | | /// information, such as the precise argument count (see comments for |
213 | | /// CallEvent::getNumArgs), the called function if it was called through a |
214 | | /// function pointer, and other information not available syntactically. |
215 | 80 | LLVM_NODISCARD const T *lookupAsWritten(const CallExpr &Call) const { |
216 | | // Slow path: linear lookup. |
217 | | // TODO: Implement some sort of fast path. |
218 | 80 | for (const std::pair<CallDescription, T> &I : LinearMap) |
219 | 379 | if (I.first.matchesAsWritten(Call)) |
220 | 4 | return &I.second; |
221 | | |
222 | 76 | return nullptr; |
223 | 80 | } MallocChecker.cpp:clang::ento::CallDescriptionMap<std::__1::function<void ((anonymous namespace)::MallocChecker const*, clang::ento::CallEvent const&, clang::ento::CheckerContext&)> >::lookupAsWritten(clang::CallExpr const&) const Line | Count | Source | 215 | 78 | LLVM_NODISCARD const T *lookupAsWritten(const CallExpr &Call) const { | 216 | | // Slow path: linear lookup. | 217 | | // TODO: Implement some sort of fast path. | 218 | 78 | for (const std::pair<CallDescription, T> &I : LinearMap) | 219 | 377 | if (I.first.matchesAsWritten(Call)) | 220 | 3 | return &I.second; | 221 | | | 222 | 75 | return nullptr; | 223 | 78 | } |
clang::ento::CallDescriptionMap<bool>::lookupAsWritten(clang::CallExpr const&) const Line | Count | Source | 215 | 2 | LLVM_NODISCARD const T *lookupAsWritten(const CallExpr &Call) const { | 216 | | // Slow path: linear lookup. | 217 | | // TODO: Implement some sort of fast path. | 218 | 2 | for (const std::pair<CallDescription, T> &I : LinearMap) | 219 | 2 | if (I.first.matchesAsWritten(Call)) | 220 | 1 | return &I.second; | 221 | | | 222 | 1 | return nullptr; | 223 | 2 | } |
|
224 | | }; |
225 | | |
226 | | /// An immutable set of CallDescriptions. |
227 | | /// Checkers can efficiently decide if a given CallEvent matches any |
228 | | /// CallDescription in the set. |
229 | | class CallDescriptionSet { |
230 | | CallDescriptionMap<bool /*unused*/> Impl = {}; |
231 | | |
232 | | public: |
233 | | CallDescriptionSet(std::initializer_list<CallDescription> &&List); |
234 | | |
235 | | CallDescriptionSet(const CallDescriptionSet &) = delete; |
236 | | CallDescriptionSet &operator=(const CallDescription &) = delete; |
237 | | |
238 | | LLVM_NODISCARD bool contains(const CallEvent &Call) const; |
239 | | |
240 | | /// When available, always prefer lookup with a CallEvent! This function |
241 | | /// exists only when that is not available, for example, when _only_ |
242 | | /// syntactic check is done on a piece of code. |
243 | | /// |
244 | | /// Also, StdLibraryFunctionsChecker::Signature is likely a better candicade |
245 | | /// for syntactic only matching if you are writing a new checker. This is |
246 | | /// handy if a CallDescriptionMap is already there. |
247 | | /// |
248 | | /// The function is imprecise because CallEvent may know path sensitive |
249 | | /// information, such as the precise argument count (see comments for |
250 | | /// CallEvent::getNumArgs), the called function if it was called through a |
251 | | /// function pointer, and other information not available syntactically. |
252 | | LLVM_NODISCARD bool containsAsWritten(const CallExpr &CE) const; |
253 | | }; |
254 | | |
255 | | } // namespace ento |
256 | | } // namespace clang |
257 | | |
258 | | #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLDESCRIPTION_H |