- Solved FIXME: Made detection of code that is no pointer-dereference more robust, uncommented code (checknullpointer.cpp)
- Removed more indendation level counters - Make use of symbol database more often - Other refactorizations
This commit is contained in:
parent
87e19d2552
commit
36479499e7
|
@ -119,7 +119,8 @@ void CheckInternal::checkTokenSimpleMatchPatterns()
|
|||
|
||||
void CheckInternal::checkMissingPercentCharacter()
|
||||
{
|
||||
std::set<std::string> magics;
|
||||
static std::set<std::string> magics;
|
||||
if (magics.empty()) {
|
||||
magics.insert("%any%");
|
||||
magics.insert("%var%");
|
||||
magics.insert("%type%");
|
||||
|
@ -129,6 +130,7 @@ void CheckInternal::checkMissingPercentCharacter()
|
|||
magics.insert("%varid%");
|
||||
magics.insert("%or%");
|
||||
magics.insert("%oror%");
|
||||
}
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (!Token::simpleMatch(tok, "Token :: Match (") && !Token::simpleMatch(tok, "Token :: findmatch ("))
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace {
|
|||
bool CheckNullPointer::isUpper(const std::string &str)
|
||||
{
|
||||
for (unsigned int i = 0; i < str.length(); ++i) {
|
||||
if (str[i] >= 'a' && str[i] <= 'z')
|
||||
if (std::islower(str[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -234,10 +234,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (Token::Match(tok->previous(), "[;{}=+-/(,] %var% ["))
|
||||
return true;
|
||||
|
||||
if (Token::Match(tok->previous(), "return %var% ["))
|
||||
if (Token::Match(tok->previous(), "!!& %var% ["))
|
||||
return true;
|
||||
|
||||
if (Token::Match(tok, "%var% ("))
|
||||
|
@ -252,7 +249,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
|||
// This is most useful in inconclusive checking
|
||||
if (inconclusive) {
|
||||
// Not a dereference..
|
||||
if (Token::Match(tok->previous(), "[;{}(] %var% ="))
|
||||
if (Token::Match(tok, "%var% ="))
|
||||
return false;
|
||||
|
||||
// OK to delete a null
|
||||
|
@ -261,7 +258,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
|||
|
||||
// OK to check if pointer is null
|
||||
// OK to take address of pointer
|
||||
if (Token::Match(tok->previous(), "!|& %var% )|,|&&|%oror%"))
|
||||
if (Token::Match(tok->previous(), "!|& %var%"))
|
||||
return false;
|
||||
|
||||
// OK to pass pointer to function
|
||||
|
@ -269,7 +266,9 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
|||
return false;
|
||||
|
||||
// Compare pointer
|
||||
if (Token::Match(tok->previous(), "(|&&|%oror%|==|!= %var% &&|%oror%|)"))
|
||||
if (Token::Match(tok->previous(), "(|&&|%oror%|==|!= %var%"))
|
||||
return false;
|
||||
if (Token::Match(tok, "%var% &&|%oror%|==|!=|)"))
|
||||
return false;
|
||||
|
||||
// Taking address
|
||||
|
@ -277,11 +276,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
|||
return false;
|
||||
|
||||
// unknown if it's a dereference
|
||||
// FIXME: Uncomment this. We just need to fix false positives
|
||||
// when cppcheck source code is checked before it can
|
||||
// be uncommented. We need to have better checks to
|
||||
// determine when there is NOT a pointer dereference.
|
||||
//unknown = true;
|
||||
unknown = true;
|
||||
}
|
||||
|
||||
// assume that it's not a dereference (no false positives)
|
||||
|
@ -292,7 +287,7 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown)
|
|||
// check if function can assign pointer
|
||||
bool CheckNullPointer::CanFunctionAssignPointer(const Token *functiontoken, unsigned int varid) const
|
||||
{
|
||||
if (Token::Match(functiontoken, "if|while|sizeof"))
|
||||
if (Token::Match(functiontoken, "if|while|for|switch|sizeof|catch"))
|
||||
return false;
|
||||
|
||||
int argumentNumber = 0;
|
||||
|
@ -434,7 +429,7 @@ void CheckNullPointer::nullPointerLinkedList()
|
|||
const std::string varname(tok2->str());
|
||||
|
||||
// Check usage of dereferenced variable in the loop..
|
||||
for (const Token *tok3 = i->classStart; tok3 && tok3 != i->classEnd; tok3 = tok3->next()) {
|
||||
for (const Token *tok3 = i->classStart->next(); tok3 && tok3 != i->classEnd; tok3 = tok3->next()) {
|
||||
// TODO: are there false negatives for "while ( %varid% ||"
|
||||
if (Token::Match(tok3, "while ( %varid% &&|)", varid)) {
|
||||
// Make sure there is a "break" or "return" inside the loop.
|
||||
|
@ -801,25 +796,24 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
|||
|
||||
void CheckNullPointer::nullPointerByCheckAndDeRef()
|
||||
{
|
||||
// Check if pointer is NULL and then dereference it..
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (Token::simpleMatch(tok, "if (") && !tok->isExpandedMacro()) {
|
||||
// Check if pointer is NULL and then dereference it..
|
||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||
if (i->type != Scope::eIf && i->type != Scope::eElseIf && i->type != Scope::eWhile)
|
||||
continue;
|
||||
if (!i->classDef || i->classDef->isExpandedMacro())
|
||||
continue;
|
||||
|
||||
const Token* const tok = i->type != Scope::eElseIf ? i->classDef : i->classDef->next();
|
||||
// TODO: investigate false negatives:
|
||||
// - handle "while"?
|
||||
// - if there are logical operators
|
||||
// - if (x) { } else { ... }
|
||||
|
||||
// If the if-body ends with a unknown macro then bailout
|
||||
{
|
||||
// goto the end parenthesis
|
||||
const Token *endpar = tok->next()->link();
|
||||
const Token *endbody = Token::simpleMatch(endpar, ") {") ? endpar->next()->link() : 0;
|
||||
if (endbody &&
|
||||
Token::Match(endbody->tokAt(-3), "[;{}] %var% ;") &&
|
||||
isUpper(endbody->strAt(-2)))
|
||||
if (Token::Match(i->classEnd->tokAt(-3), "[;{}] %var% ;") && isUpper(i->classEnd->strAt(-2)))
|
||||
continue;
|
||||
}
|
||||
|
||||
// vartok : token for the variable
|
||||
const Token *vartok = 0;
|
||||
|
@ -851,25 +845,20 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
|||
bool null = true;
|
||||
|
||||
// start token = inside the if-body
|
||||
const Token *tok1 = tok->next()->link()->tokAt(2);
|
||||
|
||||
// indentlevel inside the if-body is 1
|
||||
unsigned int indentlevel = 1;
|
||||
const Token *tok1 = i->classStart;
|
||||
|
||||
if (Token::Match(tok, "if|while ( %var% )|&&")) {
|
||||
// pointer might be null
|
||||
null = false;
|
||||
|
||||
// start token = first token after the if/while body
|
||||
tok1 = tok1->previous()->link();
|
||||
tok1 = tok1 ? tok1->next() : NULL;
|
||||
tok1 = i->classEnd->next();
|
||||
if (!tok1)
|
||||
continue;
|
||||
|
||||
// indentlevel at the base level is 0
|
||||
indentlevel = 0;
|
||||
}
|
||||
|
||||
unsigned int indentlevel = 0;
|
||||
|
||||
// Name of the pointer
|
||||
const std::string &pointerName = vartok->str();
|
||||
|
||||
|
@ -972,7 +961,6 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CheckNullPointer::nullPointer()
|
||||
|
@ -987,25 +975,13 @@ void CheckNullPointer::nullPointer()
|
|||
/** Dereferencing null constant (simplified token list) */
|
||||
void CheckNullPointer::nullConstantDereference()
|
||||
{
|
||||
// this is kept at 0 for all scopes that are not executing
|
||||
unsigned int indentlevel = 0;
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
// start of executable scope..
|
||||
if (indentlevel == 0 && Token::Match(tok, ") const| {"))
|
||||
indentlevel = 1;
|
||||
|
||||
else if (indentlevel >= 1) {
|
||||
if (tok->str() == "{")
|
||||
++indentlevel;
|
||||
|
||||
else if (tok->str() == "}") {
|
||||
if (indentlevel <= 2)
|
||||
indentlevel = 0;
|
||||
else
|
||||
--indentlevel;
|
||||
}
|
||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||
if (i->type != Scope::eFunction || !i->classStart)
|
||||
continue;
|
||||
|
||||
for (const Token *tok = i->classStart; tok != i->classEnd; tok = tok->next()) {
|
||||
if (tok->str() == "(" && Token::Match(tok->previous(), "sizeof|decltype|typeid"))
|
||||
tok = tok->link();
|
||||
|
||||
|
@ -1015,7 +991,7 @@ void CheckNullPointer::nullConstantDereference()
|
|||
}
|
||||
}
|
||||
|
||||
else if (indentlevel > 0 && Token::Match(tok->previous(), "[={};] %var% (")) {
|
||||
else if (Token::Match(tok->previous(), "[={};] %var% (")) {
|
||||
std::list<const Token *> var;
|
||||
parseFunctionCall(*tok, var, 0);
|
||||
|
||||
|
|
|
@ -599,8 +599,7 @@ void CheckOther::checkSwitchCaseFallThrough()
|
|||
const char breakPattern[] = "break|continue|return|exit|goto|throw";
|
||||
|
||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||
const Token* const tok = i->classDef;
|
||||
if (i->type != Scope::eSwitch || !tok) // Find the beginning of a switch
|
||||
if (i->type != Scope::eSwitch || !i->classStart) // Find the beginning of a switch
|
||||
continue;
|
||||
|
||||
// Check the contents of the switch statement
|
||||
|
@ -609,7 +608,7 @@ void CheckOther::checkSwitchCaseFallThrough()
|
|||
std::stack<Token *> scopenest;
|
||||
bool justbreak = true;
|
||||
bool firstcase = true;
|
||||
for (const Token *tok2 = tok->next()->link()->tokAt(2); tok2; tok2 = tok2->next()) {
|
||||
for (const Token *tok2 = i->classStart; tok2 != i->classEnd; tok2 = tok2->next()) {
|
||||
if (Token::simpleMatch(tok2, "if (")) {
|
||||
tok2 = tok2->next()->link()->next();
|
||||
if (tok2->link() == NULL) {
|
||||
|
@ -827,11 +826,11 @@ void CheckOther::checkAssignmentInAssert()
|
|||
const Token *endTok = tok ? tok->next()->link() : NULL;
|
||||
|
||||
while (tok && endTok) {
|
||||
const Token* varTok = Token::findmatch(tok->tokAt(2), "%var% --|++|+=|-=|*=|/=|&=|^=|=", endTok);
|
||||
if (varTok) {
|
||||
assignmentInAssertError(tok, varTok->str());
|
||||
} else if (NULL != (varTok = Token::findmatch(tok->tokAt(2), "--|++ %var%", endTok))) {
|
||||
assignmentInAssertError(tok, varTok->strAt(1));
|
||||
for (tok = tok->tokAt(2); tok != endTok; tok = tok->next()) {
|
||||
if (tok->isName() && (tok->next()->isAssignmentOp() || tok->next()->str() == "++" || tok->next()->str() == "--"))
|
||||
assignmentInAssertError(tok, tok->str());
|
||||
else if (Token::Match(tok, "--|++ %var%"))
|
||||
assignmentInAssertError(tok, tok->strAt(1));
|
||||
}
|
||||
|
||||
tok = Token::findmatch(endTok->next(), assertPattern);
|
||||
|
@ -1638,7 +1637,7 @@ void CheckOther::checkUnreachableCode()
|
|||
// that the goto jump was intended to skip some code on the first loop iteration.
|
||||
bool labelInFollowingLoop = false;
|
||||
if (labelName && Token::Match(secondBreak, "while|do|for")) {
|
||||
const Token *scope = Token::findmatch(secondBreak, "{");
|
||||
const Token *scope = Token::findsimplematch(secondBreak, "{");
|
||||
if (scope) {
|
||||
for (const Token *tokIter = scope; tokIter != scope->link() && tokIter; tokIter = tokIter->next()) {
|
||||
if (Token::Match(tokIter, "[;{}] %any% :") && labelName->str() == tokIter->strAt(1)) {
|
||||
|
@ -2270,24 +2269,12 @@ void CheckOther::checkMisusedScopedObject()
|
|||
|
||||
const SymbolDatabase * const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
std::list<Scope>::const_iterator scope;
|
||||
|
||||
for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
|
||||
for (std::list<Scope>::const_iterator scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
|
||||
// only check functions
|
||||
if (scope->type != Scope::eFunction)
|
||||
continue;
|
||||
|
||||
unsigned int depth = 0;
|
||||
|
||||
for (const Token *tok = scope->classStart; tok; tok = tok->next()) {
|
||||
if (tok->str() == "{") {
|
||||
++depth;
|
||||
} else if (tok->str() == "}") {
|
||||
if (depth <= 1)
|
||||
break;
|
||||
--depth;
|
||||
}
|
||||
|
||||
for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
|
||||
if (Token::Match(tok, "[;{}] %var% (")
|
||||
&& Token::simpleMatch(tok->linkAt(2), ") ;")
|
||||
&& symbolDatabase->isClassOrStruct(tok->next()->str())
|
||||
|
@ -2484,15 +2471,15 @@ void CheckOther::checkDuplicateBranch()
|
|||
//-----------------------------------------------------------------------------
|
||||
void CheckOther::checkDoubleFree()
|
||||
{
|
||||
std::set<int> freedVariables;
|
||||
std::set<int> closeDirVariables;
|
||||
std::set<unsigned int> freedVariables;
|
||||
std::set<unsigned int> closeDirVariables;
|
||||
|
||||
for (const Token* tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
|
||||
// Keep track of any variables passed to "free()", "g_free()" or "closedir()",
|
||||
// and report an error if the same variable is passed twice.
|
||||
if (Token::Match(tok, "free|g_free|closedir ( %var% )")) {
|
||||
int var = tok->tokAt(2)->varId();
|
||||
unsigned int var = tok->tokAt(2)->varId();
|
||||
if (var) {
|
||||
if (Token::Match(tok, "free|g_free")) {
|
||||
if (freedVariables.find(var) != freedVariables.end())
|
||||
|
@ -2512,7 +2499,7 @@ void CheckOther::checkDoubleFree()
|
|||
// and report an error if the same variable is delete'd twice.
|
||||
else if (Token::Match(tok, "delete %var% ;") || Token::Match(tok, "delete [ ] %var% ;")) {
|
||||
int varIdx = (tok->strAt(1) == "[") ? 3 : 1;
|
||||
int var = tok->tokAt(varIdx)->varId();
|
||||
unsigned int var = tok->tokAt(varIdx)->varId();
|
||||
if (var) {
|
||||
if (freedVariables.find(var) != freedVariables.end())
|
||||
doubleFreeError(tok, tok->tokAt(varIdx)->str());
|
||||
|
@ -2531,7 +2518,7 @@ void CheckOther::checkDoubleFree()
|
|||
else if (Token::Match(tok, "%var% (") && !Token::Match(tok, "printf|sprintf|snprintf|fprintf")) {
|
||||
for (const Token* tok2 = tok->tokAt(2); tok2 != tok->linkAt(1); tok2 = tok2->next()) {
|
||||
if (Token::Match(tok2, "%var%")) {
|
||||
int var = tok2->varId();
|
||||
unsigned int var = tok2->varId();
|
||||
if (var) {
|
||||
freedVariables.erase(var);
|
||||
closeDirVariables.erase(var);
|
||||
|
@ -2542,7 +2529,7 @@ void CheckOther::checkDoubleFree()
|
|||
|
||||
// If a pointer is assigned a new value, remove it from the set of previously freed variables
|
||||
else if (Token::Match(tok, "%var% =")) {
|
||||
int var = tok->varId();
|
||||
unsigned int var = tok->varId();
|
||||
if (var) {
|
||||
freedVariables.erase(var);
|
||||
closeDirVariables.erase(var);
|
||||
|
|
|
@ -79,7 +79,8 @@ std::string Settings::addEnabled(const std::string &str)
|
|||
|
||||
bool handled = false;
|
||||
|
||||
std::set<std::string> id;
|
||||
static std::set<std::string> id;
|
||||
if (id.empty()) {
|
||||
id.insert("style");
|
||||
id.insert("performance");
|
||||
id.insert("portability");
|
||||
|
@ -89,6 +90,7 @@ std::string Settings::addEnabled(const std::string &str)
|
|||
#ifndef NDEBUG
|
||||
id.insert("internal");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (str == "all") {
|
||||
std::set<std::string>::const_iterator it;
|
||||
|
|
|
@ -83,15 +83,15 @@ const Token* TemplateSimplifier::hasComplicatedSyntaxErrorsInTemplates(Token *to
|
|||
}
|
||||
|
||||
// skip executing scopes (ticket #1984)..
|
||||
if (Token::simpleMatch(tok, "; {"))
|
||||
else if (Token::simpleMatch(tok, "; {"))
|
||||
tok = tok->next()->link();
|
||||
|
||||
// skip executing scopes (ticket #3183)..
|
||||
if (Token::simpleMatch(tok, "( {"))
|
||||
else if (Token::simpleMatch(tok, "( {"))
|
||||
tok = tok->next()->link();
|
||||
|
||||
// skip executing scopes (ticket #1985)..
|
||||
if (Token::simpleMatch(tok, "try {")) {
|
||||
else if (Token::simpleMatch(tok, "try {")) {
|
||||
tok = tok->next()->link();
|
||||
while (Token::simpleMatch(tok, "} catch (")) {
|
||||
tok = tok->linkAt(2);
|
||||
|
|
|
@ -2392,7 +2392,7 @@ bool Tokenizer::hasEnumsWithTypedef()
|
|||
for (const Token *tok = _tokens; tok; tok = tok->next()) {
|
||||
if (Token::Match(tok, "enum %var% {")) {
|
||||
tok = tok->tokAt(2);
|
||||
const Token *tok2 = Token::findmatch(tok, "typedef", tok->link());
|
||||
const Token *tok2 = Token::findsimplematch(tok, "typedef", tok->link());
|
||||
if (tok2) {
|
||||
syntaxError(tok2);
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue