/src/cppcheck/lib/library.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Cppcheck - A tool for static C/C++ code analysis |
3 | | * Copyright (C) 2007-2023 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 | | //--------------------------------------------------------------------------- |
20 | | #ifndef libraryH |
21 | | #define libraryH |
22 | | //--------------------------------------------------------------------------- |
23 | | |
24 | | #include "config.h" |
25 | | #include "mathlib.h" |
26 | | #include "errortypes.h" |
27 | | #include "standards.h" |
28 | | |
29 | | #include <cstddef> |
30 | | #include <map> |
31 | | #include <memory> |
32 | | #include <set> |
33 | | #include <string> |
34 | | #include <unordered_map> |
35 | | #include <unordered_set> |
36 | | #include <utility> |
37 | | #include <vector> |
38 | | |
39 | | class Token; |
40 | | class Settings; |
41 | | |
42 | | namespace tinyxml2 { |
43 | | class XMLDocument; |
44 | | class XMLElement; |
45 | | } |
46 | | |
47 | | /// @addtogroup Core |
48 | | /// @{ |
49 | | |
50 | | /** |
51 | | * @brief Library definitions handling |
52 | | */ |
53 | | class CPPCHECKLIB Library { |
54 | | // TODO: get rid of this |
55 | | friend class TestSymbolDatabase; // For testing only |
56 | | friend class TestSingleExecutorBase; // For testing only |
57 | | friend class TestThreadExecutor; // For testing only |
58 | | friend class TestProcessExecutor; // For testing only |
59 | | |
60 | | public: |
61 | 1.36k | Library() = default; |
62 | | |
63 | | enum class ErrorCode { OK, FILE_NOT_FOUND, BAD_XML, UNKNOWN_ELEMENT, MISSING_ATTRIBUTE, BAD_ATTRIBUTE_VALUE, UNSUPPORTED_FORMAT, DUPLICATE_PLATFORM_TYPE, PLATFORM_TYPE_REDEFINED }; |
64 | | |
65 | | class Error { |
66 | | public: |
67 | 0 | Error() : errorcode(ErrorCode::OK) {} |
68 | 0 | explicit Error(ErrorCode e) : errorcode(e) {} |
69 | | template<typename T> |
70 | 0 | Error(ErrorCode e, T&& r) : errorcode(e), reason(r) {} Unexecuted instantiation: Library::Error::Error<char const*>(Library::ErrorCode, char const*&&) Unexecuted instantiation: Library::Error::Error<char const*&>(Library::ErrorCode, char const*&) Unexecuted instantiation: Library::Error::Error<char const (&) [5]>(Library::ErrorCode, char const (&) [5]) Unexecuted instantiation: Library::Error::Error<char const (&) [6]>(Library::ErrorCode, char const (&) [6]) Unexecuted instantiation: Library::Error::Error<char const (&) [4]>(Library::ErrorCode, char const (&) [4]) Unexecuted instantiation: Library::Error::Error<char const (&) [7]>(Library::ErrorCode, char const (&) [7]) Unexecuted instantiation: Library::Error::Error<char const (&) [3]>(Library::ErrorCode, char const (&) [3]) Unexecuted instantiation: Library::Error::Error<char const* const&>(Library::ErrorCode, char const* const&) Unexecuted instantiation: Library::Error::Error<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&>(Library::ErrorCode, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) Unexecuted instantiation: Library::Error::Error<char const (&) [11]>(Library::ErrorCode, char const (&) [11]) Unexecuted instantiation: Library::Error::Error<char const (&) [9]>(Library::ErrorCode, char const (&) [9]) Unexecuted instantiation: Library::Error::Error<char const (&) [42]>(Library::ErrorCode, char const (&) [42]) |
71 | | ErrorCode errorcode; |
72 | | std::string reason; |
73 | | }; |
74 | | |
75 | | Error load(const char exename[], const char path[]); |
76 | | Error load(const tinyxml2::XMLDocument &doc); |
77 | | |
78 | | /** this is used for unit tests */ |
79 | | bool loadxmldata(const char xmldata[], std::size_t len); |
80 | | |
81 | | struct AllocFunc { |
82 | | int groupId; |
83 | | int arg; |
84 | | enum class BufferSize {none,malloc,calloc,strdup}; |
85 | | BufferSize bufferSize; |
86 | | int bufferSizeArg1; |
87 | | int bufferSizeArg2; |
88 | | int reallocArg; |
89 | | bool initData; |
90 | | }; |
91 | | |
92 | | /** get allocation info for function */ |
93 | | const AllocFunc* getAllocFuncInfo(const Token *tok) const; |
94 | | |
95 | | /** get deallocation info for function */ |
96 | | const AllocFunc* getDeallocFuncInfo(const Token *tok) const; |
97 | | |
98 | | /** get reallocation info for function */ |
99 | | const AllocFunc* getReallocFuncInfo(const Token *tok) const; |
100 | | |
101 | | /** get allocation id for function */ |
102 | | int getAllocId(const Token *tok, int arg) const; |
103 | | |
104 | | /** get deallocation id for function */ |
105 | | int getDeallocId(const Token *tok, int arg) const; |
106 | | |
107 | | /** get reallocation id for function */ |
108 | | int getReallocId(const Token *tok, int arg) const; |
109 | | |
110 | | // TODO: get rid of this |
111 | | /** get allocation info for function by name (deprecated, use other alloc) */ |
112 | 0 | const AllocFunc* getAllocFuncInfo(const char name[]) const { |
113 | 0 | return getAllocDealloc(mAlloc, name); |
114 | 0 | } |
115 | | |
116 | | // TODO: get rid of this |
117 | | /** get deallocation info for function by name (deprecated, use other alloc) */ |
118 | 0 | const AllocFunc* getDeallocFuncInfo(const char name[]) const { |
119 | 0 | return getAllocDealloc(mDealloc, name); |
120 | 0 | } |
121 | | |
122 | | // TODO: get rid of this |
123 | | /** get allocation id for function by name (deprecated, use other alloc) */ |
124 | | // cppcheck-suppress unusedFunction |
125 | 0 | int allocId(const char name[]) const { |
126 | 0 | const AllocFunc* af = getAllocDealloc(mAlloc, name); |
127 | 0 | return af ? af->groupId : 0; |
128 | 0 | } |
129 | | |
130 | | // TODO: get rid of this |
131 | | /** get deallocation id for function by name (deprecated, use other alloc) */ |
132 | 0 | int deallocId(const char name[]) const { |
133 | 0 | const AllocFunc* af = getAllocDealloc(mDealloc, name); |
134 | 0 | return af ? af->groupId : 0; |
135 | 0 | } |
136 | | |
137 | | /** set allocation id for function */ |
138 | | // cppcheck-suppress unusedFunction - test-only |
139 | 0 | void setalloc(const std::string &functionname, int id, int arg) { |
140 | 0 | mAlloc[functionname].groupId = id; |
141 | 0 | mAlloc[functionname].arg = arg; |
142 | 0 | } |
143 | | |
144 | | // cppcheck-suppress unusedFunction - test-only |
145 | 0 | void setdealloc(const std::string &functionname, int id, int arg) { |
146 | 0 | mDealloc[functionname].groupId = id; |
147 | 0 | mDealloc[functionname].arg = arg; |
148 | 0 | } |
149 | | |
150 | | // cppcheck-suppress unusedFunction - test-only |
151 | 0 | void setrealloc(const std::string &functionname, int id, int arg, int reallocArg = 1) { |
152 | 0 | mRealloc[functionname].groupId = id; |
153 | 0 | mRealloc[functionname].arg = arg; |
154 | 0 | mRealloc[functionname].reallocArg = reallocArg; |
155 | 0 | } |
156 | | |
157 | | /** add noreturn function setting */ |
158 | | // cppcheck-suppress unusedFunction - test-only |
159 | 0 | void setnoreturn(const std::string& funcname, bool noreturn) { |
160 | 0 | mNoReturn[funcname] = noreturn ? FalseTrueMaybe::True : FalseTrueMaybe::False; |
161 | 0 | } |
162 | | |
163 | | static bool isCompliantValidationExpression(const char* p); |
164 | | |
165 | | /** is allocation type memory? */ |
166 | 0 | static bool ismemory(const int id) { |
167 | 0 | return ((id > 0) && ((id & 1) == 0)); |
168 | 0 | } |
169 | 0 | static bool ismemory(const AllocFunc* const func) { |
170 | 0 | return func && (func->groupId > 0) && ((func->groupId & 1) == 0); |
171 | 0 | } |
172 | | |
173 | | /** is allocation type resource? */ |
174 | 0 | static bool isresource(const int id) { |
175 | 0 | return ((id > 0) && ((id & 1) == 1)); |
176 | 0 | } |
177 | 0 | static bool isresource(const AllocFunc* const func) { |
178 | 0 | return func && (func->groupId > 0) && ((func->groupId & 1) == 1); |
179 | 0 | } |
180 | | |
181 | | bool formatstr_function(const Token* ftok) const; |
182 | | int formatstr_argno(const Token* ftok) const; |
183 | | bool formatstr_scan(const Token* ftok) const; |
184 | | bool formatstr_secure(const Token* ftok) const; |
185 | | |
186 | | struct NonOverlappingData { |
187 | | int ptr1Arg; |
188 | | int ptr2Arg; |
189 | | int sizeArg; |
190 | | int strlenArg; |
191 | | }; |
192 | | const NonOverlappingData* getNonOverlappingData(const Token *ftok) const; |
193 | | |
194 | | struct WarnInfo { |
195 | | std::string message; |
196 | | Standards standards; |
197 | | Severity::SeverityType severity; |
198 | | }; |
199 | | std::map<std::string, WarnInfo> functionwarn; |
200 | | |
201 | | const WarnInfo* getWarnInfo(const Token* ftok) const; |
202 | | |
203 | | // returns true if ftok is not a library function |
204 | | bool isNotLibraryFunction(const Token *ftok) const; |
205 | | bool matchArguments(const Token *ftok, const std::string &functionName) const; |
206 | | |
207 | | enum class UseRetValType { NONE, DEFAULT, ERROR_CODE }; |
208 | | UseRetValType getUseRetValType(const Token* ftok) const; |
209 | | |
210 | | const std::string& returnValue(const Token *ftok) const; |
211 | | const std::string& returnValueType(const Token *ftok) const; |
212 | | int returnValueContainer(const Token *ftok) const; |
213 | | std::vector<MathLib::bigint> unknownReturnValues(const Token *ftok) const; |
214 | | |
215 | | bool isnoreturn(const Token *ftok) const; |
216 | | bool isnotnoreturn(const Token *ftok) const; |
217 | | |
218 | | bool isScopeNoReturn(const Token *end, std::string *unknownFunc) const; |
219 | | |
220 | | class Container { |
221 | | public: |
222 | 0 | Container() = default; |
223 | | |
224 | | enum class Action { |
225 | | RESIZE, |
226 | | CLEAR, |
227 | | PUSH, |
228 | | POP, |
229 | | FIND, |
230 | | INSERT, |
231 | | ERASE, |
232 | | CHANGE_CONTENT, |
233 | | CHANGE, |
234 | | CHANGE_INTERNAL, |
235 | | NO_ACTION |
236 | | }; |
237 | | enum class Yield { |
238 | | AT_INDEX, |
239 | | ITEM, |
240 | | BUFFER, |
241 | | BUFFER_NT, |
242 | | START_ITERATOR, |
243 | | END_ITERATOR, |
244 | | ITERATOR, |
245 | | SIZE, |
246 | | EMPTY, |
247 | | NO_YIELD |
248 | | }; |
249 | | struct Function { |
250 | | Action action; |
251 | | Yield yield; |
252 | | std::string returnType; |
253 | | }; |
254 | | struct RangeItemRecordTypeItem { |
255 | | std::string name; |
256 | | int templateParameter; // TODO: use this |
257 | | }; |
258 | | std::string startPattern, startPattern2, endPattern, itEndPattern; |
259 | | std::map<std::string, Function> functions; |
260 | | int type_templateArgNo = -1; |
261 | | std::vector<RangeItemRecordTypeItem> rangeItemRecordType; |
262 | | int size_templateArgNo = -1; |
263 | | bool arrayLike_indexOp{}; |
264 | | bool stdStringLike{}; |
265 | | bool stdAssociativeLike{}; |
266 | | bool opLessAllowed = true; |
267 | | bool hasInitializerListConstructor{}; |
268 | | bool unstableErase{}; |
269 | | bool unstableInsert{}; |
270 | | bool view{}; |
271 | | |
272 | 0 | Action getAction(const std::string& function) const { |
273 | 0 | const std::map<std::string, Function>::const_iterator i = functions.find(function); |
274 | 0 | if (i != functions.end()) |
275 | 0 | return i->second.action; |
276 | 0 | return Action::NO_ACTION; |
277 | 0 | } |
278 | | |
279 | 0 | Yield getYield(const std::string& function) const { |
280 | 0 | const std::map<std::string, Function>::const_iterator i = functions.find(function); |
281 | 0 | if (i != functions.end()) |
282 | 0 | return i->second.yield; |
283 | 0 | return Yield::NO_YIELD; |
284 | 0 | } |
285 | | |
286 | 0 | const std::string& getReturnType(const std::string& function) const { |
287 | 0 | auto i = functions.find(function); |
288 | 0 | return (i != functions.end()) ? i->second.returnType : emptyString; |
289 | 0 | } |
290 | | |
291 | | static Yield yieldFrom(const std::string& yieldName); |
292 | | static Action actionFrom(const std::string& actionName); |
293 | | }; |
294 | | std::unordered_map<std::string, Container> containers; |
295 | | const Container* detectContainer(const Token* typeStart) const; |
296 | | const Container* detectIterator(const Token* typeStart) const; |
297 | | const Container* detectContainerOrIterator(const Token* typeStart, bool* isIterator = nullptr, bool withoutStd = false) const; |
298 | | |
299 | | struct ArgumentChecks { |
300 | | bool notbool{}; |
301 | | bool notnull{}; |
302 | | int notuninit = -1; |
303 | | bool formatstr{}; |
304 | | bool strz{}; |
305 | | bool optional{}; |
306 | | bool variadic{}; |
307 | | std::string valid; |
308 | | |
309 | | struct IteratorInfo { |
310 | | int container{}; |
311 | | bool it{}; |
312 | | bool first{}; |
313 | | bool last{}; |
314 | | }; |
315 | | IteratorInfo iteratorInfo; |
316 | | |
317 | | struct MinSize { |
318 | | enum class Type { NONE, STRLEN, ARGVALUE, SIZEOF, MUL, VALUE }; |
319 | 0 | MinSize(Type t, int a) : type(t), arg(a) {} |
320 | | Type type; |
321 | | int arg; |
322 | | int arg2 = 0; |
323 | | long long value = 0; |
324 | | std::string baseType; |
325 | | }; |
326 | | std::vector<MinSize> minsizes; |
327 | | |
328 | | enum class Direction { |
329 | | DIR_IN, ///< Input to called function. Data is treated as read-only. |
330 | | DIR_OUT, ///< Output to caller. Data is passed by reference or address and is potentially written. |
331 | | DIR_INOUT, ///< Input to called function, and output to caller. Data is passed by reference or address and is potentially modified. |
332 | | DIR_UNKNOWN ///< direction not known / specified |
333 | | }; |
334 | | Direction direction = Direction::DIR_UNKNOWN; |
335 | | }; |
336 | | |
337 | | struct Function { |
338 | | std::map<int, ArgumentChecks> argumentChecks; // argument nr => argument data |
339 | | bool use{}; |
340 | | bool leakignore{}; |
341 | | bool isconst{}; |
342 | | bool ispure{}; |
343 | | UseRetValType useretval = UseRetValType::NONE; |
344 | | bool ignore{}; // ignore functions/macros from a library (gtk, qt etc) |
345 | | bool formatstr{}; |
346 | | bool formatstr_scan{}; |
347 | | bool formatstr_secure{}; |
348 | | Container::Action containerAction = Container::Action::NO_ACTION; |
349 | | Container::Yield containerYield = Container::Yield::NO_YIELD; |
350 | | std::string returnType; |
351 | | }; |
352 | | |
353 | | const Function *getFunction(const Token *ftok) const; |
354 | | std::unordered_map<std::string, Function> functions; |
355 | | bool isUse(const std::string& functionName) const; |
356 | | bool isLeakIgnore(const std::string& functionName) const; |
357 | | bool isFunctionConst(const std::string& functionName, bool pure) const; |
358 | | bool isFunctionConst(const Token *ftok) const; |
359 | | |
360 | 1.03k | bool isboolargbad(const Token *ftok, int argnr) const { |
361 | 1.03k | const ArgumentChecks *arg = getarg(ftok, argnr); |
362 | 1.03k | return arg && arg->notbool; |
363 | 1.03k | } |
364 | | |
365 | | bool isnullargbad(const Token *ftok, int argnr) const; |
366 | | bool isuninitargbad(const Token *ftok, int argnr, int indirect = 0, bool *hasIndirect=nullptr) const; |
367 | | |
368 | 0 | bool isargformatstr(const Token *ftok, int argnr) const { |
369 | 0 | const ArgumentChecks *arg = getarg(ftok, argnr); |
370 | 0 | return arg && arg->formatstr; |
371 | 0 | } |
372 | | |
373 | 1.38k | bool isargstrz(const Token *ftok, int argnr) const { |
374 | 1.38k | const ArgumentChecks *arg = getarg(ftok, argnr); |
375 | 1.38k | return arg && arg->strz; |
376 | 1.38k | } |
377 | | |
378 | | bool isIntArgValid(const Token *ftok, int argnr, const MathLib::bigint argvalue) const; |
379 | | bool isFloatArgValid(const Token *ftok, int argnr, double argvalue) const; |
380 | | |
381 | 0 | const std::string& validarg(const Token *ftok, int argnr) const { |
382 | 0 | const ArgumentChecks *arg = getarg(ftok, argnr); |
383 | 0 | return arg ? arg->valid : emptyString; |
384 | 0 | } |
385 | | |
386 | 1.38k | const ArgumentChecks::IteratorInfo *getArgIteratorInfo(const Token *ftok, int argnr) const { |
387 | 1.38k | const ArgumentChecks *arg = getarg(ftok, argnr); |
388 | 1.38k | return arg && arg->iteratorInfo.it ? &arg->iteratorInfo : nullptr; |
389 | 1.38k | } |
390 | | |
391 | | bool hasminsize(const Token *ftok) const; |
392 | | |
393 | 0 | const std::vector<ArgumentChecks::MinSize> *argminsizes(const Token *ftok, int argnr) const { |
394 | 0 | const ArgumentChecks *arg = getarg(ftok, argnr); |
395 | 0 | return arg ? &arg->minsizes : nullptr; |
396 | 0 | } |
397 | | |
398 | | ArgumentChecks::Direction getArgDirection(const Token* ftok, int argnr) const; |
399 | | |
400 | | bool markupFile(const std::string &path) const; |
401 | | |
402 | | bool processMarkupAfterCode(const std::string &path) const; |
403 | | |
404 | 0 | const std::set<std::string> &markupExtensions() const { |
405 | 0 | return mMarkupExtensions; |
406 | 0 | } |
407 | | |
408 | | bool reportErrors(const std::string &path) const; |
409 | | |
410 | | bool ignorefunction(const std::string &functionName) const; |
411 | | |
412 | | bool isexecutableblock(const std::string &file, const std::string &token) const; |
413 | | |
414 | | int blockstartoffset(const std::string &file) const; |
415 | | |
416 | | const std::string& blockstart(const std::string &file) const; |
417 | | const std::string& blockend(const std::string &file) const; |
418 | | |
419 | | bool iskeyword(const std::string &file, const std::string &keyword) const; |
420 | | |
421 | 92.2k | bool isexporter(const std::string &prefix) const { |
422 | 92.2k | return mExporters.find(prefix) != mExporters.end(); |
423 | 92.2k | } |
424 | | |
425 | 0 | bool isexportedprefix(const std::string &prefix, const std::string &token) const { |
426 | 0 | const std::map<std::string, ExportedFunctions>::const_iterator it = mExporters.find(prefix); |
427 | 0 | return (it != mExporters.end() && it->second.isPrefix(token)); |
428 | 0 | } |
429 | | |
430 | 0 | bool isexportedsuffix(const std::string &prefix, const std::string &token) const { |
431 | 0 | const std::map<std::string, ExportedFunctions>::const_iterator it = mExporters.find(prefix); |
432 | 0 | return (it != mExporters.end() && it->second.isSuffix(token)); |
433 | 0 | } |
434 | | |
435 | | bool isimporter(const std::string& file, const std::string &importer) const; |
436 | | |
437 | | const Token* getContainerFromYield(const Token* tok, Container::Yield yield) const; |
438 | | const Token* getContainerFromAction(const Token* tok, Container::Action action) const; |
439 | | |
440 | 92.2k | bool isreflection(const std::string &token) const { |
441 | 92.2k | return mReflection.find(token) != mReflection.end(); |
442 | 92.2k | } |
443 | | |
444 | 0 | int reflectionArgument(const std::string &token) const { |
445 | 0 | const std::map<std::string, int>::const_iterator it = mReflection.find(token); |
446 | 0 | if (it != mReflection.end()) |
447 | 0 | return it->second; |
448 | 0 | return -1; |
449 | 0 | } |
450 | | |
451 | 1.73k | bool isentrypoint(const std::string &func) const { |
452 | 1.73k | return func == "main" || mEntrypoints.find(func) != mEntrypoints.end(); |
453 | 1.73k | } |
454 | | |
455 | | std::vector<std::string> defines; // to provide some library defines |
456 | | |
457 | | struct SmartPointer { |
458 | | std::string name; |
459 | | bool unique = false; |
460 | | }; |
461 | | |
462 | | std::unordered_map<std::string, SmartPointer> smartPointers; |
463 | | bool isSmartPointer(const Token *tok) const; |
464 | | const SmartPointer* detectSmartPointer(const Token* tok, bool withoutStd = false) const; |
465 | | |
466 | | struct PodType { |
467 | | unsigned int size; |
468 | | char sign; |
469 | | enum class Type { NO, BOOL, CHAR, SHORT, INT, LONG, LONGLONG } stdtype; |
470 | | }; |
471 | 34.1k | const struct PodType *podtype(const std::string &name) const { |
472 | 34.1k | const std::unordered_map<std::string, struct PodType>::const_iterator it = mPodTypes.find(name); |
473 | 34.1k | return (it != mPodTypes.end()) ? &(it->second) : nullptr; |
474 | 34.1k | } |
475 | | |
476 | | struct PlatformType { |
477 | 0 | bool operator == (const PlatformType & type) const { |
478 | 0 | return (mSigned == type.mSigned && |
479 | 0 | mUnsigned == type.mUnsigned && |
480 | 0 | mLong == type.mLong && |
481 | 0 | mPointer == type.mPointer && |
482 | 0 | mPtrPtr == type.mPtrPtr && |
483 | 0 | mConstPtr == type.mConstPtr && |
484 | 0 | mType == type.mType); |
485 | 0 | } |
486 | 0 | bool operator != (const PlatformType & type) const { |
487 | 0 | return !(*this == type); |
488 | 0 | } |
489 | | std::string mType; |
490 | | bool mSigned{}; |
491 | | bool mUnsigned{}; |
492 | | bool mLong{}; |
493 | | bool mPointer{}; |
494 | | bool mPtrPtr{}; |
495 | | bool mConstPtr{}; |
496 | | }; |
497 | | |
498 | | struct Platform { |
499 | 0 | const PlatformType *platform_type(const std::string &name) const { |
500 | 0 | const std::map<std::string, struct PlatformType>::const_iterator it = mPlatformTypes.find(name); |
501 | 0 | return (it != mPlatformTypes.end()) ? &(it->second) : nullptr; |
502 | 0 | } |
503 | | std::map<std::string, PlatformType> mPlatformTypes; |
504 | | }; |
505 | | |
506 | 43.3k | const PlatformType *platform_type(const std::string &name, const std::string & platform) const { |
507 | 43.3k | const std::map<std::string, Platform>::const_iterator it = mPlatforms.find(platform); |
508 | 43.3k | if (it != mPlatforms.end()) { |
509 | 0 | const PlatformType * const type = it->second.platform_type(name); |
510 | 0 | if (type) |
511 | 0 | return type; |
512 | 0 | } |
513 | | |
514 | 43.3k | const std::map<std::string, PlatformType>::const_iterator it2 = mPlatformTypes.find(name); |
515 | 43.3k | return (it2 != mPlatformTypes.end()) ? &(it2->second) : nullptr; |
516 | 43.3k | } |
517 | | |
518 | | /** |
519 | | * Get function name for function call |
520 | | */ |
521 | | std::string getFunctionName(const Token *ftok) const; |
522 | | |
523 | | static bool isContainerYield(const Token * const cond, Library::Container::Yield y, const std::string& fallback=emptyString); |
524 | | |
525 | | /** Suppress/check a type */ |
526 | | enum class TypeCheck { def, |
527 | | check, |
528 | | suppress, |
529 | | checkFiniteLifetime, // (unusedvar) object has side effects, but immediate destruction is wrong |
530 | | }; |
531 | | TypeCheck getTypeCheck(std::string check, std::string typeName) const; |
532 | | bool hasAnyTypeCheck(const std::string& typeName) const; |
533 | | |
534 | | private: |
535 | | // load a <function> xml node |
536 | | Error loadFunction(const tinyxml2::XMLElement * const node, const std::string &name, std::set<std::string> &unknown_elements); |
537 | | |
538 | | class ExportedFunctions { |
539 | | public: |
540 | 0 | void addPrefix(std::string prefix) { |
541 | 0 | mPrefixes.insert(std::move(prefix)); |
542 | 0 | } |
543 | 0 | void addSuffix(std::string suffix) { |
544 | 0 | mSuffixes.insert(std::move(suffix)); |
545 | 0 | } |
546 | 0 | bool isPrefix(const std::string& prefix) const { |
547 | 0 | return (mPrefixes.find(prefix) != mPrefixes.end()); |
548 | 0 | } |
549 | 0 | bool isSuffix(const std::string& suffix) const { |
550 | 0 | return (mSuffixes.find(suffix) != mSuffixes.end()); |
551 | 0 | } |
552 | | |
553 | | private: |
554 | | std::set<std::string> mPrefixes; |
555 | | std::set<std::string> mSuffixes; |
556 | | }; |
557 | | class CodeBlock { |
558 | | public: |
559 | 0 | CodeBlock() = default; |
560 | | |
561 | 0 | void setStart(const char* s) { |
562 | 0 | mStart = s; |
563 | 0 | } |
564 | 0 | void setEnd(const char* e) { |
565 | 0 | mEnd = e; |
566 | 0 | } |
567 | 0 | void setOffset(const int o) { |
568 | 0 | mOffset = o; |
569 | 0 | } |
570 | 0 | void addBlock(const char* blockName) { |
571 | 0 | mBlocks.insert(blockName); |
572 | 0 | } |
573 | 0 | const std::string& start() const { |
574 | 0 | return mStart; |
575 | 0 | } |
576 | 0 | const std::string& end() const { |
577 | 0 | return mEnd; |
578 | 0 | } |
579 | 0 | int offset() const { |
580 | 0 | return mOffset; |
581 | 0 | } |
582 | 0 | bool isBlock(const std::string& blockName) const { |
583 | 0 | return mBlocks.find(blockName) != mBlocks.end(); |
584 | 0 | } |
585 | | |
586 | | private: |
587 | | std::string mStart; |
588 | | std::string mEnd; |
589 | | int mOffset{}; |
590 | | std::set<std::string> mBlocks; |
591 | | }; |
592 | | enum class FalseTrueMaybe { False, True, Maybe }; |
593 | | int mAllocId{}; |
594 | | std::set<std::string> mFiles; |
595 | | std::map<std::string, AllocFunc> mAlloc; // allocation functions |
596 | | std::map<std::string, AllocFunc> mDealloc; // deallocation functions |
597 | | std::map<std::string, AllocFunc> mRealloc; // reallocation functions |
598 | | std::unordered_map<std::string, FalseTrueMaybe> mNoReturn; // is function noreturn? |
599 | | std::map<std::string, std::string> mReturnValue; |
600 | | std::map<std::string, std::string> mReturnValueType; |
601 | | std::map<std::string, int> mReturnValueContainer; |
602 | | std::map<std::string, std::vector<MathLib::bigint>> mUnknownReturnValues; |
603 | | std::map<std::string, bool> mReportErrors; |
604 | | std::map<std::string, bool> mProcessAfterCode; |
605 | | std::set<std::string> mMarkupExtensions; // file extensions of markup files |
606 | | std::map<std::string, std::set<std::string>> mKeywords; // keywords for code in the library |
607 | | std::unordered_map<std::string, CodeBlock> mExecutableBlocks; // keywords for blocks of executable code |
608 | | std::map<std::string, ExportedFunctions> mExporters; // keywords that export variables/functions to libraries (meta-code/macros) |
609 | | std::map<std::string, std::set<std::string>> mImporters; // keywords that import variables/functions |
610 | | std::map<std::string, int> mReflection; // invocation of reflection |
611 | | std::unordered_map<std::string, struct PodType> mPodTypes; // pod types |
612 | | std::map<std::string, PlatformType> mPlatformTypes; // platform independent typedefs |
613 | | std::map<std::string, Platform> mPlatforms; // platform dependent typedefs |
614 | | std::map<std::pair<std::string,std::string>, TypeCheck> mTypeChecks; |
615 | | std::unordered_map<std::string, NonOverlappingData> mNonOverlappingData; |
616 | | std::unordered_set<std::string> mEntrypoints; |
617 | | |
618 | | const ArgumentChecks * getarg(const Token *ftok, int argnr) const; |
619 | | |
620 | | std::string getFunctionName(const Token *ftok, bool &error) const; |
621 | | |
622 | 4.56k | static const AllocFunc* getAllocDealloc(const std::map<std::string, AllocFunc> &data, const std::string &name) { |
623 | 4.56k | const std::map<std::string, AllocFunc>::const_iterator it = data.find(name); |
624 | 4.56k | return (it == data.end()) ? nullptr : &it->second; |
625 | 4.56k | } |
626 | | |
627 | | enum DetectContainer { ContainerOnly, IteratorOnly, Both }; |
628 | | const Library::Container* detectContainerInternal(const Token* typeStart, DetectContainer detect, bool* isIterator = nullptr, bool withoutStd = false) const; |
629 | | }; |
630 | | |
631 | | CPPCHECKLIB const Library::Container * getLibraryContainer(const Token * tok); |
632 | | |
633 | | std::shared_ptr<Token> createTokenFromExpression(const std::string& returnValue, |
634 | | const Settings* settings, |
635 | | std::unordered_map<nonneg int, const Token*>* lookupVarId = nullptr); |
636 | | |
637 | | /// @} |
638 | | //--------------------------------------------------------------------------- |
639 | | #endif // libraryH |