Partial fix for #8028 (ValueFlow: Origin/callstack of value)
This commit is contained in:
parent
531278e075
commit
8d75d1b920
2
Makefile
2
Makefile
|
@ -411,7 +411,7 @@ $(SRCDIR)/platform.o: lib/platform.cpp lib/cxx11emu.h lib/platform.h lib/config.
|
|||
$(SRCDIR)/preprocessor.o: lib/preprocessor.cpp lib/cxx11emu.h lib/preprocessor.h lib/config.h lib/path.h lib/errorlogger.h lib/suppressions.h lib/settings.h lib/library.h lib/mathlib.h lib/standards.h lib/platform.h lib/importproject.h lib/timer.h
|
||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(SRCDIR)/preprocessor.o $(SRCDIR)/preprocessor.cpp
|
||||
|
||||
$(SRCDIR)/settings.o: lib/settings.cpp lib/cxx11emu.h lib/settings.h lib/config.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/preprocessor.h lib/utils.h
|
||||
$(SRCDIR)/settings.o: lib/settings.cpp lib/cxx11emu.h lib/settings.h lib/config.h lib/library.h lib/mathlib.h lib/standards.h lib/errorlogger.h lib/suppressions.h lib/platform.h lib/importproject.h lib/timer.h lib/preprocessor.h lib/utils.h lib/valueflow.h
|
||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CFG) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(SRCDIR)/settings.o $(SRCDIR)/settings.cpp
|
||||
|
||||
$(SRCDIR)/suppressions.o: lib/suppressions.cpp lib/cxx11emu.h lib/suppressions.h lib/config.h lib/path.h
|
||||
|
|
17
lib/check.h
17
lib/check.h
|
@ -158,6 +158,23 @@ protected:
|
|||
reportError(errmsg);
|
||||
}
|
||||
|
||||
std::list<const Token *> getErrorPath(const Token *errtok, const ValueFlow::Value *value) const {
|
||||
std::list<const Token*> errorPath;
|
||||
if (!value) {
|
||||
errorPath.push_back(errtok);
|
||||
} else if (_settings->verbose) {
|
||||
errorPath = value->callstack;
|
||||
errorPath.push_back(errtok);
|
||||
} else {
|
||||
if (value->condition)
|
||||
errorPath.push_back(value->condition);
|
||||
//else if (!value->isKnown() || value->defaultArg)
|
||||
// errorPath = value->callstack;
|
||||
errorPath.push_back(errtok);
|
||||
}
|
||||
return errorPath;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string _name;
|
||||
|
||||
|
|
|
@ -275,6 +275,7 @@ void CheckNullPointer::nullPointerLinkedList()
|
|||
continue;
|
||||
|
||||
// Check usage of dereferenced variable in the loop..
|
||||
// TODO: Move this to ValueFlow
|
||||
for (std::list<Scope*>::const_iterator j = i->nestedList.begin(); j != i->nestedList.end(); ++j) {
|
||||
const Scope* const scope = *j;
|
||||
if (scope->type != Scope::eWhile)
|
||||
|
@ -287,7 +288,8 @@ void CheckNullPointer::nullPointerLinkedList()
|
|||
// for statement.
|
||||
for (const Token *tok4 = scope->classStart; tok4; tok4 = tok4->next()) {
|
||||
if (tok4 == i->classEnd) {
|
||||
nullPointerError(tok1, var->name(), scope->classDef, false);
|
||||
const ValueFlow::Value v(scope->classDef, 0LL);
|
||||
nullPointerError(tok1, var->name(), &v, false);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -306,7 +308,6 @@ void CheckNullPointer::nullPointerLinkedList()
|
|||
|
||||
void CheckNullPointer::nullPointerByDeRefAndChec()
|
||||
{
|
||||
const bool printWarnings = _settings->isEnabled(Settings::WARNING);
|
||||
const bool printInconclusive = (_settings->inconclusive);
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
|
@ -340,10 +341,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
|||
std::list<const Token *> varlist;
|
||||
parseFunctionCall(*ftok->previous(), varlist, &_settings->library);
|
||||
if (std::find(varlist.begin(), varlist.end(), tok) != varlist.end()) {
|
||||
if (value->condition == nullptr)
|
||||
nullPointerError(tok, tok->str(), false, value->defaultArg, !value->isKnown());
|
||||
else if (printWarnings)
|
||||
nullPointerError(tok, tok->str(), value->condition, value->inconclusive);
|
||||
nullPointerError(tok, tok->str(), value, value->inconclusive);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -351,19 +349,12 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
|||
// Pointer dereference.
|
||||
bool unknown = false;
|
||||
if (!isPointerDeRef(tok,unknown)) {
|
||||
if (printInconclusive && unknown) {
|
||||
if (value->condition == nullptr)
|
||||
nullPointerError(tok, tok->str(), true, value->defaultArg, !value->isKnown());
|
||||
else
|
||||
nullPointerError(tok, tok->str(), value->condition, true);
|
||||
}
|
||||
if (unknown)
|
||||
nullPointerError(tok, tok->str(), value, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value->condition == nullptr)
|
||||
nullPointerError(tok, tok->str(), value->inconclusive, value->defaultArg, !value->isKnown());
|
||||
else if (printWarnings)
|
||||
nullPointerError(tok, tok->str(), value->condition, value->inconclusive);
|
||||
nullPointerError(tok, tok->str(), value, value->inconclusive);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,32 +453,39 @@ void CheckNullPointer::nullConstantDereference()
|
|||
}
|
||||
}
|
||||
|
||||
void CheckNullPointer::nullPointerError(const Token *tok)
|
||||
void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, const ValueFlow::Value *value, bool inconclusive)
|
||||
{
|
||||
reportError(tok, Severity::error, "nullPointer", "Null pointer dereference", CWE476, false);
|
||||
}
|
||||
const std::string errmsgcond(ValueFlow::eitherTheConditionIsRedundant(value ? value->condition : nullptr) + " or there is possible null pointer dereference: " + varname + ".");
|
||||
const std::string errmsgdefarg("Possible null pointer dereference if the default parameter value is used: " + varname);
|
||||
|
||||
void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, bool inconclusive, bool defaultArg, bool possible)
|
||||
{
|
||||
if (defaultArg) {
|
||||
if (_settings->isEnabled(Settings::WARNING))
|
||||
reportError(tok, Severity::warning, "nullPointerDefaultArg", "Possible null pointer dereference if the default parameter value is used: " + varname, CWE476, inconclusive);
|
||||
} else if (possible) {
|
||||
if (_settings->isEnabled(Settings::WARNING))
|
||||
reportError(tok, Severity::warning, "nullPointer", "Possible null pointer dereference: " + varname, CWE476, inconclusive);
|
||||
} else
|
||||
reportError(tok, Severity::error, "nullPointer", "Null pointer dereference: " + varname, CWE476, inconclusive);
|
||||
}
|
||||
|
||||
void CheckNullPointer::nullPointerError(const Token *tok, const std::string &varname, const Token* nullCheck, bool inconclusive)
|
||||
{
|
||||
if (! _settings->isEnabled(Settings::WARNING))
|
||||
if (!tok) {
|
||||
reportError(tok, Severity::error, "nullPointer", "Null pointer dereference", CWE476, false);
|
||||
reportError(tok, Severity::warning, "nullPointerDefaultArg", errmsgdefarg, CWE476, false);
|
||||
reportError(tok, Severity::warning, "nullPointerRedundantCheck", errmsgcond, CWE476, false);
|
||||
return;
|
||||
std::list<const Token*> callstack;
|
||||
callstack.push_back(tok);
|
||||
callstack.push_back(nullCheck);
|
||||
const std::string errmsg(ValueFlow::eitherTheConditionIsRedundant(nullCheck) + " or there is possible null pointer dereference: " + varname + ".");
|
||||
reportError(callstack, Severity::warning, "nullPointerRedundantCheck", errmsg, CWE476, inconclusive);
|
||||
}
|
||||
|
||||
if (!_settings->isEnabled(value, inconclusive))
|
||||
return;
|
||||
|
||||
const std::list<const Token*> errorPath = getErrorPath(tok,value);
|
||||
|
||||
if (value->condition) {
|
||||
reportError(errorPath, Severity::warning, "nullPointerRedundantCheck", errmsgcond, CWE476, inconclusive || value->inconclusive);
|
||||
} else if (value->defaultArg) {
|
||||
reportError(errorPath, Severity::warning, "nullPointerDefaultArg", errmsgdefarg, CWE476, inconclusive || value->inconclusive);
|
||||
} else {
|
||||
std::string errmsg;
|
||||
errmsg = std::string(value->isKnown() ? "Null" : "Possible null") + " pointer dereference";
|
||||
if (!varname.empty())
|
||||
errmsg += ": " + varname;
|
||||
|
||||
reportError(errorPath,
|
||||
value->isKnown() ? Severity::error : Severity::warning,
|
||||
"nullPointer",
|
||||
errmsg,
|
||||
CWE476, inconclusive || value->inconclusive);
|
||||
}
|
||||
}
|
||||
|
||||
void CheckNullPointer::arithmetic()
|
||||
|
|
|
@ -83,16 +83,17 @@ public:
|
|||
/** @brief dereferencing null constant (after Tokenizer::simplifyKnownVariables) */
|
||||
void nullConstantDereference();
|
||||
|
||||
void nullPointerError(const Token *tok); // variable name unknown / doesn't exist
|
||||
void nullPointerError(const Token *tok, const std::string &varname, bool inconclusive, bool defaultArg, bool possible);
|
||||
void nullPointerError(const Token *tok, const std::string &varname, const Token* nullCheck, bool inconclusive);
|
||||
void nullPointerError(const Token *tok) {
|
||||
ValueFlow::Value v(0);
|
||||
v.setKnown();
|
||||
nullPointerError(tok, "", &v, false);
|
||||
}
|
||||
void nullPointerError(const Token *tok, const std::string &varname, const ValueFlow::Value* value, bool inconclusive);
|
||||
private:
|
||||
|
||||
/** Get error messages. Used by --errorlist */
|
||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||
CheckNullPointer c(nullptr, settings, errorLogger);
|
||||
c.nullPointerError(nullptr);
|
||||
c.nullPointerError(nullptr, "pointer", false, true, true);
|
||||
c.nullPointerError(nullptr, "pointer", nullptr, false);
|
||||
c.arithmeticError(nullptr, nullptr);
|
||||
}
|
||||
|
|
|
@ -1625,9 +1625,6 @@ void CheckOther::constStatementError(const Token *tok, const std::string &type)
|
|||
//---------------------------------------------------------------------------
|
||||
void CheckOther::checkZeroDivision()
|
||||
{
|
||||
const bool printWarnings = _settings->isEnabled(Settings::WARNING);
|
||||
const bool printInconclusive = _settings->inconclusive;
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (!tok->astOperand2() || !tok->astOperand1())
|
||||
continue;
|
||||
|
@ -1646,31 +1643,27 @@ void CheckOther::checkZeroDivision()
|
|||
|
||||
// Value flow..
|
||||
const ValueFlow::Value *value = tok->astOperand2()->getValue(0LL);
|
||||
if (!value)
|
||||
continue;
|
||||
if (!printInconclusive && value->inconclusive)
|
||||
continue;
|
||||
if (value->condition == nullptr)
|
||||
zerodivError(tok, value->inconclusive);
|
||||
else if (printWarnings)
|
||||
zerodivcondError(value->condition,tok,value->inconclusive);
|
||||
if (value && _settings->isEnabled(value, false))
|
||||
zerodivError(tok, value);
|
||||
}
|
||||
}
|
||||
|
||||
void CheckOther::zerodivError(const Token *tok, bool inconclusive)
|
||||
void CheckOther::zerodivError(const Token *tok, const ValueFlow::Value *value)
|
||||
{
|
||||
reportError(tok, Severity::error, "zerodiv", "Division by zero.", CWE369, inconclusive);
|
||||
}
|
||||
|
||||
void CheckOther::zerodivcondError(const Token *tokcond, const Token *tokdiv, bool inconclusive)
|
||||
{
|
||||
std::list<const Token *> callstack;
|
||||
if (tokcond && tokdiv) {
|
||||
callstack.push_back(tokcond);
|
||||
callstack.push_back(tokdiv);
|
||||
if (!tok && !value) {
|
||||
reportError(tok, Severity::error, "zerodiv", "Division by zero.", CWE369, false);
|
||||
reportError(tok, Severity::error, "zerodivcond", ValueFlow::eitherTheConditionIsRedundant(nullptr) + " or there is division by zero.", CWE369, false);
|
||||
return;
|
||||
}
|
||||
|
||||
const std::list<const Token *> errorPath = getErrorPath(tok, value);
|
||||
|
||||
if (!value->condition)
|
||||
reportError(errorPath, Severity::error, "zerodiv", "Division by zero.", CWE369, value->inconclusive);
|
||||
else {
|
||||
const std::string linenr(MathLib::toString(tok->linenr()));
|
||||
reportError(errorPath, Severity::warning, "zerodivcond", ValueFlow::eitherTheConditionIsRedundant(value->condition) + " or there is division by zero at line " + linenr + ".", CWE369, value->inconclusive);
|
||||
}
|
||||
const std::string linenr(MathLib::toString(tokdiv ? tokdiv->linenr() : 0));
|
||||
reportError(callstack, Severity::warning, "zerodivcond", ValueFlow::eitherTheConditionIsRedundant(tokcond) + " or there is division by zero at line " + linenr + ".", CWE369, inconclusive);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -218,8 +218,7 @@ private:
|
|||
void unknownSignCharArrayIndexError(const Token *tok);
|
||||
void charBitOpError(const Token *tok);
|
||||
void variableScopeError(const Token *tok, const std::string &varname);
|
||||
void zerodivError(const Token *tok, bool inconclusive);
|
||||
void zerodivcondError(const Token *tokcond, const Token *tokdiv, bool inconclusive);
|
||||
void zerodivError(const Token *tok, const ValueFlow::Value *value);
|
||||
void nanInArithmeticExpressionError(const Token *tok);
|
||||
void redundantAssignmentError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive);
|
||||
void redundantAssignmentInSwitchError(const Token *tok1, const Token *tok2, const std::string &var);
|
||||
|
@ -258,8 +257,7 @@ private:
|
|||
CheckOther c(nullptr, settings, errorLogger);
|
||||
|
||||
// error
|
||||
c.zerodivError(nullptr, false);
|
||||
c.zerodivcondError(nullptr, 0,false);
|
||||
c.zerodivError(nullptr, nullptr);
|
||||
c.misusedScopeObjectError(nullptr, "varname");
|
||||
c.invalidPointerCastError(nullptr, "float", "double", false);
|
||||
c.negativeBitwiseShiftError(nullptr, 1);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "settings.h"
|
||||
#include "preprocessor.h" // Preprocessor
|
||||
#include "utils.h"
|
||||
#include "valueflow.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
|
@ -129,3 +130,12 @@ bool Settings::isEnabled(Severity::SeverityType severity) const
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Settings::isEnabled(const ValueFlow::Value *value, bool inconclusiveCheck) const
|
||||
{
|
||||
if (!isEnabled(Settings::WARNING) && (!value->isKnown() || value->condition || value->defaultArg))
|
||||
return false;
|
||||
if (!inconclusive && (inconclusiveCheck || value->inconclusive))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
#include "errorlogger.h"
|
||||
#include "timer.h"
|
||||
|
||||
namespace ValueFlow {
|
||||
class Value;
|
||||
}
|
||||
|
||||
/// @addtogroup Core
|
||||
/// @{
|
||||
|
||||
|
@ -178,6 +182,12 @@ public:
|
|||
*/
|
||||
bool isEnabled(Severity::SeverityType severity) const;
|
||||
|
||||
/**
|
||||
* @brief Returns true if given value can be shown
|
||||
* @return true if the value can be shown
|
||||
*/
|
||||
bool isEnabled(const ValueFlow::Value *value, bool inconclusiveCheck=false) const;
|
||||
|
||||
/**
|
||||
* @brief Enable extra checks by id. See isEnabled()
|
||||
* @param str single id or list of id values to be enabled
|
||||
|
|
|
@ -1970,6 +1970,8 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat
|
|||
continue;
|
||||
|
||||
std::list<ValueFlow::Value> values = tok->astOperand2()->values();
|
||||
for (std::list<ValueFlow::Value>::iterator it = values.begin(); it != values.end(); ++it)
|
||||
it->callstack.push_back(tok->astOperand2());
|
||||
const bool constValue = tok->astOperand2()->isNumber();
|
||||
|
||||
if (tokenlist->isCPP() && Token::Match(var->typeStartToken(), "bool|_Bool")) {
|
||||
|
@ -2768,6 +2770,10 @@ static void valueFlowSubFunction(TokenList *tokenlist, ErrorLogger *errorLogger,
|
|||
}
|
||||
}
|
||||
|
||||
// callstack..
|
||||
for (std::list<ValueFlow::Value>::iterator it = argvalues.begin(); it != argvalues.end(); ++it)
|
||||
it->callstack.push_back(argtok);
|
||||
|
||||
// passed values are not "known"..
|
||||
for (std::list<ValueFlow::Value>::iterator it = argvalues.begin(); it != argvalues.end(); ++it) {
|
||||
it->changeKnownToPossible();
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#define valueflowH
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include "config.h"
|
||||
|
||||
|
@ -34,7 +35,9 @@ namespace ValueFlow {
|
|||
class CPPCHECKLIB Value {
|
||||
public:
|
||||
explicit Value(long long val = 0) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(NonMovedVariable), varvalue(val), condition(0), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {}
|
||||
Value(const Token *c, long long val) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(NonMovedVariable), varvalue(val), condition(c), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {}
|
||||
Value(const Token *c, long long val) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(NonMovedVariable), varvalue(val), condition(c), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {
|
||||
callstack.push_back(c);
|
||||
}
|
||||
|
||||
bool operator==(const Value &rhs) const {
|
||||
if (valueType != rhs.valueType)
|
||||
|
@ -105,6 +108,8 @@ namespace ValueFlow {
|
|||
/** Condition that this value depends on (TODO: replace with a 'callstack') */
|
||||
const Token *condition;
|
||||
|
||||
std::list<const Token *> callstack;
|
||||
|
||||
/** For calculated values - varId that calculated value depends on */
|
||||
unsigned int varId;
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ private:
|
|||
if (!tokenizer.tokenize(istr, filename))
|
||||
return;
|
||||
|
||||
// Check for redundant code..
|
||||
// Check for null pointer dereferences..
|
||||
CheckNullPointer checkNullPointer;
|
||||
checkNullPointer.runChecks(&tokenizer, &settings, this);
|
||||
|
||||
|
@ -127,7 +127,7 @@ private:
|
|||
" while (tok);\n"
|
||||
" tok = tok->next();\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning, inconclusive) Either the condition 'tok' is redundant or there is possible null pointer dereference: tok.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning, inconclusive) Either the condition 'tok' is redundant or there is possible null pointer dereference: tok.\n", errout.str());
|
||||
|
||||
// #2681
|
||||
{
|
||||
|
@ -144,7 +144,7 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check(code, true); // inconclusive=true => error
|
||||
ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:3]: (warning, inconclusive) Either the condition 'tok' is redundant or there is possible null pointer dereference: tok.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:6]: (warning, inconclusive) Either the condition 'tok' is redundant or there is possible null pointer dereference: tok.\n", errout.str());
|
||||
}
|
||||
|
||||
check("void foo()\n"
|
||||
|
@ -155,7 +155,7 @@ private:
|
|||
" tok = tok->next();\n"
|
||||
" }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (warning) Either the condition 'while' is redundant or there is possible null pointer dereference: tok.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (warning) Either the condition 'while' is redundant or there is possible null pointer dereference: tok.\n", errout.str());
|
||||
|
||||
check("void foo(Token &tok)\n"
|
||||
"{\n"
|
||||
|
@ -281,7 +281,7 @@ private:
|
|||
" if (!abc)\n"
|
||||
" ;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
|
||||
check("void foo(struct ABC *abc) {\n"
|
||||
" bar(abc->a);\n"
|
||||
|
@ -290,9 +290,9 @@ private:
|
|||
" if (!abc)\n"
|
||||
" ;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n"
|
||||
"[test.cpp:3] -> [test.cpp:5]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n"
|
||||
"[test.cpp:4] -> [test.cpp:5]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:2]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n"
|
||||
"[test.cpp:5] -> [test.cpp:3]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n"
|
||||
"[test.cpp:5] -> [test.cpp:4]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
|
||||
check("void foo(ABC *abc) {\n"
|
||||
" if (abc->a == 3) {\n"
|
||||
|
@ -300,7 +300,7 @@ private:
|
|||
" }\n"
|
||||
" if (abc) {}\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:2]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
|
||||
check("void f(ABC *abc) {\n"
|
||||
" if (abc->x == 0) {\n"
|
||||
|
@ -308,7 +308,7 @@ private:
|
|||
" }\n"
|
||||
" if (!abc);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:2]: (warning) Either the condition '!abc' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
|
||||
// TODO: False negative if member of member is dereferenced
|
||||
check("void foo(ABC *abc) {\n"
|
||||
|
@ -316,14 +316,14 @@ private:
|
|||
" if (abc->next)\n"
|
||||
" ;\n"
|
||||
"}");
|
||||
TODO_ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Possible null pointer dereference: abc - otherwise it is redundant to check it against null.\n", "", errout.str());
|
||||
TODO_ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Possible null pointer dereference: abc - otherwise it is redundant to check it against null.\n", "", errout.str());
|
||||
|
||||
check("void foo(ABC *abc) {\n"
|
||||
" abc->a = 0;\n"
|
||||
" if (abc && abc->b == 0)\n"
|
||||
" ;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'if(abc&&abc->b==0)' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'if(abc&&abc->b==0)' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
|
||||
// ok dereferencing in a condition
|
||||
check("void foo(struct ABC *abc)\n"
|
||||
|
@ -446,7 +446,7 @@ private:
|
|||
" do_stuff();\n"
|
||||
" if (abc) { }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n",errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n",errout.str());
|
||||
|
||||
// #2641 - local pointer, function call
|
||||
check("void f(ABC *abc) {\n"
|
||||
|
@ -454,7 +454,7 @@ private:
|
|||
" do_stuff();\n"
|
||||
" if (abc) { }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n",errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n",errout.str());
|
||||
|
||||
// #2691 - switch/break
|
||||
check("void f(ABC *abc) {\n"
|
||||
|
@ -503,7 +503,7 @@ private:
|
|||
check(code);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
check(code, true);
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning, inconclusive) Either the condition 'if(fred)' is redundant or there is possible null pointer dereference: fred.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'if(fred)' is redundant or there is possible null pointer dereference: fred.\n", errout.str());
|
||||
}
|
||||
|
||||
// #3425 - false positives when there are macros
|
||||
|
@ -523,21 +523,21 @@ private:
|
|||
" if (!p)\n"
|
||||
" ;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
check("void foo(int *p)\n"
|
||||
"{\n"
|
||||
" *p = 0;\n"
|
||||
" if (p) { }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
check("void foo(int *p)\n"
|
||||
"{\n"
|
||||
" *p = 0;\n"
|
||||
" if (p || q) { }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition 'if(p||q)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition 'if(p||q)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
check("void foo(int *p)\n"
|
||||
"{\n"
|
||||
|
@ -545,7 +545,7 @@ private:
|
|||
" if (!p)\n"
|
||||
" ;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
check("void foo(char *p)\n"
|
||||
"{\n"
|
||||
|
@ -553,14 +553,14 @@ private:
|
|||
" if (!p)\n"
|
||||
" ;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
check("void foo(char *p)\n"
|
||||
"{\n"
|
||||
" if (*p == 0) { }\n"
|
||||
" if (!p) { }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
// no error
|
||||
check("void foo()\n"
|
||||
|
@ -613,7 +613,7 @@ private:
|
|||
" if (!p)\n"
|
||||
" ;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
// while
|
||||
check("void f(int *p) {\n"
|
||||
|
@ -626,7 +626,7 @@ private:
|
|||
" *p = 0;\n"
|
||||
" while (p) { }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'while(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'while(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
// Ticket #3125
|
||||
check("void foo(ABC *p)\n"
|
||||
|
@ -703,7 +703,7 @@ private:
|
|||
" assert(p && (*p<=6));\n"
|
||||
" if (p) { *p = 0; }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
check("void foo(x *p)\n"
|
||||
"{\n"
|
||||
|
@ -768,7 +768,7 @@ private:
|
|||
" a = b ? c : d;\n"
|
||||
" if (item) { }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'if(item)' is redundant or there is possible null pointer dereference: item.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'if(item)' is redundant or there is possible null pointer dereference: item.\n", errout.str());
|
||||
|
||||
check("BOOL GotoFlyAnchor()\n" // #2243
|
||||
"{\n"
|
||||
|
@ -1315,7 +1315,7 @@ private:
|
|||
" }\n"
|
||||
" }\n"
|
||||
"}\n", true);
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning, inconclusive) Either the condition 'if(values)' is redundant or there is possible null pointer dereference: values.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning, inconclusive) Either the condition 'if(values)' is redundant or there is possible null pointer dereference: values.\n", errout.str());
|
||||
}
|
||||
|
||||
void nullpointer_addressOf() { // address of
|
||||
|
@ -1373,27 +1373,27 @@ private:
|
|||
" }\n"
|
||||
" *p = 0;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
check("void foo(char *p) {\n"
|
||||
" if (p && *p == 0) {\n"
|
||||
" }\n"
|
||||
" printf(\"%c\", *p);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
check("void foo(char *p) {\n"
|
||||
" if (p && *p == 0) {\n"
|
||||
" } else { *p = 0; }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
check("void foo(char *p) {\n"
|
||||
" if (p) {\n"
|
||||
" }\n"
|
||||
" strcpy(p, \"abc\");\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
check("void foo(char *p) {\n"
|
||||
" if (p) {\n"
|
||||
|
@ -1401,7 +1401,7 @@ private:
|
|||
" bar();\n"
|
||||
" strcpy(p, \"abc\");\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:2]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
check("void foo(abc *p) {\n"
|
||||
" if (!p) {\n"
|
||||
|
@ -1470,8 +1470,8 @@ private:
|
|||
" return 5+*p;\n"
|
||||
" }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n"
|
||||
"[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n"
|
||||
"[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
// operator!
|
||||
check("void f() {\n"
|
||||
|
@ -1507,7 +1507,7 @@ private:
|
|||
" }\n"
|
||||
" *p = 0;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:2]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (warning) Either the condition 'p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
// #2467 - unknown macro may terminate the application
|
||||
check("void f(Fred *fred) {\n"
|
||||
|
@ -1607,7 +1607,7 @@ private:
|
|||
" if (fred) { }\n"
|
||||
" return fred->a;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'fred' is redundant or there is possible null pointer dereference: fred.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'fred' is redundant or there is possible null pointer dereference: fred.\n", errout.str());
|
||||
|
||||
// #2789 - assign and check pointer
|
||||
check("void f() {\n"
|
||||
|
@ -1615,7 +1615,7 @@ private:
|
|||
" if (!p) { }\n"
|
||||
" *p = 0;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
// check, assign and use
|
||||
check("void f() {\n"
|
||||
|
@ -1689,7 +1689,7 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check(code, true); // inconclusive
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'fred==NULL' is redundant or there is possible null pointer dereference: fred.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning, inconclusive) Either the condition 'fred==NULL' is redundant or there is possible null pointer dereference: fred.\n", errout.str());
|
||||
}
|
||||
|
||||
check("void f(char *s) {\n" // #3358
|
||||
|
@ -1722,7 +1722,7 @@ private:
|
|||
" if (!p) {}\n"
|
||||
" return q ? p->x : 0;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
check("int f(ABC *p) {\n" // FP : return &&
|
||||
" if (!p) {}\n"
|
||||
|
@ -1734,7 +1734,7 @@ private:
|
|||
" if (x || !p) {}\n"
|
||||
" *p = 0;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition '!p' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
// sizeof
|
||||
check("void f() {\n"
|
||||
|
@ -2131,7 +2131,7 @@ private:
|
|||
"}", false);
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference: p\n"
|
||||
"[test.cpp:4]: (error) Null pointer dereference: p\n"
|
||||
"[test.cpp:6] -> [test.cpp:5]: (warning) Either the condition 'q==0' is redundant or there is possible null pointer dereference: q.\n", errout.str());
|
||||
"[test.cpp:5] -> [test.cpp:6]: (warning) Either the condition 'q==0' is redundant or there is possible null pointer dereference: q.\n", errout.str());
|
||||
|
||||
check("void f(const char* p) {\n"
|
||||
" if(p == 0) {\n"
|
||||
|
@ -2141,12 +2141,12 @@ private:
|
|||
" std::cout << abc << p;\n"
|
||||
" }\n"
|
||||
"}", false);
|
||||
TODO_ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n"
|
||||
"[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n"
|
||||
"[test.cpp:5] -> [test.cpp:2]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n"
|
||||
"[test.cpp:6] -> [test.cpp:2]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n",
|
||||
"[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n"
|
||||
"[test.cpp:4] -> [test.cpp:2]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n",
|
||||
TODO_ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n"
|
||||
"[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n"
|
||||
"[test.cpp:2] -> [test.cpp:5]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n"
|
||||
"[test.cpp:2] -> [test.cpp:6]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n",
|
||||
"[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n"
|
||||
"[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'p==0' is redundant or there is possible null pointer dereference: p.\n",
|
||||
errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
|
@ -2210,7 +2210,7 @@ private:
|
|||
" foo(p);\n"
|
||||
" if (p) { }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
// function seen (taking reference parameter)
|
||||
check("void foo(int *&p) { }\n"
|
||||
|
@ -2230,7 +2230,7 @@ private:
|
|||
" foo(p);\n"
|
||||
" if (p) { }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
|
||||
// inconclusive
|
||||
check("void f(int *p) {\n"
|
||||
|
@ -2238,7 +2238,7 @@ private:
|
|||
" foo(p);\n"
|
||||
" if (p) { }\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning, inconclusive) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'if(p)' is redundant or there is possible null pointer dereference: p.\n", errout.str());
|
||||
}
|
||||
|
||||
// dereference struct pointer and then check if it's null
|
||||
|
@ -2259,7 +2259,7 @@ private:
|
|||
" foo(abc);\n"
|
||||
" if (abc) { }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
|
||||
// function implementation not seen
|
||||
check("void foo(struct ABC *abc);\n"
|
||||
|
@ -2269,7 +2269,7 @@ private:
|
|||
" foo(abc);\n"
|
||||
" if (abc) { }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:6]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
|
||||
// inconclusive
|
||||
check("void f(struct ABC *abc) {\n"
|
||||
|
@ -2277,7 +2277,7 @@ private:
|
|||
" foo(abc);\n"
|
||||
" if (abc) { }\n"
|
||||
"}", true);
|
||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning, inconclusive) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (warning, inconclusive) Either the condition 'if(abc)' is redundant or there is possible null pointer dereference: abc.\n", errout.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue