Fixed #4999 (Crash with simple code snipped in rev ab30fa3)

This commit is contained in:
Robert Reif 2013-08-31 18:58:55 +02:00 committed by Daniel Marjamäki
parent 6b260c481c
commit 8790f6d73f
5 changed files with 37 additions and 25 deletions

View File

@ -792,23 +792,25 @@ bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Tok
varTok = tok1->linkAt(-1)->previous(); varTok = tok1->linkAt(-1)->previous();
if (varTok->str() == ")" && varTok->link()->previous()->type() == Token::eFunction) { if (varTok->str() == ")" && varTok->link()->previous()->type() == Token::eFunction) {
const Function * function = varTok->link()->previous()->function(); const Function * function = varTok->link()->previous()->function();
if (function) { if (function && function->retDef) {
*var = 0; *var = 0;
*typeTok = function->retDef; *typeTok = function->retDef;
*func = function; *func = function;
element = true; element = true;
return true; return true;
} } else
return false;
} }
} else if (tok1->previous()->str() == ")" && tok1->linkAt(-1)->previous()->type() == Token::eFunction) { } else if (tok1->previous()->str() == ")" && tok1->linkAt(-1)->previous()->type() == Token::eFunction) {
const Function * function = tok1->linkAt(-1)->previous()->function(); const Function * function = tok1->linkAt(-1)->previous()->function();
if (function) { if (function && function->retDef) {
*var = 0; *var = 0;
*typeTok = function->retDef; *typeTok = function->retDef;
*func = function; *func = function;
element = false; element = false;
return true; return true;
} } else
return false;
} else } else
varTok = tok1->previous(); varTok = tok1->previous();
break; break;

View File

@ -612,9 +612,10 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
break; break;
} }
} }
// save function prototype in database // save function prototype in database
if (newFunc) if (newFunc)
addGlobalFunctionDecl(scope, argStart, funcStart); addGlobalFunctionDecl(scope, tok, argStart, funcStart);
tok = argStart->link()->next(); tok = argStart->link()->next();
continue; continue;
@ -630,7 +631,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
} }
// save function prototype in database // save function prototype in database
if (newFunc) { if (newFunc) {
Function* func = addGlobalFunctionDecl(scope, argStart, funcStart); Function* func = addGlobalFunctionDecl(scope, tok, argStart, funcStart);
func->retFuncPtr = true; func->retFuncPtr = true;
} }
@ -1243,25 +1244,12 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co
} }
if (!function) if (!function)
function = addGlobalFunctionDecl(scope, argStart, funcStart); function = addGlobalFunctionDecl(scope, tok, argStart, funcStart);
function->arg = argStart; function->arg = argStart;
function->token = funcStart; function->token = funcStart;
function->hasBody = true; 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); addNewFunction(&scope, &tok);
if (scope) { if (scope) {
@ -1272,7 +1260,7 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co
return 0; 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; Function function;
@ -1290,6 +1278,19 @@ Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *argS
function.type = Function::eFunction; function.type = Function::eFunction;
function.nestedIn = scope; 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); scope->functionList.push_back(function);
return &scope->functionList.back(); return &scope->functionList.back();
} }

View File

@ -742,7 +742,7 @@ private:
friend class Scope; friend class Scope;
void addClassFunction(Scope **info, const Token **tok, const Token *argStart); 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); Function *addGlobalFunction(Scope*& scope, const Token*& tok, const Token *argStart, const Token* funcStart);
void addNewFunction(Scope **info, const Token **tok); void addNewFunction(Scope **info, const Token **tok);
static bool isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart); static bool isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart);

View File

@ -9577,11 +9577,13 @@ void Tokenizer::createSymbolDatabase()
if (membertok) { if (membertok) {
const Variable *var = tok->variable(); const Variable *var = tok->variable();
if (var && var->typeScope()) {
const Variable *membervar = var->typeScope()->getVariable(membertok->str()); const Variable *membervar = var->typeScope()->getVariable(membertok->str());
if (membervar) if (membervar)
membertok->variable(membervar); membertok->variable(membervar);
} }
} }
}
// check for function returning record type // check for function returning record type
// func(...).var // func(...).var

View File

@ -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" 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()); "[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 void testPosixPrintfScanfParameterPosition() { // #4900 - No support for parameters in format strings