diff --git a/src/cppcheck.cpp b/src/cppcheck.cpp index 0c0088f84..9ec43b2c4 100644 --- a/src/cppcheck.cpp +++ b/src/cppcheck.cpp @@ -380,7 +380,11 @@ void CppCheck::checkFile(const std::string &code, const char FileName[]) // Tokenize the file { std::istringstream istr(code); - _tokenizer.tokenize(istr, FileName); + if (!_tokenizer.tokenize(istr, FileName)) + { + // File had syntax errors, abort + return; + } } // Set variable id diff --git a/src/tokenize.cpp b/src/tokenize.cpp index 4f262cbd9..757baeef2 100644 --- a/src/tokenize.cpp +++ b/src/tokenize.cpp @@ -153,7 +153,7 @@ void Tokenizer::InsertTokens(Token *dest, Token *src, unsigned int n) // Tokenize - tokenizes a given file. //--------------------------------------------------------------------------- -void Tokenizer::tokenize(std::istream &code, const char FileName[]) +bool Tokenizer::tokenize(std::istream &code, const char FileName[]) { // The "_files" vector remembers what files have been tokenized.. _files.push_back(FileLister::simplifyPath(FileName)); @@ -336,6 +336,12 @@ void Tokenizer::tokenize(std::istream &code, const char FileName[]) } addtoken(CurrentToken.c_str(), lineno, FileIndex); + if (!createLinks()) + { + // Source has syntax errors, can't proceed + return false; + } + // Combine "- %num%" .. for (Token *tok = _tokens; tok; tok = tok->next()) { @@ -464,6 +470,7 @@ void Tokenizer::tokenize(std::istream &code, const char FileName[]) // Handle templates.. simplifyTemplates(); + return true; } //--------------------------------------------------------------------------- @@ -945,6 +952,7 @@ bool Tokenizer::createLinks() if (links.size() == 0) { // Error, { and } don't match. + syntaxError(token, '{'); return false; } @@ -961,6 +969,7 @@ bool Tokenizer::createLinks() if (links2.size() == 0) { // Error, ( and ) don't match. + syntaxError(token, '('); return false; } @@ -970,9 +979,17 @@ bool Tokenizer::createLinks() } } - if (links.size() > 0 || links2.size() > 0) + if (links.size() > 0) { // Error, { and } don't match. + syntaxError(_tokens, '{'); + return false; + } + + if (links2.size() > 0) + { + // Error, { and } don't match. + syntaxError(_tokens, '('); return false; } @@ -2622,6 +2639,23 @@ const Token * Tokenizer::FindClassFunction(const Token *tok, const char classnam return NULL; } //--------------------------------------------------------------------------- - +// Error message for bad iterator usage.. + +void Tokenizer::syntaxError(const Token *tok, char c) +{ + std::cout << "### Error: Invalid number of character " << c << std::endl; + /* + std::list locationList; + ErrorLogger::ErrorMessage::FileLocation loc; + loc.line = tok->linenr(); + loc.file = tok->fileIndex(); + locationList.push_back(loc); + _errorLogger->reportErr( + ErrorLogger::ErrorMessage(locationList, + "error", + std::string("Invalid number of character (") + c + "). Can't process file. File is either invalid or unicode, which is currently not supported.", + "syntaxError")); + */ +} diff --git a/src/tokenize.h b/src/tokenize.h index e85835cc4..5afbf83f6 100644 --- a/src/tokenize.h +++ b/src/tokenize.h @@ -45,8 +45,9 @@ public: * Tokenize code * @param code input stream for code * @param FileName The filename + * @return false if Source code contains syntax errors */ - void tokenize(std::istream &code, const char FileName[]); + bool tokenize(std::istream &code, const char FileName[]); /** Set variable id */ void setVarId(); @@ -208,6 +209,8 @@ private: */ bool createLinks(); + void syntaxError(const Token *tok, char c); + Token *_tokensBack; std::map _typeSize; std::vector _files; diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index d44c52130..4e573b1e7 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -74,7 +74,7 @@ private: check("void func1(int **res)\n" "{\n" " int num=2;" - "res=#"); + "res=#}"); ASSERT_EQUALS(std::string("[test.cpp:3]: (error) Wrong assignement of an auto-variable to an effective parameter of a function\n"), errout.str()); } void testautovararray() @@ -82,7 +82,7 @@ private: check("void func1(int* arr[2])\n" "{\n" " int num=2;" - "arr[0]=#"); + "arr[0]=#}"); ASSERT_EQUALS(std::string("[test.cpp:3]: (error) Wrong assignement of an auto-variable to an effective parameter of a function\n"), errout.str()); } void testautovarreturn() @@ -90,7 +90,7 @@ private: check("int* func1()\n" "{\n" " int num=2;" - "return #"); + "return #}"); ASSERT_EQUALS(std::string("[test.cpp:3]: (error) Return of the address of an auto-variable\n"), errout.str()); } }; diff --git a/test/testdivision.cpp b/test/testdivision.cpp index a9d054f1b..f2e67874a 100644 --- a/test/testdivision.cpp +++ b/test/testdivision.cpp @@ -112,7 +112,7 @@ private: "void f2(unsigned int i1)\n" "{\n" " unsigned int i2;\n" - " result = i2 / i1;\n" + " result = i2 / i1;}\n" ); ASSERT_EQUALS(std::string(""), errout.str()); } @@ -123,7 +123,7 @@ private: "void foo()\n" "{\n" " unsigned int val = 32;\n" - " val = val / USER_HASH;\n" + " val = val / USER_HASH;}\n" ); ASSERT_EQUALS(std::string(""), errout.str()); } @@ -133,7 +133,7 @@ private: check("void foo()\n" "{\n" " unsigned int val = 32;\n" - " int i = val / -2;\n" + " int i = val / -2; }\n" ); ASSERT_EQUALS(std::string("[test.cpp:4]: (error) Unsigned division. The result will be wrong.\n"), errout.str()); } @@ -143,7 +143,7 @@ private: check("void foo()\n" "{\n" " unsigned int val = 32;\n" - " int i = -96 / val;\n" + " int i = -96 / val; }\n" ); ASSERT_EQUALS(std::string("[test.cpp:4]: (error) Unsigned division. The result will be wrong.\n"), errout.str()); } diff --git a/test/testincompletestatement.cpp b/test/testincompletestatement.cpp index 649928a8a..4ebd85f6a 100644 --- a/test/testincompletestatement.cpp +++ b/test/testincompletestatement.cpp @@ -142,8 +142,7 @@ private: "{\n" "{ 346.1,114.1 }, { 347.1,111.1 }\n" "};\n" - "}\n" - "};\n"); + "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } diff --git a/test/teststl.cpp b/test/teststl.cpp index 02cec07ae..815a89325 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -358,11 +358,14 @@ private: void invalidcode() { - check("void f()\n" - "{\n" - " for ( \n" - "}\n"); - ASSERT_EQUALS("", errout.str()); + const std::string src = "void f()\n" + "{\n" + " for ( \n" + "}\n"; + + Tokenizer tokenizer; + std::istringstream istr(src); + ASSERT_EQUALS(false, tokenizer.tokenize(istr, "test.cpp")); } diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index a32873ccc..94d7df193 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -139,6 +139,7 @@ private: TEST_CASE(vardecl1); TEST_CASE(vardecl2); TEST_CASE(volatile_variables); + TEST_CASE(syntax_error); } @@ -1709,6 +1710,33 @@ private: ASSERT_EQUALS("int a ; a = 0 ;\nint b ; b = 0 ;\nint c ; c = 0 ;", actual); } + + void syntax_error() + { + { + const char code[] = "void f() {}"; + Tokenizer tokenizer; + std::istringstream istr(code); + ASSERT_EQUALS(true, tokenizer.tokenize(istr, "test.cpp")); + ASSERT_EQUALS(std::string(""), errout.str()); + } + + { + const char code[] = "void f() {{}"; + Tokenizer tokenizer; + std::istringstream istr(code); + ASSERT_EQUALS(false, tokenizer.tokenize(istr, "test.cpp")); + TODO_ASSERT_EQUALS(std::string("correct error message here"), errout.str()); + } + + { + const char code[] = "void f()) {}"; + Tokenizer tokenizer; + std::istringstream istr(code); + ASSERT_EQUALS(false, tokenizer.tokenize(istr, "test.cpp")); + TODO_ASSERT_EQUALS(std::string("correct error message here"), errout.str()); + } + } }; REGISTER_TEST(TestTokenizer)