From 4123b457d723bb887da328b33a48a1397ecccb53 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Fri, 6 Jan 2017 11:53:17 +0100 Subject: [PATCH] Fixed #7441 (SymbolDatabase: No scope when function return type not specified) --- lib/symboldatabase.cpp | 14 ++++++++++++++ test/testgarbage.cpp | 20 ++++++++++---------- test/testmemleak.cpp | 10 +++++++--- test/teststl.cpp | 2 +- test/testsymboldatabase.cpp | 23 +++++++++++++++++++---- test/testtokenize.cpp | 2 +- 6 files changed, 52 insertions(+), 19 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 40441d33d..968870dbd 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -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; } diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index 7d78278cd..b1043f949 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -482,13 +482,13 @@ private: void garbageCode24() { // don't crash (example from #6361) - 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"); + 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"), 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 struct tuple Args> tuple { } main() { foo(); }"); + ASSERT_THROW(checkCode("foo() template struct tuple Args> tuple { } main() { foo(); }"), InternalError); checkCode("( ) template < T1 = typename = unused> struct Args { } main ( ) { foo < int > ( ) ; }"); checkCode("() template < T = typename = x > struct a {} { f () }"); checkCode("template < T = typename = > struct a { f }"); diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 0d09d6d7d..d050d9074 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -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")); diff --git a/test/teststl.cpp b/test/teststl.cpp index 29e8aec0d..efd98b3c0 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -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 Vector;\n" " Vector.push_back(\"123\");\n" diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 14e0ba104..06902c628 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -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) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index b98d8871e..5a493b828 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -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