Fixed #7441 (SymbolDatabase: No scope when function return type not specified)
This commit is contained in:
parent
8eeb09ba88
commit
4123b457d7
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<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> }");
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue