/src/cppcheck/lib/checkother.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 | | //--------------------------------------------------------------------------- |
21 | | #ifndef checkotherH |
22 | | #define checkotherH |
23 | | //--------------------------------------------------------------------------- |
24 | | |
25 | | #include "check.h" |
26 | | #include "config.h" |
27 | | #include "errortypes.h" |
28 | | #include "tokenize.h" |
29 | | |
30 | | #include <string> |
31 | | #include <vector> |
32 | | |
33 | | namespace ValueFlow { |
34 | | class Value; |
35 | | } |
36 | | |
37 | | class Settings; |
38 | | class Token; |
39 | | class Function; |
40 | | class Variable; |
41 | | class ErrorLogger; |
42 | | |
43 | | /// @addtogroup Checks |
44 | | /// @{ |
45 | | |
46 | | |
47 | | /** @brief Various small checks */ |
48 | | |
49 | | class CPPCHECKLIB CheckOther : public Check { |
50 | | friend class TestCharVar; |
51 | | friend class TestIncompleteStatement; |
52 | | friend class TestOther; |
53 | | |
54 | | public: |
55 | | /** @brief This constructor is used when registering the CheckClass */ |
56 | 2 | CheckOther() : Check(myName()) {} |
57 | | |
58 | | /** Is expression a comparison that checks if a nonzero (unsigned/pointer) expression is less than zero? */ |
59 | | static bool comparisonNonZeroExpressionLessThanZero(const Token *tok, const ValueFlow::Value **zeroValue, const Token **nonZeroExpr); |
60 | | |
61 | | /** Is expression a comparison that checks if a nonzero (unsigned/pointer) expression is positive? */ |
62 | | static bool testIfNonZeroExpressionIsPositive(const Token *tok, const ValueFlow::Value **zeroValue, const Token **nonZeroExpr); |
63 | | |
64 | | private: |
65 | | /** @brief This constructor is used when running checks. */ |
66 | | CheckOther(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) |
67 | 1.36k | : Check(myName(), tokenizer, settings, errorLogger) {} |
68 | | |
69 | | |
70 | | /** @brief Run checks against the normal token list */ |
71 | 1.36k | void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override { |
72 | 1.36k | CheckOther checkOther(&tokenizer, tokenizer.getSettings(), errorLogger); |
73 | | |
74 | | // Checks |
75 | 1.36k | checkOther.warningOldStylePointerCast(); |
76 | 1.36k | checkOther.invalidPointerCast(); |
77 | 1.36k | checkOther.checkCharVariable(); |
78 | 1.36k | checkOther.checkRedundantAssignment(); |
79 | 1.36k | checkOther.redundantBitwiseOperationInSwitchError(); |
80 | 1.36k | checkOther.checkSuspiciousCaseInSwitch(); |
81 | 1.36k | checkOther.checkDuplicateBranch(); |
82 | 1.36k | checkOther.checkDuplicateExpression(); |
83 | 1.36k | checkOther.checkUnreachableCode(); |
84 | 1.36k | checkOther.checkSuspiciousSemicolon(); |
85 | 1.36k | checkOther.checkVariableScope(); |
86 | 1.36k | checkOther.checkSignOfUnsignedVariable(); // don't ignore casts (#3574) |
87 | 1.36k | checkOther.checkIncompleteArrayFill(); |
88 | 1.36k | checkOther.checkVarFuncNullUB(); |
89 | 1.36k | checkOther.checkNanInArithmeticExpression(); |
90 | 1.36k | checkOther.checkCommaSeparatedReturn(); |
91 | 1.36k | checkOther.checkRedundantPointerOp(); |
92 | 1.36k | checkOther.checkZeroDivision(); |
93 | 1.36k | checkOther.checkNegativeBitwiseShift(); |
94 | 1.36k | checkOther.checkInterlockedDecrement(); |
95 | 1.36k | checkOther.checkUnusedLabel(); |
96 | 1.36k | checkOther.checkEvaluationOrder(); |
97 | 1.36k | checkOther.checkFuncArgNamesDifferent(); |
98 | 1.36k | checkOther.checkShadowVariables(); |
99 | 1.36k | checkOther.checkKnownArgument(); |
100 | 1.36k | checkOther.checkKnownPointerToBool(); |
101 | 1.36k | checkOther.checkComparePointers(); |
102 | 1.36k | checkOther.checkIncompleteStatement(); |
103 | 1.36k | checkOther.checkRedundantCopy(); |
104 | 1.36k | checkOther.clarifyCalculation(); |
105 | 1.36k | checkOther.checkPassByReference(); |
106 | 1.36k | checkOther.checkConstVariable(); |
107 | 1.36k | checkOther.checkConstPointer(); |
108 | 1.36k | checkOther.checkComparisonFunctionIsAlwaysTrueOrFalse(); |
109 | 1.36k | checkOther.checkInvalidFree(); |
110 | 1.36k | checkOther.clarifyStatement(); |
111 | 1.36k | checkOther.checkCastIntToCharAndBack(); |
112 | 1.36k | checkOther.checkMisusedScopedObject(); |
113 | 1.36k | checkOther.checkAccessOfMovedVariable(); |
114 | 1.36k | checkOther.checkModuloOfOne(); |
115 | 1.36k | checkOther.checkOverlappingWrite(); |
116 | 1.36k | } |
117 | | |
118 | | /** @brief Clarify calculation for ".. a * b ? .." */ |
119 | | void clarifyCalculation(); |
120 | | |
121 | | /** @brief Suspicious statement like '*A++;' */ |
122 | | void clarifyStatement(); |
123 | | |
124 | | /** @brief Are there C-style pointer casts in a c++ file? */ |
125 | | void warningOldStylePointerCast(); |
126 | | |
127 | | /** @brief Check for pointer casts to a type with an incompatible binary data representation */ |
128 | | void invalidPointerCast(); |
129 | | |
130 | | /** @brief %Check scope of variables */ |
131 | | void checkVariableScope(); |
132 | | bool checkInnerScope(const Token *tok, const Variable* var, bool& used) const; |
133 | | |
134 | | /** @brief %Check for comma separated statements in return */ |
135 | | void checkCommaSeparatedReturn(); |
136 | | |
137 | | /** @brief %Check for function parameters that should be passed by reference */ |
138 | | void checkPassByReference(); |
139 | | |
140 | | void checkConstVariable(); |
141 | | void checkConstPointer(); |
142 | | |
143 | | /** @brief Using char variable as array index / as operand in bit operation */ |
144 | | void checkCharVariable(); |
145 | | |
146 | | /** @brief Incomplete statement. A statement that only contains a constant or variable */ |
147 | | void checkIncompleteStatement(); |
148 | | |
149 | | /** @brief %Check zero division*/ |
150 | | void checkZeroDivision(); |
151 | | |
152 | | /** @brief Check for NaN (not-a-number) in an arithmetic expression */ |
153 | | void checkNanInArithmeticExpression(); |
154 | | |
155 | | /** @brief copying to memory or assigning to a variable twice */ |
156 | | void checkRedundantAssignment(); |
157 | | |
158 | | /** @brief %Check for redundant bitwise operation in switch statement*/ |
159 | | void redundantBitwiseOperationInSwitchError(); |
160 | | |
161 | | /** @brief %Check for code like 'case A||B:'*/ |
162 | | void checkSuspiciousCaseInSwitch(); |
163 | | |
164 | | /** @brief %Check for objects that are destroyed immediately */ |
165 | | void checkMisusedScopedObject(); |
166 | | |
167 | | /** @brief %Check for suspicious code where if and else branch are the same (e.g "if (a) b = true; else b = true;") */ |
168 | | void checkDuplicateBranch(); |
169 | | |
170 | | /** @brief %Check for suspicious code with the same expression on both sides of operator (e.g "if (a && a)") */ |
171 | | void checkDuplicateExpression(); |
172 | | |
173 | | /** @brief %Check for code that gets never executed, such as duplicate break statements */ |
174 | | void checkUnreachableCode(); |
175 | | |
176 | | /** @brief %Check for testing sign of unsigned variable */ |
177 | | void checkSignOfUnsignedVariable(); |
178 | | |
179 | | /** @brief %Check for suspicious use of semicolon */ |
180 | | void checkSuspiciousSemicolon(); |
181 | | |
182 | | /** @brief %Check for free() operations on invalid memory locations */ |
183 | | void checkInvalidFree(); |
184 | | void invalidFreeError(const Token *tok, const std::string &allocation, bool inconclusive); |
185 | | |
186 | | /** @brief %Check for code creating redundant copies */ |
187 | | void checkRedundantCopy(); |
188 | | |
189 | | /** @brief %Check for bitwise shift with negative right operand */ |
190 | | void checkNegativeBitwiseShift(); |
191 | | |
192 | | /** @brief %Check for buffers that are filled incompletely with memset and similar functions */ |
193 | | void checkIncompleteArrayFill(); |
194 | | |
195 | | /** @brief %Check that variadic function calls don't use NULL. If NULL is \#defined as 0 and the function expects a pointer, the behaviour is undefined. */ |
196 | | void checkVarFuncNullUB(); |
197 | | |
198 | | /** @brief %Check to avoid casting a return value to unsigned char and then back to integer type. */ |
199 | | void checkCastIntToCharAndBack(); |
200 | | |
201 | | /** @brief %Check for using of comparison functions evaluating always to true or false. */ |
202 | | void checkComparisonFunctionIsAlwaysTrueOrFalse(); |
203 | | |
204 | | /** @brief %Check for redundant pointer operations */ |
205 | | void checkRedundantPointerOp(); |
206 | | |
207 | | /** @brief %Check for race condition with non-interlocked access after InterlockedDecrement() */ |
208 | | void checkInterlockedDecrement(); |
209 | | |
210 | | /** @brief %Check for unused labels */ |
211 | | void checkUnusedLabel(); |
212 | | |
213 | | /** @brief %Check for expression that depends on order of evaluation of side effects */ |
214 | | void checkEvaluationOrder(); |
215 | | |
216 | | /** @brief %Check for access of moved or forwarded variable */ |
217 | | void checkAccessOfMovedVariable(); |
218 | | |
219 | | /** @brief %Check if function declaration and definition argument names different */ |
220 | | void checkFuncArgNamesDifferent(); |
221 | | |
222 | | /** @brief %Check for shadow variables. Less noisy than gcc/clang -Wshadow. */ |
223 | | void checkShadowVariables(); |
224 | | |
225 | | void checkKnownArgument(); |
226 | | |
227 | | void checkKnownPointerToBool(); |
228 | | |
229 | | void checkComparePointers(); |
230 | | |
231 | | void checkModuloOfOne(); |
232 | | |
233 | | void checkOverlappingWrite(); |
234 | | void overlappingWriteUnion(const Token *tok); |
235 | | void overlappingWriteFunction(const Token *tok); |
236 | | |
237 | | // Error messages.. |
238 | | void checkComparisonFunctionIsAlwaysTrueOrFalseError(const Token* tok, const std::string &functionName, const std::string &varName, const bool result); |
239 | | void checkCastIntToCharAndBackError(const Token *tok, const std::string &strFunctionName); |
240 | | void clarifyCalculationError(const Token *tok, const std::string &op); |
241 | | void clarifyStatementError(const Token* tok); |
242 | | void cstyleCastError(const Token *tok); |
243 | | void invalidPointerCastError(const Token* tok, const std::string& from, const std::string& to, bool inconclusive, bool toIsInt); |
244 | | void passedByValueError(const Token *tok, const std::string &parname, bool inconclusive); |
245 | | void constVariableError(const Variable *var, const Function *function); |
246 | | void constStatementError(const Token *tok, const std::string &type, bool inconclusive); |
247 | | void signedCharArrayIndexError(const Token *tok); |
248 | | void unknownSignCharArrayIndexError(const Token *tok); |
249 | | void charBitOpError(const Token *tok); |
250 | | void variableScopeError(const Token *tok, const std::string &varname); |
251 | | void zerodivError(const Token *tok, const ValueFlow::Value *value); |
252 | | void nanInArithmeticExpressionError(const Token *tok); |
253 | | void redundantAssignmentError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive); |
254 | | void redundantInitializationError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive); |
255 | | void redundantAssignmentInSwitchError(const Token *tok1, const Token *tok2, const std::string &var); |
256 | | void redundantCopyError(const Token *tok1, const Token* tok2, const std::string& var); |
257 | | void redundantBitwiseOperationInSwitchError(const Token *tok, const std::string &varname); |
258 | | void suspiciousCaseInSwitchError(const Token* tok, const std::string& operatorString); |
259 | | void selfAssignmentError(const Token *tok, const std::string &varname); |
260 | | void misusedScopeObjectError(const Token *tok, const std::string &varname, bool isAssignment = false); |
261 | | void duplicateBranchError(const Token *tok1, const Token *tok2, ErrorPath errors); |
262 | | void duplicateAssignExpressionError(const Token *tok1, const Token *tok2, bool inconclusive); |
263 | | void oppositeExpressionError(const Token *opTok, ErrorPath errors); |
264 | | void duplicateExpressionError(const Token *tok1, const Token *tok2, const Token *opTok, ErrorPath errors, bool hasMultipleExpr = false); |
265 | | void duplicateValueTernaryError(const Token *tok); |
266 | | void duplicateExpressionTernaryError(const Token *tok, ErrorPath errors); |
267 | | void duplicateBreakError(const Token *tok, bool inconclusive); |
268 | | void unreachableCodeError(const Token* tok, const Token* noreturn, bool inconclusive); |
269 | | void redundantContinueError(const Token* tok); |
270 | | void unsignedLessThanZeroError(const Token *tok, const ValueFlow::Value *v, const std::string &varname); |
271 | | void pointerLessThanZeroError(const Token *tok, const ValueFlow::Value *v); |
272 | | void unsignedPositiveError(const Token *tok, const ValueFlow::Value *v, const std::string &varname); |
273 | | void pointerPositiveError(const Token *tok, const ValueFlow::Value *v); |
274 | | void suspiciousSemicolonError(const Token *tok); |
275 | | void negativeBitwiseShiftError(const Token *tok, int op); |
276 | | void redundantCopyError(const Token *tok, const std::string &varname); |
277 | | void incompleteArrayFillError(const Token* tok, const std::string& buffer, const std::string& function, bool boolean); |
278 | | void varFuncNullUBError(const Token *tok); |
279 | | void commaSeparatedReturnError(const Token *tok); |
280 | | void redundantPointerOpError(const Token* tok, const std::string& varname, bool inconclusive, bool addressOfDeref); |
281 | | void raceAfterInterlockedDecrementError(const Token* tok); |
282 | | void unusedLabelError(const Token* tok, bool inSwitch, bool hasIfdef); |
283 | | void unknownEvaluationOrder(const Token* tok); |
284 | | void accessMovedError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive); |
285 | | void funcArgNamesDifferent(const std::string & functionName, nonneg int index, const Token* declaration, const Token* definition); |
286 | | void funcArgOrderDifferent(const std::string & functionName, const Token * declaration, const Token * definition, const std::vector<const Token*> & declarations, const std::vector<const Token*> & definitions); |
287 | | void shadowError(const Token *var, const Token *shadowed, std::string type); |
288 | | void knownArgumentError(const Token *tok, const Token *ftok, const ValueFlow::Value *value, const std::string &varexpr, bool isVariableExpressionHidden); |
289 | | void knownPointerToBoolError(const Token* tok, const ValueFlow::Value* value); |
290 | | void comparePointersError(const Token *tok, const ValueFlow::Value *v1, const ValueFlow::Value *v2); |
291 | | void checkModuloOfOneError(const Token *tok); |
292 | | |
293 | 0 | void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override { |
294 | 0 | CheckOther c(nullptr, settings, errorLogger); |
295 | |
|
296 | 0 | ErrorPath errorPath; |
297 | | |
298 | | // error |
299 | 0 | c.zerodivError(nullptr, nullptr); |
300 | 0 | c.misusedScopeObjectError(nullptr, "varname"); |
301 | 0 | c.invalidPointerCastError(nullptr, "float *", "double *", false, false); |
302 | 0 | c.negativeBitwiseShiftError(nullptr, 1); |
303 | 0 | c.negativeBitwiseShiftError(nullptr, 2); |
304 | 0 | c.raceAfterInterlockedDecrementError(nullptr); |
305 | 0 | c.invalidFreeError(nullptr, "malloc", false); |
306 | 0 | c.overlappingWriteUnion(nullptr); |
307 | 0 | c.overlappingWriteFunction(nullptr); |
308 | | |
309 | | //performance |
310 | 0 | c.redundantCopyError(nullptr, "varname"); |
311 | 0 | c.redundantCopyError(nullptr, nullptr, "var"); |
312 | | |
313 | | // style/warning |
314 | 0 | c.checkComparisonFunctionIsAlwaysTrueOrFalseError(nullptr, "isless","varName",false); |
315 | 0 | c.checkCastIntToCharAndBackError(nullptr, "func_name"); |
316 | 0 | c.cstyleCastError(nullptr); |
317 | 0 | c.passedByValueError(nullptr, "parametername", false); |
318 | 0 | c.constVariableError(nullptr, nullptr); |
319 | 0 | c.constStatementError(nullptr, "type", false); |
320 | 0 | c.signedCharArrayIndexError(nullptr); |
321 | 0 | c.unknownSignCharArrayIndexError(nullptr); |
322 | 0 | c.charBitOpError(nullptr); |
323 | 0 | c.variableScopeError(nullptr, "varname"); |
324 | 0 | c.redundantAssignmentInSwitchError(nullptr, nullptr, "var"); |
325 | 0 | c.suspiciousCaseInSwitchError(nullptr, "||"); |
326 | 0 | c.selfAssignmentError(nullptr, "varname"); |
327 | 0 | c.clarifyCalculationError(nullptr, "+"); |
328 | 0 | c.clarifyStatementError(nullptr); |
329 | 0 | c.duplicateBranchError(nullptr, nullptr, errorPath); |
330 | 0 | c.duplicateAssignExpressionError(nullptr, nullptr, true); |
331 | 0 | c.oppositeExpressionError(nullptr, errorPath); |
332 | 0 | c.duplicateExpressionError(nullptr, nullptr, nullptr, errorPath); |
333 | 0 | c.duplicateValueTernaryError(nullptr); |
334 | 0 | c.duplicateExpressionTernaryError(nullptr, errorPath); |
335 | 0 | c.duplicateBreakError(nullptr, false); |
336 | 0 | c.unreachableCodeError(nullptr, nullptr, false); |
337 | 0 | c.unsignedLessThanZeroError(nullptr, nullptr, "varname"); |
338 | 0 | c.unsignedPositiveError(nullptr, nullptr, "varname"); |
339 | 0 | c.pointerLessThanZeroError(nullptr, nullptr); |
340 | 0 | c.pointerPositiveError(nullptr, nullptr); |
341 | 0 | c.suspiciousSemicolonError(nullptr); |
342 | 0 | c.incompleteArrayFillError(nullptr, "buffer", "memset", false); |
343 | 0 | c.varFuncNullUBError(nullptr); |
344 | 0 | c.nanInArithmeticExpressionError(nullptr); |
345 | 0 | c.commaSeparatedReturnError(nullptr); |
346 | 0 | c.redundantPointerOpError(nullptr, "varname", false, /*addressOfDeref*/ true); |
347 | 0 | c.unusedLabelError(nullptr, false, false); |
348 | 0 | c.unusedLabelError(nullptr, false, true); |
349 | 0 | c.unusedLabelError(nullptr, true, false); |
350 | 0 | c.unusedLabelError(nullptr, true, true); |
351 | 0 | c.unknownEvaluationOrder(nullptr); |
352 | 0 | c.accessMovedError(nullptr, "v", nullptr, false); |
353 | 0 | c.funcArgNamesDifferent("function", 1, nullptr, nullptr); |
354 | 0 | c.redundantBitwiseOperationInSwitchError(nullptr, "varname"); |
355 | 0 | c.shadowError(nullptr, nullptr, "variable"); |
356 | 0 | c.shadowError(nullptr, nullptr, "function"); |
357 | 0 | c.shadowError(nullptr, nullptr, "argument"); |
358 | 0 | c.knownArgumentError(nullptr, nullptr, nullptr, "x", false); |
359 | 0 | c.knownPointerToBoolError(nullptr, nullptr); |
360 | 0 | c.comparePointersError(nullptr, nullptr, nullptr); |
361 | 0 | c.redundantAssignmentError(nullptr, nullptr, "var", false); |
362 | 0 | c.redundantInitializationError(nullptr, nullptr, "var", false); |
363 | |
|
364 | 0 | const std::vector<const Token *> nullvec; |
365 | 0 | c.funcArgOrderDifferent("function", nullptr, nullptr, nullvec, nullvec); |
366 | 0 | c.checkModuloOfOneError(nullptr); |
367 | 0 | } |
368 | | |
369 | 1.36k | static std::string myName() { |
370 | 1.36k | return "Other"; |
371 | 1.36k | } |
372 | | |
373 | 0 | std::string classInfo() const override { |
374 | 0 | return "Other checks\n" |
375 | | |
376 | | // error |
377 | 0 | "- division with zero\n" |
378 | 0 | "- scoped object destroyed immediately after construction\n" |
379 | 0 | "- assignment in an assert statement\n" |
380 | 0 | "- free() or delete of an invalid memory location\n" |
381 | 0 | "- bitwise operation with negative right operand\n" |
382 | 0 | "- cast the return values of getc(),fgetc() and getchar() to character and compare it to EOF\n" |
383 | 0 | "- race condition with non-interlocked access after InterlockedDecrement() call\n" |
384 | 0 | "- expression 'x = x++;' depends on order of evaluation of side effects\n" |
385 | 0 | "- overlapping write of union\n" |
386 | | |
387 | | // warning |
388 | 0 | "- either division by zero or useless condition\n" |
389 | 0 | "- access of moved or forwarded variable.\n" |
390 | | |
391 | | // performance |
392 | 0 | "- redundant data copying for const variable\n" |
393 | 0 | "- subsequent assignment or copying to a variable or buffer\n" |
394 | 0 | "- passing parameter by value\n" |
395 | | |
396 | | // portability |
397 | 0 | "- Passing NULL pointer to function with variable number of arguments leads to UB.\n" |
398 | | |
399 | | // style |
400 | 0 | "- C-style pointer cast in C++ code\n" |
401 | 0 | "- casting between incompatible pointer types\n" |
402 | 0 | "- [Incomplete statement](IncompleteStatement)\n" |
403 | 0 | "- [check how signed char variables are used](CharVar)\n" |
404 | 0 | "- variable scope can be limited\n" |
405 | 0 | "- unusual pointer arithmetic. For example: \"abc\" + 'd'\n" |
406 | 0 | "- redundant assignment, increment, or bitwise operation in a switch statement\n" |
407 | 0 | "- redundant strcpy in a switch statement\n" |
408 | 0 | "- Suspicious case labels in switch()\n" |
409 | 0 | "- assignment of a variable to itself\n" |
410 | 0 | "- Comparison of values leading always to true or false\n" |
411 | 0 | "- Clarify calculation with parentheses\n" |
412 | 0 | "- suspicious comparison of '\\0' with a char\\* variable\n" |
413 | 0 | "- duplicate break statement\n" |
414 | 0 | "- unreachable code\n" |
415 | 0 | "- testing if unsigned variable is negative/positive\n" |
416 | 0 | "- Suspicious use of ; at the end of 'if/for/while' statement.\n" |
417 | 0 | "- Array filled incompletely using memset/memcpy/memmove.\n" |
418 | 0 | "- NaN (not a number) value used in arithmetic expression.\n" |
419 | 0 | "- comma in return statement (the comma can easily be misread as a semicolon).\n" |
420 | 0 | "- prefer erfc, expm1 or log1p to avoid loss of precision.\n" |
421 | 0 | "- identical code in both branches of if/else or ternary operator.\n" |
422 | 0 | "- redundant pointer operation on pointer like &\\*some_ptr.\n" |
423 | 0 | "- find unused 'goto' labels.\n" |
424 | 0 | "- function declaration and definition argument names different.\n" |
425 | 0 | "- function declaration and definition argument order different.\n" |
426 | 0 | "- shadow variable.\n" |
427 | 0 | "- variable can be declared const.\n" |
428 | 0 | "- calculating modulo of one.\n" |
429 | 0 | "- known function argument, suspicious calculation.\n"; |
430 | 0 | } |
431 | | }; |
432 | | /// @} |
433 | | //--------------------------------------------------------------------------- |
434 | | #endif // checkotherH |