Fixed #7441 (SymbolDatabase: No scope when function return type not specified)

This commit is contained in:
Robert Reif 2017-01-06 11:53:17 +01:00 committed by Daniel Marjamäki
parent 8eeb09ba88
commit 4123b457d7
6 changed files with 52 additions and 19 deletions

View File

@ -1559,6 +1559,20 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
}
}
// regular C function with missing return or invalid C++ ?
else if (Token::Match(tok, "%name% (") && !isReservedName(tok->str()) &&
Token::simpleMatch(tok->linkAt(1), ") {") &&
(!tok->previous() || Token::Match(tok->previous(), ";|}"))) {
if (_tokenizer->isC()) {
debugMessage(tok, "SymbolDatabase::isFunction found C function '" + tok->str() + "' without a return type.");
*funcStart = tok;
*argStart = tok->next();
*declEnd = tok->linkAt(1)->next();
return true;
}
_tokenizer->syntaxError(tok);
}
return false;
}

View File

@ -482,13 +482,13 @@ private:
void garbageCode24() {
// don't crash (example from #6361)
checkCode("float buffer[64];\n"
ASSERT_THROW(checkCode("float buffer[64];\n"
"main (void)\n"
"{\n"
" char *cptr;\n"
" cptr = (char *)buffer;\n"
" cptr += (-(long int) buffer & (16 * sizeof (float) - 1));\n"
"}\n");
"}\n"), InternalError);
}
void garbageCode25() {
@ -695,7 +695,7 @@ private:
}
void garbageCode74() { // #6751
checkCode("_lenraw(const char* digits) { } typedef decltype(sizeof(0)) { } operator");
ASSERT_THROW(checkCode("_lenraw(const char* digits) { } typedef decltype(sizeof(0)) { } operator"), InternalError);
}
void garbageCode76() { // #6754
@ -707,7 +707,7 @@ private:
}
void garbageCode78() { // #6756
checkCode("( ) { [ ] } ( ) { } const_array_of_int ( ) { } typedef int A [ ] [ ] ; A a = { { } { } }");
ASSERT_THROW(checkCode("( ) { [ ] } ( ) { } const_array_of_int ( ) { } typedef int A [ ] [ ] ; A a = { { } { } }"), InternalError);
}
void garbageCode79() { // #6757
@ -1004,7 +1004,7 @@ private:
void garbageCode134() {
// Ticket #5605, #5759, #5762, #5774, #5823, #6059
checkCode("foo() template<typename T1 = T2 = typename = unused, T5 = = unused> struct tuple Args> tuple<Args...> { } main() { foo<int,int,int,int,int,int>(); }");
ASSERT_THROW(checkCode("foo() template<typename T1 = T2 = typename = unused, T5 = = unused> struct tuple Args> tuple<Args...> { } main() { foo<int,int,int,int,int,int>(); }"), InternalError);
checkCode("( ) template < T1 = typename = unused> struct Args { } main ( ) { foo < int > ( ) ; }");
checkCode("() template < T = typename = x > struct a {} { f <int> () }");
checkCode("template < T = typename = > struct a { f <int> }");

View File

@ -380,8 +380,12 @@ private:
if (!tokenizer.tokenize(istr, "test.cpp"))
return "";
tokenizer.simplifyTokenList2();
const Token * start = tokenizer.tokens();
const SymbolDatabase * db = tokenizer.getSymbolDatabase();
if (db && db->functionScopes.size())
start = db->functionScopes[0]->classStart->next();
const unsigned int varId(Token::findmatch(tokenizer.tokens(), varname)->varId());
const unsigned int varId(Token::findmatch(start, varname)->varId());
// getcode..
CheckMemoryLeakInFunction checkMemoryLeak(&tokenizer, &settings2, nullptr);
@ -389,7 +393,7 @@ private:
callstack.push_back(0);
CheckMemoryLeak::AllocType allocType, deallocType;
allocType = deallocType = CheckMemoryLeak::No;
Token *tokens = checkMemoryLeak.getcode(tokenizer.tokens(), callstack, varId, allocType, deallocType, classfunc, 1);
Token *tokens = checkMemoryLeak.getcode(start, callstack, varId, allocType, deallocType, classfunc, 1);
// stringify..
std::ostringstream ret;
@ -554,7 +558,7 @@ private:
ASSERT_EQUALS(";;if{exit;}", getcode("char *s; if (a) { exit(0); }", "s"));
// list_for_each
ASSERT_EQUALS(";;exit;{}", getcode("char *s; list_for_each(x,y,z) { }", "s"));
ASSERT_EQUALS(";;exit;{}}", getcode("void f() { char *s; list_for_each(x,y,s) { } }", "s"));
// open/close
ASSERT_EQUALS(";;alloc;if(var){dealloc;}", getcode("int f; f=open(a,b); if(f>=0)close(f);", "f"));

View File

@ -2847,7 +2847,7 @@ private:
"}\n",true);
ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Reading from empty STL container 'Vector'\n", errout.str());
check("f() {\n"
check("Vector f() {\n"
" try {\n"
" std::vector<std::string> Vector;\n"
" Vector.push_back(\"123\");\n"

View File

@ -309,6 +309,8 @@ private:
TEST_CASE(variadic1); // #7453
TEST_CASE(variadic2); // #7649
TEST_CASE(variadic3); // #7387
TEST_CASE(noReturnType);
}
void array() {
@ -1513,7 +1515,7 @@ private:
}
}
void check(const char code[], bool debug = true) {
void check(const char code[], bool debug = true, const char filename[] = "test.cpp") {
// Clear the error log
errout.str("");
@ -1523,7 +1525,7 @@ private:
// Tokenize..
Tokenizer tokenizer(&settings1, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
tokenizer.tokenize(istr, filename);
tokenizer.simplifyTokenList2();
// force symbol database creation
@ -2028,8 +2030,8 @@ private:
"static void function_declaration_after(void) __attribute__((__used__));\n");
ASSERT_EQUALS("", errout.str());
check("main(int argc, char *argv[]) { }");
ASSERT_EQUALS("", errout.str());
check("main(int argc, char *argv[]) { }", true, "test.c");
ASSERT_EQUALS("[test.c:1]: (debug) SymbolDatabase::isFunction found C function 'main' without a return type.\n", errout.str());
check("namespace boost {\n"
" std::locale generate_locale()\n"
@ -4156,6 +4158,19 @@ private:
ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 1);
}
}
void noReturnType() {
GET_SYMBOL_DB_C("func() { }");
ASSERT(db && db->functionScopes.size() == 1);
if (db && db->functionScopes.size() == 1) {
ASSERT(db->functionScopes[0]->function);
if (db->functionScopes[0]->function) {
const Token *retDef = db->functionScopes[0]->function->retDef;
ASSERT_EQUALS("func", retDef ? retDef->str() : "");
}
}
}
};
REGISTER_TEST(TestSymbolDatabase)

View File

@ -729,7 +729,7 @@ private:
// #4239 - segfault for "f ( struct { int typedef T x ; } ) { }"
void tokenize25() {
tokenizeAndStringify("f ( struct { int typedef T x ; } ) { }");
ASSERT_THROW(tokenizeAndStringify("f ( struct { int typedef T x ; } ) { }"), InternalError);
}
// #4245 - segfault