/src/cppcheck/lib/suppressions.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- C++ -*- |
2 | | * Cppcheck - A tool for static C/C++ code analysis |
3 | | * Copyright (C) 2007-2024 Cppcheck team. |
4 | | * |
5 | | * This program is free software: you can redistribute it and/or modify |
6 | | * it under the terms of the GNU General Public License as published by |
7 | | * the Free Software Foundation, either version 3 of the License, or |
8 | | * (at your option) any later version. |
9 | | * |
10 | | * This program is distributed in the hope that it will be useful, |
11 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | * GNU General Public License for more details. |
14 | | * |
15 | | * You should have received a copy of the GNU General Public License |
16 | | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | | */ |
18 | | //--------------------------------------------------------------------------- |
19 | | #ifndef suppressionsH |
20 | | #define suppressionsH |
21 | | //--------------------------------------------------------------------------- |
22 | | |
23 | | #include "config.h" |
24 | | |
25 | | #include <cstddef> |
26 | | #include <cstdint> |
27 | | #include <istream> |
28 | | #include <list> |
29 | | #include <set> |
30 | | #include <string> |
31 | | #include <utility> |
32 | | #include <vector> |
33 | | |
34 | | /// @addtogroup Core |
35 | | /// @{ |
36 | | |
37 | | class Tokenizer; |
38 | | class ErrorMessage; |
39 | | class ErrorLogger; |
40 | | enum class Certainty : std::uint8_t; |
41 | | class FileWithDetails; |
42 | | |
43 | | /** @brief class for handling suppressions */ |
44 | | class CPPCHECKLIB SuppressionList { |
45 | | public: |
46 | | |
47 | | enum class Type : std::uint8_t { |
48 | | unique, file, block, blockBegin, blockEnd, macro |
49 | | }; |
50 | | |
51 | | struct CPPCHECKLIB ErrorMessage { |
52 | | std::size_t hash; |
53 | | std::string errorId; |
54 | | void setFileName(std::string s); |
55 | 0 | const std::string &getFileName() const { |
56 | 0 | return mFileName; |
57 | 0 | } |
58 | | int lineNumber; |
59 | | Certainty certainty; |
60 | | std::string symbolNames; |
61 | | std::set<std::string> macroNames; |
62 | | |
63 | | static SuppressionList::ErrorMessage fromErrorMessage(const ::ErrorMessage &msg, const std::set<std::string> ¯oNames); |
64 | | private: |
65 | | std::string mFileName; |
66 | | }; |
67 | | |
68 | | struct CPPCHECKLIB Suppression { |
69 | 0 | Suppression() = default; |
70 | 0 | Suppression(std::string id, std::string file, int line=NO_LINE) : errorId(std::move(id)), fileName(std::move(file)), lineNumber(line) {} |
71 | | |
72 | 0 | bool operator<(const Suppression &other) const { |
73 | 0 | if (errorId != other.errorId) |
74 | 0 | return errorId < other.errorId; |
75 | 0 | if (lineNumber < other.lineNumber) |
76 | 0 | return true; |
77 | 0 | if (fileName != other.fileName) |
78 | 0 | return fileName < other.fileName; |
79 | 0 | if (symbolName != other.symbolName) |
80 | 0 | return symbolName < other.symbolName; |
81 | 0 | if (macroName != other.macroName) |
82 | 0 | return macroName < other.macroName; |
83 | 0 | if (hash != other.hash) |
84 | 0 | return hash < other.hash; |
85 | 0 | if (thisAndNextLine != other.thisAndNextLine) |
86 | 0 | return thisAndNextLine; |
87 | 0 | return false; |
88 | 0 | } |
89 | | |
90 | 0 | bool operator==(const Suppression &other) const { |
91 | 0 | if (errorId != other.errorId) |
92 | 0 | return false; |
93 | 0 | if (lineNumber < other.lineNumber) |
94 | 0 | return false; |
95 | 0 | if (fileName != other.fileName) |
96 | 0 | return false; |
97 | 0 | if (symbolName != other.symbolName) |
98 | 0 | return false; |
99 | 0 | if (macroName != other.macroName) |
100 | 0 | return false; |
101 | 0 | if (hash != other.hash) |
102 | 0 | return false; |
103 | 0 | if (type != other.type) |
104 | 0 | return false; |
105 | 0 | if (lineBegin != other.lineBegin) |
106 | 0 | return false; |
107 | 0 | if (lineEnd != other.lineEnd) |
108 | 0 | return false; |
109 | 0 | return true; |
110 | 0 | } |
111 | | |
112 | | /** |
113 | | * Parse inline suppression in comment |
114 | | * @param comment the full comment text |
115 | | * @param errorMessage output parameter for error message (wrong suppression attribute) |
116 | | * @return true if it is a inline comment. |
117 | | */ |
118 | | bool parseComment(std::string comment, std::string *errorMessage); |
119 | | |
120 | | bool isSuppressed(const ErrorMessage &errmsg) const; |
121 | | |
122 | | bool isMatch(const ErrorMessage &errmsg); |
123 | | |
124 | | std::string getText() const; |
125 | | |
126 | 0 | bool isLocal() const { |
127 | 0 | return !fileName.empty() && fileName.find_first_of("?*") == std::string::npos; |
128 | 0 | } |
129 | | |
130 | 0 | bool isSameParameters(const Suppression &other) const { |
131 | 0 | return errorId == other.errorId && |
132 | 0 | fileName == other.fileName && |
133 | 0 | lineNumber == other.lineNumber && |
134 | 0 | symbolName == other.symbolName && |
135 | 0 | hash == other.hash && |
136 | 0 | thisAndNextLine == other.thisAndNextLine; |
137 | 0 | } |
138 | | |
139 | | std::string toString() const; |
140 | | |
141 | | std::string errorId; |
142 | | std::string fileName; |
143 | | int lineNumber = NO_LINE; |
144 | | int lineBegin = NO_LINE; |
145 | | int lineEnd = NO_LINE; |
146 | | Type type = Type::unique; |
147 | | std::string symbolName; |
148 | | std::string macroName; |
149 | | std::size_t hash{}; |
150 | | bool thisAndNextLine{}; // Special case for backwards compatibility: { // cppcheck-suppress something |
151 | | bool matched{}; |
152 | | bool checked{}; // for inline suppressions, checked or not |
153 | | |
154 | | enum : std::int8_t { NO_LINE = -1 }; |
155 | | }; |
156 | | |
157 | | /** |
158 | | * @brief Don't show errors listed in the file. |
159 | | * @param istr Open file stream where errors can be read. |
160 | | * @return error message. empty upon success |
161 | | */ |
162 | | std::string parseFile(std::istream &istr); |
163 | | |
164 | | /** |
165 | | * @brief Don't show errors listed in the file. |
166 | | * @param filename file name |
167 | | * @return error message. empty upon success |
168 | | */ |
169 | | std::string parseXmlFile(const char *filename); |
170 | | |
171 | | /** |
172 | | * Parse multi inline suppression in comment |
173 | | * @param comment the full comment text |
174 | | * @param errorMessage output parameter for error message (wrong suppression attribute) |
175 | | * @return empty vector if something wrong. |
176 | | */ |
177 | | static std::vector<Suppression> parseMultiSuppressComment(const std::string &comment, std::string *errorMessage); |
178 | | |
179 | | /** |
180 | | * @brief Don't show the given error. |
181 | | * @param line Description of error to suppress (in id:file:line format). |
182 | | * @return error message. empty upon success |
183 | | */ |
184 | | std::string addSuppressionLine(const std::string &line); |
185 | | |
186 | | /** |
187 | | * @brief Don't show this error. File and/or line are optional. In which case |
188 | | * the errorId alone is used for filtering. |
189 | | * @param suppression suppression details |
190 | | * @return error message. empty upon success |
191 | | */ |
192 | | std::string addSuppression(Suppression suppression); |
193 | | |
194 | | /** |
195 | | * @brief Combine list of suppressions into the current suppressions. |
196 | | * @param suppressions list of suppression details |
197 | | * @return error message. empty upon success |
198 | | */ |
199 | | std::string addSuppressions(std::list<Suppression> suppressions); |
200 | | |
201 | | /** |
202 | | * @brief Updates the state of the given suppression. |
203 | | * @param suppression the suppression to update |
204 | | * @return true if suppression to update was found |
205 | | */ |
206 | | bool updateSuppressionState(const SuppressionList::Suppression& suppression); |
207 | | |
208 | | /** |
209 | | * @brief Returns true if this message should not be shown to the user. |
210 | | * @param errmsg error message |
211 | | * @param global use global suppressions |
212 | | * @return true if this error is suppressed. |
213 | | */ |
214 | | bool isSuppressed(const ErrorMessage &errmsg, bool global = true); |
215 | | |
216 | | /** |
217 | | * @brief Returns true if this message is "explicitly" suppressed. The suppression "id" must match textually exactly. |
218 | | * @param errmsg error message |
219 | | * @param global use global suppressions |
220 | | * @return true if this error is explicitly suppressed. |
221 | | */ |
222 | | bool isSuppressedExplicitly(const ErrorMessage &errmsg, bool global = true); |
223 | | |
224 | | /** |
225 | | * @brief Returns true if this message should not be shown to the user. |
226 | | * @param errmsg error message |
227 | | * @return true if this error is suppressed. |
228 | | */ |
229 | | bool isSuppressed(const ::ErrorMessage &errmsg, const std::set<std::string>& macroNames); |
230 | | |
231 | | /** |
232 | | * @brief Create an xml dump of suppressions |
233 | | * @param out stream to write XML to |
234 | | */ |
235 | | void dump(std::ostream &out) const; |
236 | | |
237 | | /** |
238 | | * @brief Returns list of unmatched local (per-file) suppressions. |
239 | | * @return list of unmatched suppressions |
240 | | */ |
241 | | std::list<Suppression> getUnmatchedLocalSuppressions(const FileWithDetails &file, bool unusedFunctionChecking) const; |
242 | | |
243 | | /** |
244 | | * @brief Returns list of unmatched global (glob pattern) suppressions. |
245 | | * @return list of unmatched suppressions |
246 | | */ |
247 | | std::list<Suppression> getUnmatchedGlobalSuppressions(bool unusedFunctionChecking) const; |
248 | | |
249 | | /** |
250 | | * @brief Returns list of all suppressions. |
251 | | * @return list of suppressions |
252 | | */ |
253 | | const std::list<Suppression> &getSuppressions() const; |
254 | | |
255 | | /** |
256 | | * @brief Marks Inline Suppressions as checked if source line is in the token stream |
257 | | */ |
258 | | void markUnmatchedInlineSuppressionsAsChecked(const Tokenizer &tokenizer); |
259 | | |
260 | | /** |
261 | | * Report unmatched suppressions |
262 | | * @param unmatched list of unmatched suppressions (from Settings::Suppressions::getUnmatched(Local|Global)Suppressions) |
263 | | * @return true is returned if errors are reported |
264 | | */ |
265 | | static bool reportUnmatchedSuppressions(const std::list<SuppressionList::Suppression> &unmatched, ErrorLogger &errorLogger); |
266 | | |
267 | | private: |
268 | | /** @brief List of error which the user doesn't want to see. */ |
269 | | std::list<Suppression> mSuppressions; |
270 | | }; |
271 | | |
272 | | struct Suppressions |
273 | | { |
274 | | /** @brief suppress message (--suppressions) */ |
275 | | SuppressionList nomsg; |
276 | | /** @brief suppress exitcode */ |
277 | | SuppressionList nofail; |
278 | | }; |
279 | | |
280 | | /// @} |
281 | | //--------------------------------------------------------------------------- |
282 | | #endif // suppressionsH |