diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index d77726b3f..d968d96d4 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -1,24 +1,29 @@ # Minimal CMake build file to build cppcheck command line executable +include_directories("${CPPCHECK_SOURCE_DIR}/lib") + if(PCRE_FOUND) add_definitions(-DHAVE_RULES) - include_directories("${PCRE_INCLUDE_DIR}") + set(TINYXML_INCLUDE_DIR "${CPPCHECK_SOURCE_DIR}/externals/tinyxml/") + include_directories("${PCRE_INCLUDE_DIR}" "${TINYXML_INCLUDE_DIR}") set(CHECK_LIBS ${PCRE_LIBRARIES}) endif() -set(TINYXML_INCLUDE_DIR "${CPPCHECK_SOURCE_DIR}/externals/tinyxml/") - SET(CHECKCLI_SRCS cmdlineparser.cpp cppcheckexecutor.cpp filelister.cpp main.cpp - threadexecutor.cpp pathmatch.cpp - "${TINYXML_INCLUDE_DIR}tinystr.cpp" - "${TINYXML_INCLUDE_DIR}tinyxml.cpp" - "${TINYXML_INCLUDE_DIR}tinyxmlerror.cpp" - "${TINYXML_INCLUDE_DIR}tinyxmlparser.cpp") + threadexecutor.cpp) + +if(PCRE_FOUND) + set(CHECKCLI_SRCS ${CHECKCLI_SRCS} + "${TINYXML_INCLUDE_DIR}tinystr.cpp" + "${TINYXML_INCLUDE_DIR}tinyxml.cpp" + "${TINYXML_INCLUDE_DIR}tinyxmlerror.cpp" + "${TINYXML_INCLUDE_DIR}tinyxmlparser.cpp") +endif() set(CPPCHECK_LIB_DIR "${CPPCHECK_SOURCE_DIR}/lib/") include("${CPPCHECK_LIB_DIR}library_sources.cmake") @@ -37,7 +42,5 @@ if (CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wshadow -Wno-long-long -Wfloat-equal -Wcast-qual") endif (CMAKE_COMPILER_IS_GNUCXX) -include_directories("${CPPCHECK_SOURCE_DIR}/lib" - "${TINYXML_INCLUDE_DIR}") add_executable(cppcheck ${CHECKCLI_SRCS} ${CPPCHECK_LIB_SOURCES}) TARGET_LINK_LIBRARIES(cppcheck ${CHECK_LIBS}) diff --git a/gui/main.cpp b/gui/main.cpp index fbc709744..30dcc246b 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -21,12 +21,21 @@ #include #include #include +#include +#include #include "mainwindow.h" #include "erroritem.h" +void ShowUsage(); +bool CheckArgs(const QStringList &args); + int main(int argc, char *argv[]) { QApplication app(argc, argv); + + if (!CheckArgs(app.arguments())) + return 0; + app.setWindowIcon(QIcon(":icon.png")); // Register this metatype that is used to transfer error info @@ -40,3 +49,25 @@ int main(int argc, char *argv[]) window.show(); return app.exec(); } + +// Check only arguments needing action before GUI is shown. +// Rest of the arguments are handled in MainWindow::HandleCLIParams() +bool CheckArgs(const QStringList &args) +{ + if (args.contains("-h") || args.contains("--help")) + { + ShowUsage(); + return false; + } + return true; +} + +void ShowUsage() +{ + std::cout << "Cppcheck GUI.\n\n"; + std::cout << "Syntax:\n"; + std::cout << " cppcheck-gui [OPTIONS] [files or paths]\n\n"; + std::cout << "Options:\n"; + std::cout << " -h, --help Print this help\n"; + std::cout << " -p Open given project file and start checking it\n"; +} diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 4281166c7..efa99910b 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -117,7 +117,7 @@ MainWindow::MainWindow() : args.removeFirst(); if (!args.isEmpty()) { - DoCheckFiles(args); + HandleCLIParams(args); } } @@ -127,6 +127,21 @@ MainWindow::~MainWindow() delete mProject; } +void MainWindow::HandleCLIParams(const QStringList ¶ms) +{ + if (params.contains("-p")) + { + QString projFile; + const int ind = params.indexOf("-p"); + if ((ind + 1) < params.length()) + projFile = params[ind + 1]; + + LoadProjectFile(projFile); + } + else + DoCheckFiles(params); +} + void MainWindow::LoadSettings() { if (mSettings->value(SETTINGS_WINDOW_MAXIMIZED, false).toBool()) @@ -730,39 +745,43 @@ void MainWindow::OpenProjectFile() if (!filepath.isEmpty()) { - QFileInfo inf(filepath); - const QString filename = inf.fileName(); - FormatAndSetTitle(tr("Project: ") + QString(" ") + filename); + LoadProjectFile(filepath); + } +} - mUI.mActionCloseProjectFile->setEnabled(true); - mUI.mActionEditProjectFile->setEnabled(true); - delete mProject; - mProject = new Project(filepath, this); - mProject->Open(); - QString rootpath = mProject->GetProjectFile()->GetRootPath(); +void MainWindow::LoadProjectFile(const QString &filePath) +{ + QFileInfo inf(filePath); + const QString filename = inf.fileName(); + FormatAndSetTitle(tr("Project: ") + QString(" ") + filename); - // If root path not give or "current dir" then use project file's directory - // as check path - if (rootpath.isEmpty() || rootpath == ".") - mCurrentDirectory = inf.canonicalPath(); - else - mCurrentDirectory = rootpath; + mUI.mActionCloseProjectFile->setEnabled(true); + mUI.mActionEditProjectFile->setEnabled(true); + delete mProject; + mProject = new Project(filePath, this); + mProject->Open(); + QString rootpath = mProject->GetProjectFile()->GetRootPath(); - QStringList paths = mProject->GetProjectFile()->GetCheckPaths(); - if (!paths.isEmpty()) + // If root path not give or "current dir" then use project file's directory + // as check path + if (rootpath.isEmpty() || rootpath == ".") + mCurrentDirectory = inf.canonicalPath(); + else + mCurrentDirectory = rootpath; + + QStringList paths = mProject->GetProjectFile()->GetCheckPaths(); + if (!paths.isEmpty()) + { + for (int i = 0; i < paths.size(); i++) { - for (int i = 0; i < paths.size(); i++) + if (!QDir::isAbsolutePath(paths[i])) { - if (!QDir::isAbsolutePath(paths[i])) - { - QString path = mCurrentDirectory + "/"; - path += paths[i]; - paths[i] = QDir::cleanPath(path); - } + QString path = mCurrentDirectory + "/"; + path += paths[i]; + paths[i] = QDir::cleanPath(path); } - - DoCheckFiles(paths); } + DoCheckFiles(paths); } } diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 04cefede7..c316f5970 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -360,6 +360,18 @@ protected: */ void AddIncludeDirs(const QStringList &includeDirs, Settings &result); + /** + * @brief Handle command line parameters given to GUI. + * @param params List of string given to command line. + */ + void HandleCLIParams(const QStringList ¶ms); + + /** + * @brief Load project file to the GUI. + * @param filePath Filename (inc. path) of project file to load. + */ + void LoadProjectFile(const QString &filePath); + /** * @brief Program settings * diff --git a/lib/checkobsoletefunctions.h b/lib/checkobsoletefunctions.h index 3c56516e2..1fd705b74 100644 --- a/lib/checkobsoletefunctions.h +++ b/lib/checkobsoletefunctions.h @@ -68,8 +68,8 @@ private: { _obsoleteFunctions.push_back(std::make_pair("bsd_signal","Found obsolete function 'bsd_signal'. It is recommended that new applications use the 'sigaction' function")); - _obsoleteFunctions.push_back(std::make_pair("gethostbyaddr","Found obsolete function 'gethostbyaddr'. It is recommended that new applications use the 'getaddrinfo' function")); - _obsoleteFunctions.push_back(std::make_pair("gethostbyname","Found obsolete function 'gethostbyname'. It is recommended that new applications use the 'getnameinfo' function")); + _obsoleteFunctions.push_back(std::make_pair("gethostbyaddr","Found obsolete function 'gethostbyaddr'. It is recommended that new applications use the 'getnameinfo' function")); + _obsoleteFunctions.push_back(std::make_pair("gethostbyname","Found obsolete function 'gethostbyname'. It is recommended that new applications use the 'getaddrinfo' function")); _obsoleteFunctions.push_back(std::make_pair("usleep","Found obsolete function 'usleep'. It is recommended that new applications use the 'nanosleep' or 'setitimer' function\n" "Found obsolete function 'usleep'. POSIX.1-2001 declares usleep() function obsolete and POSIX.1-2008 removes it. It is recommended that new applications use the 'nanosleep' or 'setitimer' function.")); diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 227733e95..a648e76ea 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -1910,13 +1910,7 @@ void Preprocessor::handleIncludes(std::string &code, const std::string &filePath } else if (!fileOpened) { - // TODO: Fix the handling of system includes and then - // remove the "headerType == UserHeader" -#ifdef NDEBUG - if (headerType == UserHeader && _errorLogger && _settings && _settings->isEnabled("missingInclude")) -#else - if (_errorLogger && _settings && _settings->isEnabled("missingInclude")) -#endif + if (_errorLogger && _settings && ((headerType == UserHeader && _settings->isEnabled("missingInclude")) || _settings->debugwarnings)) { std::string f = filePath; @@ -2384,14 +2378,17 @@ public: } // expand nopar macro - const std::map::const_iterator it = macros.find(str); - if (it != macros.end() && it->second->_macro.find("(") == std::string::npos) + if (tok->strAt(-1) != "##") { - str = it->second->_macro; - if (str.find(" ") != std::string::npos) - str.erase(0, str.find(" ")); - else - str = ""; + const std::map::const_iterator it = macros.find(str); + if (it != macros.end() && it->second->_macro.find("(") == std::string::npos) + { + str = it->second->_macro; + if (str.find(" ") != std::string::npos) + str.erase(0, str.find(" ")); + else + str = ""; + } } } if (_variadic && tok->str() == "," && tok->next() && tok->next()->str() == "##") diff --git a/test/test.vcproj b/test/test.vcproj old mode 100755 new mode 100644 diff --git a/test/testobsoletefunctions.cpp b/test/testobsoletefunctions.cpp index a489191f0..72d24908b 100644 --- a/test/testobsoletefunctions.cpp +++ b/test/testobsoletefunctions.cpp @@ -103,7 +103,7 @@ private: " exit(1);\n" " }\n" "}\n"); - ASSERT_EQUALS("[test.cpp:4]: (style) Found obsolete function 'gethostbyname'. It is recommended that new applications use the 'getnameinfo' function\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (style) Found obsolete function 'gethostbyname'. It is recommended that new applications use the 'getaddrinfo' function\n", errout.str()); } void testgethostbyaddr() @@ -116,7 +116,7 @@ private: " exit(1);\n" " }\n" "}\n"); - ASSERT_EQUALS("[test.cpp:5]: (style) Found obsolete function 'gethostbyaddr'. It is recommended that new applications use the 'getaddrinfo' function\n", errout.str()); + ASSERT_EQUALS("[test.cpp:5]: (style) Found obsolete function 'gethostbyaddr'. It is recommended that new applications use the 'getnameinfo' function\n", errout.str()); } void testusleep() diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 96e1a33cf..aa341688f 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -159,7 +159,8 @@ private: TEST_CASE(macro_simple13); TEST_CASE(macro_simple14); TEST_CASE(macro_simple15); - TEST_CASE(macroInMacro); + TEST_CASE(macroInMacro1); + TEST_CASE(macroInMacro2); TEST_CASE(macro_mismatch); TEST_CASE(macro_linenumbers); TEST_CASE(macro_nopar); @@ -1692,7 +1693,7 @@ private: ASSERT_EQUALS("\n\"foo\"\n", OurPreprocessor::expandMacros(filedata)); } - void macroInMacro() + void macroInMacro1() { { const char filedata[] = "#define A(m) long n = m; n++;\n" @@ -1793,6 +1794,14 @@ private: } } + void macroInMacro2() + { + const char filedata[] = "#define A(x) a##x\n" + "#define B 0\n" + "A(B)\n"; + ASSERT_EQUALS("\n\naB\n", OurPreprocessor::expandMacros(filedata)); + } + void macro_mismatch() { const char filedata[] = "#define AAA(aa,bb) f(aa)\n" diff --git a/win_installer/cppcheck.wxs b/win_installer/cppcheck.wxs index 47440dd51..ed4e5098c 100644 --- a/win_installer/cppcheck.wxs +++ b/win_installer/cppcheck.wxs @@ -42,6 +42,7 @@ +