Remove ExecutionPath from CheckNullPointer

This commit is contained in:
Daniel Marjamäki 2014-01-22 20:24:51 +01:00
parent f3f7e6d302
commit 1d7bb05faf
3 changed files with 0 additions and 212 deletions

View File

@ -19,7 +19,6 @@
//---------------------------------------------------------------------------
#include "checknullpointer.h"
#include "executionpath.h"
#include "mathlib.h"
#include "symboldatabase.h"
#include <cctype>
@ -1038,212 +1037,6 @@ void CheckNullPointer::nullPointerDefaultArgument()
/// @{
/**
* @brief %Check for null pointer usage (using ExecutionPath)
*/
class Nullpointer : public ExecutionPath {
public:
/** Startup constructor */
Nullpointer(Check *c, const SymbolDatabase* symbolDatabase_, const Library *lib) : ExecutionPath(c, 0), symbolDatabase(symbolDatabase_), library(lib), null(false) {
}
private:
const SymbolDatabase* symbolDatabase;
const Library *library;
/** Create checking of specific variable: */
Nullpointer(Check *c, const unsigned int id, const std::string &name, const SymbolDatabase* symbolDatabase_, const Library *lib)
: ExecutionPath(c, id),
symbolDatabase(symbolDatabase_),
library(lib),
varname(name),
null(false) {
}
/** Copy this check */
ExecutionPath *copy() {
return new Nullpointer(*this);
}
/** no implementation => compiler error if used by accident */
void operator=(const Nullpointer &);
/** is other execution path equal? */
bool is_equal(const ExecutionPath *e) const {
const Nullpointer *c = static_cast<const Nullpointer *>(e);
return (varname == c->varname && null == c->null);
}
/** variable name for this check (empty => dummy check) */
const std::string varname;
/** is this variable null? */
bool null;
/** variable is set to null */
static void setnull(std::list<ExecutionPath *> &checks, const unsigned int varid, bool null) {
std::list<ExecutionPath *>::iterator it;
for (it = checks.begin(); it != checks.end(); ++it) {
Nullpointer *c = dynamic_cast<Nullpointer *>(*it);
if (c && c->varId == varid)
c->null = null;
}
}
/**
* Dereferencing variable. Check if it is safe (if the variable is null there's an error)
* @param checks Checks
* @param tok token where dereferencing happens
*/
static void dereference(std::list<ExecutionPath *> &checks, const Token *tok) {
const unsigned int varid(tok->varId());
std::list<ExecutionPath *>::iterator it;
for (it = checks.begin(); it != checks.end(); ++it) {
Nullpointer *c = dynamic_cast<Nullpointer *>(*it);
if (c && c->varId == varid && c->null) {
for (const Token *tok2 = tok; tok2 && tok2->str() != ";"; tok2 = tok2->previous()) {
// Checking that pointer is not NULL
if (Token::Match(tok2, "return|=|[|(|,|&& %varid% )| &&", varid))
return;
if (Token::Match(tok2, "return|=|[|(|,|%oror% ! %varid% )| %oror%", varid))
return;
}
CheckNullPointer *checkNullPointer = dynamic_cast<CheckNullPointer *>(c->owner);
if (checkNullPointer) {
checkNullPointer->nullPointerError(tok, c->varname);
return;
}
}
}
}
/** parse tokens */
const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const {
if (tok.varId() != 0) {
// Pointer declaration declaration?
const Variable *var = tok.variable();
if (var && var->isPointer() && var->nameToken() == &tok)
checks.push_back(new Nullpointer(owner, var->declarationId(), var->name(), symbolDatabase, library));
}
if (Token::simpleMatch(&tok, "try {")) {
// Bail out all used variables
const Token* tok2 = &tok;
const Token* endtok = tok.linkAt(1);
for (; tok2 && tok2 != endtok; tok2 = tok2->next()) {
if (tok2->varId())
bailOutVar(checks,tok2->varId());
}
return tok2;
}
if (Token::Match(&tok, "%var% (")) {
if (tok.str() == "sizeof" || tok.str() == "typeid")
return tok.next()->link();
// parse usage..
std::list<const Token *> var;
CheckNullPointer::parseFunctionCall(tok, var, library, 0);
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it)
dereference(checks, *it);
}
else if (Token::simpleMatch(&tok, "( 0 &&"))
return tok.link();
if (tok.varId() != 0) {
// unknown: if isPointerDeRef fails to determine if there
// is a dereference this will be set to true.
bool unknown = owner->inconclusiveFlag();
bool deref = CheckNullPointer::isPointerDeRef(&tok, unknown);
if (deref)
dereference(checks, &tok);
else if (unknown && owner->inconclusiveFlag())
dereference(checks, &tok);
if (Token::Match(tok.previous(), "[;{}=] %var% ="))
setnull(checks, tok.varId(), Token::simpleMatch(tok.tokAt(2), "0 ;"));
else if (!deref &&
(!tok.previous()->isOp() || tok.previous()->str() == "&") &&
(!tok.next()->isConstOp() || tok.next()->str() == ">>"))
bailOutVar(checks, tok.varId()); // If its possible that the pointers value changes, bail out.
}
else if (tok.str() == "delete") {
const Token *ret = tok.next();
if (Token::simpleMatch(ret, "[ ]"))
ret = ret->tokAt(2);
if (Token::Match(ret, "%var% ;"))
return ret->next();
}
else if (tok.str() == "return") {
bool unknown = owner->inconclusiveFlag();
const Token* tok2 = &tok;
for (; tok2 && tok2->str() != ";"; tok2 = tok2->next()) {
if (tok2->varId()) {
if (CheckNullPointer::isPointerDeRef(tok2, unknown) || unknown)
dereference(checks, tok2);
}
// If return statement contains "?" then assume there
// is no dangours dereferencing later
if (tok2->str() == "?") {
while (tok2 && tok2->str() != ";")
tok2 = tok2->next();
return tok2;
}
}
}
return &tok;
}
/** parse condition. @sa ExecutionPath::parseCondition */
bool parseCondition(const Token &tok, std::list<ExecutionPath *> &checks) {
for (const Token *tok2 = &tok; tok2; tok2 = tok2->next()) {
if (tok2->str() == "(" || tok2->str() == ")" || tok2->str() == "&&" || tok2->str() == "||" || tok2->str() == "?")
break;
bool unknown = owner->inconclusiveFlag();
if (tok2->varId() && (CheckNullPointer::isPointerDeRef(tok2, unknown) || unknown))
dereference(checks, tok2);
}
if (Token::Match(&tok, "!| %var% (")) {
std::list<const Token *> var;
CheckNullPointer::parseFunctionCall(tok.str() == "!" ? *tok.next() : tok, var, library, 0);
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it)
dereference(checks, *it);
}
return ExecutionPath::parseCondition(tok, checks);
}
void parseLoopBody(const Token *tok, std::list<ExecutionPath *> &checks) const {
while (tok) {
if (Token::Match(tok, "{|}|return|goto|break|if"))
return;
const Token *next = parse(*tok, checks);
if (next)
tok = tok->next();
}
}
};
/// @}
void CheckNullPointer::executionPaths()
{
// Check for null pointer errors..
Nullpointer c(this, _tokenizer->getSymbolDatabase(), &_settings->library);
checkExecutionPaths(_tokenizer->getSymbolDatabase(), &c);
}
void CheckNullPointer::nullPointerError(const Token *tok)
{
reportError(tok, Severity::error, "nullPointer", "Null pointer dereference");

View File

@ -56,7 +56,6 @@ public:
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
CheckNullPointer checkNullPointer(tokenizer, settings, errorLogger);
checkNullPointer.nullConstantDereference();
checkNullPointer.executionPaths();
}
/**
@ -95,9 +94,6 @@ public:
/** @brief dereferencing null constant (after Tokenizer::simplifyKnownVariables) */
void nullConstantDereference();
/** @brief new type of check: check execution paths */
void executionPaths();
void nullPointerError(const Token *tok); // variable name unknown / doesn't exist
void nullPointerError(const Token *tok, const std::string &varname, bool inconclusive=false);
void nullPointerError(const Token *tok, const std::string &varname, const Token* nullcheck, bool inconclusive = false);

View File

@ -113,7 +113,6 @@ private:
"TestSimplifyTokens instead.\nstr1="+str1+"\nstr2="+str2).c_str());
checkNullPointer.nullConstantDereference();
//checkNullPointer.executionPaths();
}