From 8790f6d73f9fd61fde487a5803f2c6a0599ce7fc Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Sat, 31 Aug 2013 18:58:55 +0200 Subject: [PATCH] Fixed #4999 (Crash with simple code snipped in rev ab30fa3) --- lib/checkio.cpp | 10 ++++++---- lib/symboldatabase.cpp | 35 ++++++++++++++++++----------------- lib/symboldatabase.h | 2 +- lib/tokenize.cpp | 8 +++++--- test/testio.cpp | 7 +++++++ 5 files changed, 37 insertions(+), 25 deletions(-) diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 1bd0d474a..fb7ab30a1 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -792,23 +792,25 @@ bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Tok varTok = tok1->linkAt(-1)->previous(); if (varTok->str() == ")" && varTok->link()->previous()->type() == Token::eFunction) { const Function * function = varTok->link()->previous()->function(); - if (function) { + if (function && function->retDef) { *var = 0; *typeTok = function->retDef; *func = function; element = true; return true; - } + } else + return false; } } else if (tok1->previous()->str() == ")" && tok1->linkAt(-1)->previous()->type() == Token::eFunction) { const Function * function = tok1->linkAt(-1)->previous()->function(); - if (function) { + if (function && function->retDef) { *var = 0; *typeTok = function->retDef; *func = function; element = false; return true; - } + } else + return false; } else varTok = tok1->previous(); break; diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 1b917fbea..64aafd93b 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -612,9 +612,10 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti break; } } + // save function prototype in database if (newFunc) - addGlobalFunctionDecl(scope, argStart, funcStart); + addGlobalFunctionDecl(scope, tok, argStart, funcStart); tok = argStart->link()->next(); continue; @@ -630,7 +631,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti } // save function prototype in database if (newFunc) { - Function* func = addGlobalFunctionDecl(scope, argStart, funcStart); + Function* func = addGlobalFunctionDecl(scope, tok, argStart, funcStart); func->retFuncPtr = true; } @@ -1243,25 +1244,12 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co } if (!function) - function = addGlobalFunctionDecl(scope, argStart, funcStart); + function = addGlobalFunctionDecl(scope, tok, argStart, funcStart); function->arg = argStart; function->token = funcStart; function->hasBody = true; - const Token *tok1 = tok; - - // look for end of previous statement - while (tok1->previous() && !Token::Match(tok1->previous(), ";|}|{")) - tok1 = tok1->previous(); - - // find the return type - while (tok1 && Token::Match(tok1->next(), "static|const")) - tok1 = tok1->next(); - - if (tok1) - function->retDef = tok1; - addNewFunction(&scope, &tok); if (scope) { @@ -1272,7 +1260,7 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co return 0; } -Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *argStart, const Token* funcStart) +Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *tok, const Token *argStart, const Token* funcStart) { Function function; @@ -1290,6 +1278,19 @@ Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *argS function.type = Function::eFunction; function.nestedIn = scope; + const Token *tok1 = tok; + + // look for end of previous statement + while (tok1->previous() && !Token::Match(tok1->previous(), ";|}|{")) + tok1 = tok1->previous(); + + // find the return type + while (tok1 && Token::Match(tok1->next(), "static|const")) + tok1 = tok1->next(); + + if (tok1) + function.retDef = tok1; + scope->functionList.push_back(function); return &scope->functionList.back(); } diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index f1200849a..4ba897213 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -742,7 +742,7 @@ private: friend class Scope; void addClassFunction(Scope **info, const Token **tok, const Token *argStart); - Function *addGlobalFunctionDecl(Scope*& scope, const Token *argStart, const Token* funcStart); + Function *addGlobalFunctionDecl(Scope*& scope, const Token* tok, const Token *argStart, const Token* funcStart); Function *addGlobalFunction(Scope*& scope, const Token*& tok, const Token *argStart, const Token* funcStart); void addNewFunction(Scope **info, const Token **tok); static bool isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart); diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 6cbfd8edb..5c2a17bc1 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -9577,9 +9577,11 @@ void Tokenizer::createSymbolDatabase() if (membertok) { const Variable *var = tok->variable(); - const Variable *membervar = var->typeScope()->getVariable(membertok->str()); - if (membervar) - membertok->variable(membervar); + if (var && var->typeScope()) { + const Variable *membervar = var->typeScope()->getVariable(membertok->str()); + if (membervar) + membertok->variable(membervar); + } } } diff --git a/test/testio.cpp b/test/testio.cpp index 86c002463..acffcccbd 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -1074,6 +1074,13 @@ private: ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'int'.\n" "[test.cpp:3]: (warning) %f in format string (no. 3) requires a floating point number but the argument type is 'int'.\n", errout.str()); + // #4999 (crash) + check("int bar(int a);\n" + "void foo() {\n" + " printf(\"%d\", bar(0));\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } void testPosixPrintfScanfParameterPosition() { // #4900 - No support for parameters in format strings