diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 428d6a2ae..93ac303ad 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -197,6 +197,18 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) } } + else if (strncmp(argv[i], "--suppress=", 11) == 0) + { + std::string suppression = argv[i]; + suppression = suppression.substr(11); + const std::string errmsg(_settings->nomsg.addSuppressionLine(suppression)); + if (!errmsg.empty()) + { + PrintMessage(errmsg); + return false; + } + } + // Enables inline suppressions. else if (strcmp(argv[i], "--inline-suppr") == 0) _settings->_inlineSuppressions = true; @@ -628,7 +640,8 @@ void CmdLineParser::PrintHelp() " * information - Enable information messages\n" " * unusedFunction - check for unused functions\n" " * missingInclude - check for missing includes\n" - " Several ids can be given if you separate them with commas.\n" + " Several ids can be given if you separate them with\n" + " commas.\n" " --error-exitcode= If errors are found, integer [n] is returned instead\n" " of default 0. EXIT_FAILURE is returned\n" " if arguments are not valid or if no input files are\n" @@ -638,17 +651,18 @@ void CmdLineParser::PrintHelp() " --exitcode-suppressions=\n" " Used when certain messages should be displayed but\n" " should not cause a non-zero exitcode.\n" - " --file-list= Specify the files to check in a text file. One Filename per line.\n" + " --file-list= Specify the files to check in a text file. One Filename\n" + " per line.\n" " -f, --force Force checking on files that have \"too many\"\n" " configurations.\n" " -h, --help Print this help.\n" " -I Give include path. Give several -I parameters to give\n" " several paths. First given path is checked first. If\n" " paths are relative to source files, this is not needed.\n" - " -i Give path to ignore. Give several -i parameters to ignore\n" - " several paths. Give directory name or filename with path\n" - " as parameter. Directory name is matched to all parts of the\n" - " path.\n" + " -i Give path to ignore. Give several -i parameters to\n" + " ignore several paths. Give directory name or filename\n" + " with path as parameter. Directory name is matched to\n" + " all parts of the path.\n" " --inline-suppr Enable inline suppressions. Use them by placing one or\n" " more comments, like: // cppcheck-suppress warningId\n" " on the lines before the warning to suppress.\n" @@ -659,11 +673,12 @@ void CmdLineParser::PrintHelp() " --rule-file= Use given rule file. For more information, see: \n" " https://sourceforge.net/projects/cppcheck/files/Articles/\n" " -s, --style Deprecated, use --enable=style\n" - " --suppressions-list=\n" - " Suppress warnings listed in the file. Filename and line\n" - " are optional in the suppression file. The format of the\n" - " single line in the suppression file is:\n" + " --suppress= Suppress a specific warning. The format of is:\n" " [error id]:[filename]:[line]\n" + " The [filename] and [line] are optional.\n" + " --suppressions-list=\n" + " Suppress warnings listed in the file. Each suppression\n" + " is in the same format as above.\n" " --template '' Format the error messages. E.g.\n" " '{file}:{line},{severity},{id},{message}' or\n" " '{file}({line}):({severity}) {message}'\n" diff --git a/gui/applicationlist.cpp b/gui/applicationlist.cpp index 090733c7a..7dada872b 100644 --- a/gui/applicationlist.cpp +++ b/gui/applicationlist.cpp @@ -27,7 +27,8 @@ ApplicationList::ApplicationList(QObject *parent) : - QObject(parent) + QObject(parent), + mDefaultApplicationIndex(-1) { //ctor } @@ -42,6 +43,7 @@ void ApplicationList::LoadSettings(QSettings *programSettings) QStringList names = programSettings->value(SETTINGS_APPLICATION_NAMES, QStringList()).toStringList(); QStringList paths = programSettings->value(SETTINGS_APPLICATION_PATHS, QStringList()).toStringList(); + int defapp = programSettings->value(SETTINGS_APPLICATION_DEFAULT, -1).toInt(); if (names.empty() && paths.empty()) { @@ -50,28 +52,37 @@ void ApplicationList::LoadSettings(QSettings *programSettings) // use as default for gnome environments if (QFileInfo("/usr/bin/gedit").isExecutable()) { - AddApplicationType("gedit", "/usr/bin/gedit +(line) (file)"); + AddApplication("gedit", "/usr/bin/gedit +(line) (file)"); + defapp = 0; break; } // use as default for kde environments if (QFileInfo("/usr/bin/kate").isExecutable()) { - AddApplicationType("kate", "/usr/bin/kate -l(line) (file)"); + AddApplication("kate", "/usr/bin/kate -l(line) (file)"); + defapp = 0; break; } - // use as default for windows environments if (FindDefaultWindowsEditor()) + { + defapp = 0; break; + } } while (0); } - if (names.size() == paths.size()) + if (names.size() > 0 && (names.size() == paths.size())) { for (int i = 0; i < names.size(); i++) - { - AddApplicationType(names[i], paths[i]); - } + AddApplication(names[i], paths[i]); + + if (defapp == -1) + mDefaultApplicationIndex = 0; + else if (defapp < names.size()) + mDefaultApplicationIndex = defapp; + else + mDefaultApplicationIndex = 0; } } @@ -88,6 +99,7 @@ void ApplicationList::SaveSettings(QSettings *programSettings) programSettings->setValue(SETTINGS_APPLICATION_NAMES, names); programSettings->setValue(SETTINGS_APPLICATION_PATHS, paths); + programSettings->setValue(SETTINGS_APPLICATION_DEFAULT, mDefaultApplicationIndex); } @@ -117,9 +129,9 @@ QString ApplicationList::GetApplicationPath(const int index) const } -void ApplicationList::SetApplicationType(const int index, - const QString &name, - const QString &path) +void ApplicationList::SetApplication(const int index, + const QString &name, + const QString &path) { if (index >= 0 && index < mApplications.size()) { @@ -128,7 +140,7 @@ void ApplicationList::SetApplicationType(const int index, } } -void ApplicationList::AddApplicationType(const QString &name, const QString &path) +void ApplicationList::AddApplication(const QString &name, const QString &path) { if (name.isEmpty() || path.isEmpty()) { @@ -146,15 +158,15 @@ void ApplicationList::RemoveApplication(const int index) mApplications.removeAt(index); } -void ApplicationList::MoveFirst(const int index) +void ApplicationList::SetDefault(const int index) { - if (index < mApplications.size() && index > 0) + if (index < mApplications.size() && index >= 0) { - mApplications.move(index, 0); + mDefaultApplicationIndex = index; } } -void ApplicationList::Copy(ApplicationList *list) +void ApplicationList::Copy(const ApplicationList *list) { if (!list) { @@ -164,13 +176,15 @@ void ApplicationList::Copy(ApplicationList *list) Clear(); for (int i = 0; i < list->GetApplicationCount(); i++) { - AddApplicationType(list->GetApplicationName(i), list->GetApplicationPath(i)); + AddApplication(list->GetApplicationName(i), list->GetApplicationPath(i)); } + mDefaultApplicationIndex = list->GetDefaultApplication(); } void ApplicationList::Clear() { mApplications.clear(); + mDefaultApplicationIndex = -1; } bool ApplicationList::FindDefaultWindowsEditor() @@ -179,7 +193,7 @@ bool ApplicationList::FindDefaultWindowsEditor() const QString notepadppPath = appPath + "\\Notepad++\\notepad++.exe"; if (QFileInfo(notepadppPath).isExecutable()) { - AddApplicationType("Notepad++", "\"" + notepadppPath + "\" -n(line) (file)"); + AddApplication("Notepad++", "\"" + notepadppPath + "\" -n(line) (file)"); return true; } @@ -187,7 +201,7 @@ bool ApplicationList::FindDefaultWindowsEditor() const QString notepadPath = windowsPath + "\\system32\\notepad.exe"; if (QFileInfo(notepadPath).isExecutable()) { - AddApplicationType("Notepad", notepadPath + " (file)"); + AddApplication("Notepad", notepadPath + " (file)"); return true; } return false; diff --git a/gui/applicationlist.h b/gui/applicationlist.h index 2cbc19156..9bad886a8 100644 --- a/gui/applicationlist.h +++ b/gui/applicationlist.h @@ -56,7 +56,7 @@ public: typedef struct { /** - * @brief Applicaton's name + * @brief Application's name * */ QString Name; @@ -106,6 +106,15 @@ public: */ QString GetApplicationPath(const int index) const; + /** + * @brief Return the default application. + * @return Index of the default application. + */ + int GetDefaultApplication() const + { + return mDefaultApplicationIndex; + } + /** * @brief Modify an application * @@ -113,9 +122,8 @@ public: * @param name New name for the application * @param path New path for the application */ - void SetApplicationType(const int index, - const QString &name, - const QString &path); + void SetApplication(const int index, const QString &name, + const QString &path); /** * @brief Add a new application @@ -123,7 +131,7 @@ public: * @param name Name of the application * @param path Path to the application */ - void AddApplicationType(const QString &name, const QString &path); + void AddApplication(const QString &name, const QString &path); /** * @brief Remove an application from the list @@ -133,21 +141,18 @@ public: void RemoveApplication(const int index); /** - * @brief Move certain application as first. - * Position of the application is used by the application to determine - * which of the applications is the default application. First application - * (index 0) is the default application. - * + * @brief Set application as default application. * @param index Index of the application to make the default one */ - void MoveFirst(const int index); + void SetDefault(const int index); /** * @brief Remove all applications from this list and copy all applications from * list given as a parameter. * @param list Copying source */ - void Copy(ApplicationList *list); + void Copy(const ApplicationList *list); + protected: /** @@ -162,12 +167,19 @@ protected: */ bool FindDefaultWindowsEditor(); +private: + /** * @brief List of applications * */ QList mApplications; -private: + + /** + * @brief Index of the default application. + * + */ + int mDefaultApplicationIndex; }; /// @} #endif // APPLICATIONLIST_H diff --git a/gui/checkthread.cpp b/gui/checkthread.cpp index 724228ded..5ae40a3ef 100644 --- a/gui/checkthread.cpp +++ b/gui/checkthread.cpp @@ -25,7 +25,7 @@ CheckThread::CheckThread(ThreadResult &result) : mState(Ready), mResult(result), - mCppcheck(result) + mCppcheck(result, true) { //ctor } diff --git a/gui/common.h b/gui/common.h index 7f3b5669b..6d9383ad2 100644 --- a/gui/common.h +++ b/gui/common.h @@ -77,6 +77,7 @@ ShowTypes; #define SETTINGS_SAVE_FULL_PATH "Save full path" #define SETTINGS_APPLICATION_NAMES "Application names" #define SETTINGS_APPLICATION_PATHS "Application paths" +#define SETTINGS_APPLICATION_DEFAULT "Default Application" #define SETTINGS_LANGUAGE "Application language" #define SETTINGS_GLOBAL_INCLUDE_PATHS "Global include paths" #define SETTINGS_INLINE_SUPPRESSIONS "Inline suppressions" diff --git a/gui/cppcheck_de.ts b/gui/cppcheck_de.ts index 99899b8ae..4d41ecd63 100644 --- a/gui/cppcheck_de.ts +++ b/gui/cppcheck_de.ts @@ -220,12 +220,12 @@ kate -l(line) (file) MainWindow - - - - - - + + + + + + Cppcheck Cppcheck @@ -537,97 +537,103 @@ kate -l(line) (file) &Hilfe - + Select files to check Dateien zum Überprüfen auswählen - + Select directory to check Verzeichnis zum Überprüfen auswählen - + No suitable files found to check! Kein passenden Dateien zum Überprüfen gefunden! - + License Lizenz - + Authors Autoren - + XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) XML-Dateien (*.xml);;Textdateien (*.txt);;CSV-Dateien (*.csv) - + Save the report file Speichert die Berichtdatei - + XML files (*.xml) XML-Dateien (*.xml) - + You must close the project file before selecting new files or directories! - - - + + + Project: - + Open the report file - + Checking is running. Do you want to stop the checking and exit Cppcheck?. - + XML files version 1 (*.xml) - + XML files version 2 (*.xml) - + Text files (*.txt) Textdateien (*.txt) - + CSV files (*.csv) CSV-Dateien (*.csv) - + Cppcheck - %1 Cppcheck - %1 - + + Failed to change the language: + +%1 + + + Failed to change the language: %1 @@ -636,56 +642,56 @@ Do you want to stop the checking and exit Cppcheck?. Failed to change language: %1 - Fehler beim Ändern der Sprache: + Fehler beim Ändern der Sprache: %1 + - Cppcheck Help - + Failed to load help file (not found) - + Failed to load help file - - + + Project files (*.cppcheck);;All files(*.*) - + Select Project File - + Select Project Filename - + No project file loaded - + Finnish Finnisch - + English Englisch @@ -695,33 +701,38 @@ Do you want to stop the checking and exit Cppcheck?. Niederländisch - + + French + + + + Swedish Schwedisch - + German Deutsch - + Russian Russisch - + Polish Polnisch - + Japanese Japanease - + Serbian @@ -753,28 +764,50 @@ Do you want to stop the checking and exit Cppcheck?. - + + Project + + + + Project: - + Paths: - - - Browse... + + + Add... - - Include paths: + + + Edit - + + + Remove + + + + + Includes + + + + + Include directories: + + + + Defines: @@ -800,18 +833,22 @@ Do you want to stop the checking and exit Cppcheck?. QObject - Incorrect language specified! - Falsche Sprache angegeben! + Falsche Sprache angegeben! - + + Unknown language specified! + + + + Language file %1 not found! Language file %1.qm not found! Sprachdatei %1 nicht gefunden! - + Failed to load translation for language %1 from file %2 Failed to load translation for language %1 from file %2.qm Die Übersetzungen der Sprache %1 konnten nicht aus der Datei %2 geladen werden @@ -821,71 +858,71 @@ Do you want to stop the checking and exit Cppcheck?. ResultsTree - + File Datei - + Severity Schweregrad - + Line Zeile - + Summary - + Undefined file Undefinierte Datei - + Copy filename Dateiname kopieren - + Copy full path Vollständigen Pfad kopieren - + Copy message Meldung kopieren - + Hide - + Cppcheck Cppcheck - + Configure the text file viewer program in Cppcheck preferences/Applications. You can open this error by specifying applications in program's settings. Konfigurieren Sie das Text-Dateibetrachter-Programm unter Einstellungen/Anwendungen. - + Could not find the file! - + Could not start %1 Please check the application path and parameters are correct. @@ -894,44 +931,44 @@ Please check the application path and parameters are correct. Bitte überprüfen Sie ob der Pfad und die Parameter der Anwendung richtig eingestellt sind. - + Could not find file: %1 Please select the directory where file is located. - + Select Directory - + style Stil - + error Fehler - + warning - + performance - + portability - + information @@ -1003,98 +1040,121 @@ Legen Sie unter dem Menü Ansicht fest, welche Art von Fehlern angezeigt werden Allgemein - + Include paths: - + + Add... - + Number of threads: Anzahl der Threads: - + Ideal count: - + TextLabel - + Force checking all #ifdef configurations Check all #ifdef configurations Alle #ifdef-Konfigurationen überprüfen - + Show full path of files Vollständigen Dateipfad anzeigen - + Show "No errors found" message when no errors found "Keine Fehler gefunden"-Meldung anzeigen, wenn keine Fehler gefunden werden - + Show internal warnings in log - + Enable inline suppressions - + + Paths + + + + + Edit + + + + + + Remove + + + + Applications Anwendungen - + + Edit... + + + + + Set as default + + + Add application - Anwendung hinzufügen + Anwendung hinzufügen - Delete application - Anwendung löschen + Anwendung löschen - Modify application - Anwendung ändern + Anwendung ändern - Set as default application - Als Standard-Anwendung verwenden + Als Standard-Anwendung verwenden - + Reports Berichte - + Save all errors when creating report Alle Fehler beim Erstellen von Berichten speichern - + Save full path to files in reports Vollständigen Dateipfad in Berichten speichern - + Language @@ -1102,22 +1162,27 @@ Legen Sie unter dem Menü Ansicht fest, welche Art von Fehlern angezeigt werden SettingsDialog - + N/A - + Add a new application Neue Anwendung hinzufügen - + Modify an application Anwendung ändern - + + [Default] + + + + Select include directory diff --git a/gui/cppcheck_en.ts b/gui/cppcheck_en.ts index 4621571d1..926c62f56 100644 --- a/gui/cppcheck_en.ts +++ b/gui/cppcheck_en.ts @@ -222,12 +222,12 @@ kate -l(line) (file) MainWindow - - - - - - + + + + + + Cppcheck Cppcheck @@ -539,97 +539,103 @@ kate -l(line) (file) &Help - + Select files to check Select files to check - + Select directory to check Select directory to check - + No suitable files found to check! No suitable files found to check! - + License License - + Authors Authors - + XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) - + Save the report file Save the report file - + XML files (*.xml) XML files (*.xml) - + You must close the project file before selecting new files or directories! - - - + + + Project: - + Open the report file - + Checking is running. Do you want to stop the checking and exit Cppcheck?. - + XML files version 1 (*.xml) - + XML files version 2 (*.xml) - + Text files (*.txt) Text files (*.txt) - + CSV files (*.csv) - + Cppcheck - %1 Cppcheck - %1 - + + Failed to change the language: + +%1 + + + Failed to change the language: %1 @@ -638,54 +644,54 @@ Do you want to stop the checking and exit Cppcheck?. Failed to change language: %1 - Failed to change language: + Failed to change language: %1 + - Cppcheck Help - + Failed to load help file (not found) - + Failed to load help file - - + + Project files (*.cppcheck);;All files(*.*) - + Select Project File - + Select Project Filename - + No project file loaded - + Finnish Finnish - + English English @@ -695,33 +701,38 @@ Do you want to stop the checking and exit Cppcheck?. - + + French + + + + Swedish Swedish - + German German - + Russian Russian - + Polish Polish - + Japanese Japanease - + Serbian Serbian @@ -753,28 +764,50 @@ Do you want to stop the checking and exit Cppcheck?. - + + Project + + + + Project: - + Paths: - - - Browse... + + + Add... - - Include paths: + + + Edit - + + + Remove + + + + + Includes + + + + + Include directories: + + + + Defines: @@ -800,18 +833,22 @@ Do you want to stop the checking and exit Cppcheck?. QObject - Incorrect language specified! - Incorrect language specified! + Incorrect language specified! - + + Unknown language specified! + + + + Language file %1 not found! Language file %1.qm not found! Could not find the file: %1! - + Failed to load translation for language %1 from file %2 Failed to load translation for language %1 from file %2.qm Failed to load translation for language %1 from file %2 @@ -821,71 +858,71 @@ Do you want to stop the checking and exit Cppcheck?. ResultsTree - + File File - + Severity Severity - + Line Line - + Summary - + Undefined file Undefined file - + Copy filename Copy filename - + Copy full path Copy full path - + Copy message - + Hide - + Cppcheck Cppcheck - + Configure the text file viewer program in Cppcheck preferences/Applications. You can open this error by specifying applications in program's settings. You can open this error by specifying applications in program's settings. - + Could not find the file! - + Could not start %1 Please check the application path and parameters are correct. @@ -894,44 +931,44 @@ Please check the application path and parameters are correct. Please check the application path and parameters are correct. - + Could not find file: %1 Please select the directory where file is located. - + Select Directory - + style Style - + error Error - + warning - + performance - + portability - + information @@ -1003,98 +1040,121 @@ To toggle what kind of errors are shown, open view menu. General - + Include paths: - + + Add... - + Number of threads: Number of threads: - + Ideal count: - + TextLabel - + Force checking all #ifdef configurations Check all #ifdef configurations Check all #ifdef configurations - + Show full path of files Show full path of files - + Show "No errors found" message when no errors found Show "No errors found" message when no errors found - + Show internal warnings in log - + Enable inline suppressions - + + Paths + + + + + Edit + + + + + + Remove + + + + Applications Applications - + + Edit... + + + + + Set as default + + + Add application - Add application + Add application - Delete application - Delete application + Delete application - Modify application - Modify application + Modify application - Set as default application - Set as default application + Set as default application - + Reports Reports - + Save all errors when creating report Save all errors when creating report - + Save full path to files in reports Save full path to files in reports - + Language @@ -1102,22 +1162,27 @@ To toggle what kind of errors are shown, open view menu. SettingsDialog - + N/A - + Add a new application Add a new application - + Modify an application Modify an application - + + [Default] + + + + Select include directory diff --git a/gui/cppcheck_fi.ts b/gui/cppcheck_fi.ts index f336f63c2..afc617cb1 100644 --- a/gui/cppcheck_fi.ts +++ b/gui/cppcheck_fi.ts @@ -224,12 +224,12 @@ kate -l(line) (file) MainWindow - - - - - - + + + + + + Cppcheck Cppcheck @@ -541,97 +541,103 @@ kate -l(line) (file) &Ohje - + Select files to check Valitse tarkistettavat tiedostot - + Select directory to check Valitse tarkistettava hakemisto - + No suitable files found to check! Tarkistettavaksi sopivia tiedostoja ei löytynyt! - + License Lisenssi - + Authors Tekijät - + XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) XML-tiedostot (*.xml);;Tekstitiedostot (*.txt);;CSV-tiedostot (*.csv) - + Save the report file Tallenna raportti - + XML files (*.xml) XML-tiedostot (*xml) - + You must close the project file before selecting new files or directories! - - - + + + Project: - + Open the report file - + Checking is running. Do you want to stop the checking and exit Cppcheck?. - + XML files version 1 (*.xml) - + XML files version 2 (*.xml) - + Text files (*.txt) Tekstitiedostot (*.txt) - + CSV files (*.csv) - + Cppcheck - %1 Cppcheck - %1 - + + Failed to change the language: + +%1 + + + Failed to change the language: %1 @@ -640,56 +646,56 @@ Do you want to stop the checking and exit Cppcheck?. Failed to change language: %1 - Ohjelman kielen vaihtaminen epäonnistui: + Ohjelman kielen vaihtaminen epäonnistui: %1 + - Cppcheck Help - + Failed to load help file (not found) - + Failed to load help file - - + + Project files (*.cppcheck);;All files(*.*) - + Select Project File - + Select Project Filename - + No project file loaded - + Finnish Suomi - + English Englanti @@ -699,33 +705,38 @@ Do you want to stop the checking and exit Cppcheck?. - + + French + + + + Swedish Ruotsi - + German Saksa - + Russian Venäjä - + Polish Puola - + Japanese Japanease - + Serbian @@ -757,28 +768,50 @@ Do you want to stop the checking and exit Cppcheck?. - + + Project + + + + Project: - + Paths: - - - Browse... + + + Add... - - Include paths: + + + Edit - + + + Remove + + + + + Includes + + + + + Include directories: + + + + Defines: @@ -804,18 +837,22 @@ Do you want to stop the checking and exit Cppcheck?. QObject - Incorrect language specified! - Virheellinen kieli valittu! + Virheellinen kieli valittu! - + + Unknown language specified! + + + + Language file %1 not found! Language file %1.qm not found! Käännöstiedostoa %1 ei löytynyt! - + Failed to load translation for language %1 from file %2 Failed to load translation for language %1 from file %2.qm Käänöksen lataaminen kielelle %1 tiedostosta %2 epäonnistui @@ -825,71 +862,71 @@ Do you want to stop the checking and exit Cppcheck?. ResultsTree - + File Tiedosto - + Severity Tyyppi - + Line Rivi - + Summary - + Undefined file Määrittelemätön tiedosto - + Copy filename Kopioi tiedostonimi - + Copy full path Kopioi tiedoston koko polku - + Copy message - + Hide - + Cppcheck Cppcheck - + Configure the text file viewer program in Cppcheck preferences/Applications. You can open this error by specifying applications in program's settings. Voit asetuksista määritellä muita ohjelmia joilla avata tämän virheen sisältävän tiedoston. - + Could not find the file! - + Could not start %1 Please check the application path and parameters are correct. @@ -898,44 +935,44 @@ Please check the application path and parameters are correct. Tarkista että ohjelman polku ja parametrit ovat oikeat. - + Could not find file: %1 Please select the directory where file is located. - + Select Directory - + style Tyyli - + error Yleinen - + warning - + performance - + portability - + information @@ -1007,98 +1044,121 @@ Määrittääksesi minkä tyyppisiä virheitä näytetään, avaa näkymä valik Yleiset - + Include paths: - + + Add... - + Number of threads: Säikeiden lukumäärä: - + Ideal count: - + TextLabel - + Force checking all #ifdef configurations Check all #ifdef configurations Tarkista kaikki #ifdef kombinaatiot - + Show full path of files Näytä tiedostojen täysi polku - + Show "No errors found" message when no errors found Näytä "virheitä ei löytynyt"-viesti jos virheitä ei löydy - + Show internal warnings in log - + Enable inline suppressions - + + Paths + + + + + Edit + + + + + + Remove + + + + Applications Ohjelmat - + + Edit... + + + + + Set as default + + + Add application - Lisää ohjelma + Lisää ohjelma - Delete application - Poista ohjelma + Poista ohjelma - Modify application - Muokkaa ohjelmaa + Muokkaa ohjelmaa - Set as default application - Aseta oletusohjelmaksi + Aseta oletusohjelmaksi - + Reports Raportit - + Save all errors when creating report Tallenna kaikki virheet raporttia luodessa - + Save full path to files in reports Tallenna tiedostojen koko polku raportteihin - + Language @@ -1106,22 +1166,27 @@ Määrittääksesi minkä tyyppisiä virheitä näytetään, avaa näkymä valik SettingsDialog - + N/A - + Add a new application Lisää uusi ohjelma - + Modify an application Muokkaa ohjelmaa - + + [Default] + + + + Select include directory diff --git a/gui/cppcheck_fr.ts b/gui/cppcheck_fr.ts index bd9e29e7e..1c512ee03 100644 --- a/gui/cppcheck_fr.ts +++ b/gui/cppcheck_fr.ts @@ -339,7 +339,7 @@ kate -l(ligne) (fichier) %1 - Erreur lors du chargement de la langue : + Erreur lors du chargement de la langue : %1 @@ -563,6 +563,16 @@ Do you want to stop the checking and exit Cppcheck?. Serbian + + Failed to change the language: + +%1 + + + + French + + Project @@ -593,18 +603,34 @@ Do you want to stop the checking and exit Cppcheck?. Paths: - - Browse... - - - - Include paths: - - Defines: + + Project + + + + Add... + + + + Edit + + + + Remove + + + + Includes + + + + Include directories: + + ProjectFileDialog @@ -625,7 +651,7 @@ Do you want to stop the checking and exit Cppcheck?. QObject Incorrect language specified! - Langue incorrecte ! + Langue incorrecte ! Language file %1 not found! @@ -635,6 +661,10 @@ Do you want to stop the checking and exit Cppcheck?. Failed to load translation for language %1 from file %2 Erreur lors du chargement de la langue %1 depuis le fichier %2 + + Unknown language specified! + + ResultsTree @@ -798,19 +828,19 @@ Pour configurer les erreurs affichées, ouvrez le menu d'affichage. Add application - Ajouter une application + Ajouter une application Delete application - Supprimer l'application + Supprimer l'application Modify application - Modifier l'application + Modifier l'application Set as default application - Définir comme application par défaut + Définir comme application par défaut Reports @@ -856,6 +886,26 @@ Pour configurer les erreurs affichées, ouvrez le menu d'affichage.Language + + Paths + + + + Edit + + + + Remove + + + + Edit... + + + + Set as default + + SettingsDialog @@ -875,6 +925,10 @@ Pour configurer les erreurs affichées, ouvrez le menu d'affichage.Select include directory + + [Default] + + StatsDialog diff --git a/gui/cppcheck_ja.ts b/gui/cppcheck_ja.ts index 12d8c80ca..9b244d533 100644 --- a/gui/cppcheck_ja.ts +++ b/gui/cppcheck_ja.ts @@ -208,12 +208,12 @@ kate -l(line) (file) MainWindow - - - - - - + + + + + + Cppcheck Cppcheck @@ -525,44 +525,44 @@ kate -l(line) (file) ログ表示 - + No suitable files found to check! 解析可能なファイルではありません - + You must close the project file before selecting new files or directories! 新しいファイル/ディレクトリを解析するには現在のプロジェクトを閉じてください - + Select files to check チェック対象のファイルを選択 - + Select directory to check チェック対象のディレクトリを選択 - - - + + + Project: プロジェクト: - + XML files (*.xml) XML ファイル (*.xml) - + Open the report file レポートを開く - + Checking is running. Do you want to stop the checking and exit Cppcheck?. @@ -571,103 +571,109 @@ Do you want to stop the checking and exit Cppcheck?. 解析を停止してCppcheckを終了しますか?. - + License ライセンス - + Authors 作者 - + XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) XML ファイル (*.xml);;テキストファイル (*.txt);;CSV形式ファイル (*.csv) - + Save the report file レポートを保存 - + XML files version 1 (*.xml) - + XML files version 2 (*.xml) - + Text files (*.txt) テキストファイル (*.txt) - + CSV files (*.csv) CSV形式ファイル (*.csv) - + Cppcheck - %1 Cppcheck - %1 - + + Failed to change the language: + +%1 + + + Failed to change the language: %1 - 言語の切り替えに失敗: + 言語の切り替えに失敗: %1 + - Cppcheck Help Cppcheck ヘルプ - + Failed to load help file (not found) ヘルプファイルが見つかりませんでした - + Failed to load help file ヘルプファイルの読み込みに失敗しました - - + + Project files (*.cppcheck);;All files(*.*) プロジェクトファイル (*.cppcheck);;All files(*.*) - + Select Project File プロジェクトファイルを選択 - + Select Project Filename プロジェクトファイル名を選択 - + No project file loaded プロジェクトファイルが読み込まれていません - + English @@ -677,38 +683,43 @@ Do you want to stop the checking and exit Cppcheck?. - + Finnish - + + French + + + + Swedish - + German - + Russian - + Polish - + Japanese Japanease - + Serbian @@ -740,28 +751,54 @@ Do you want to stop the checking and exit Cppcheck?. プロジェクトファイル - + + Project + プロジェクト + + + Project: プロジェクト名: - + Paths: パス: - - - Browse... - + + + Add... + 追加... + + + + + Edit + + + + + + Remove + + + + + Includes + + + + + Include directories: + - Include paths: - Include ディレクトリ: + Include ディレクトリ: - + Defines: Defines: @@ -787,17 +824,17 @@ Do you want to stop the checking and exit Cppcheck?. QObject - - Incorrect language specified! + + Unknown language specified! - + Language file %1 not found! 言語ファイル %1 が見つかりません! - + Failed to load translation for language %1 from file %2 @@ -806,70 +843,70 @@ Do you want to stop the checking and exit Cppcheck?. ResultsTree - + File ファイル - + Severity 警告種別 - + Line - + Summary 内容 - + Undefined file 未定義ファイル - + Copy filename ファイル名をコピー - + Copy full path フルパスをコピー - + Copy message メッセージをコピー - + Hide 非表示 - + Cppcheck Cppcheck - + Configure the text file viewer program in Cppcheck preferences/Applications. メニューの「編集」→「設定」からテキストファイルを表示するアプリケーションを設定してください。 - + Could not find the file! ファイルが見つかりません - + Could not start %1 Please check the application path and parameters are correct. @@ -878,7 +915,7 @@ Please check the application path and parameters are correct. 実行ファイルパスや引数の設定を確認してください。 - + Could not find file: %1 Please select the directory where file is located. @@ -887,37 +924,37 @@ Please select the directory where file is located. ディレクトリにファイルが存在するか確認してください。 - + Select Directory ディレクトリを選択 - + style スタイル - + error エラー - + warning 警告 - + performance パフォーマンス - + portability - + information @@ -988,98 +1025,121 @@ To toggle what kind of errors are shown, open view menu. 全般 - + Include paths: Include ディレクトリ: - + + Add... 追加... - + Number of threads: 解析スレッド数: - + Ideal count: - + TextLabel - + Force checking all #ifdef configurations Check all #ifdef configurations すべての #ifdef をチェックする - + Show full path of files ファイルのフルパスを表示 - + Show "No errors found" message when no errors found エラーが無いときは"エラーなし"を表示 - + Show internal warnings in log cppcheck内部警告をログに表示する - + Enable inline suppressions - + + Paths + + + + + Edit + + + + + + Remove + + + + Applications アプリケーション - + + Edit... + + + + + Set as default + + + Add application - アプリケーションを追加 + アプリケーションを追加 - Delete application - アプリケーションの削除 + アプリケーションの削除 - Modify application - アプリケーション設定の変更 + アプリケーション設定の変更 - Set as default application - デフォルトアプリケーションに設定 + デフォルトアプリケーションに設定 - + Reports レポート - + Save all errors when creating report すべての警告/エラーを保存 - + Save full path to files in reports ファイルのフルパスを保存 - + Language @@ -1087,22 +1147,27 @@ To toggle what kind of errors are shown, open view menu. SettingsDialog - + N/A - + Add a new application 新しいアプリケーションの追加 - + Modify an application アプリケーションの変更 - + + [Default] + + + + Select include directory include ディレクトリを選択 diff --git a/gui/cppcheck_nl.ts b/gui/cppcheck_nl.ts index e34529164..957f80c22 100644 --- a/gui/cppcheck_nl.ts +++ b/gui/cppcheck_nl.ts @@ -222,12 +222,12 @@ kate -l(line) (file) MainWindow - - - - - - + + + + + + Cppcheck Cppcheck @@ -539,97 +539,103 @@ kate -l(line) (file) &Help - + Select files to check Selecteer bestanden om te controleren - + Select directory to check Selecteer een map om te controleren - + No suitable files found to check! Geen geschikte bestanden gevonden om te controleren! - + License Licentie - + Authors Auteurs - + XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) XML bestanden (*.xml);;Tekst bestanden (*.txt);;CSV bestanden (*.csv) - + Save the report file Rapport opslaan - + XML files (*.xml) XML bestanden (*.xml) - + You must close the project file before selecting new files or directories! - - - + + + Project: - + Open the report file - + Checking is running. Do you want to stop the checking and exit Cppcheck?. - + XML files version 1 (*.xml) - + XML files version 2 (*.xml) - + Text files (*.txt) Tekst bestanden (*.txt) - + CSV files (*.csv) - + Cppcheck - %1 Cppcheck - %1 - + + Failed to change the language: + +%1 + + + Failed to change the language: %1 @@ -638,54 +644,54 @@ Do you want to stop the checking and exit Cppcheck?. Failed to change language: %1 - Kon de taal niet wisselen: + Kon de taal niet wisselen: %1 + - Cppcheck Help - + Failed to load help file (not found) - + Failed to load help file - - + + Project files (*.cppcheck);;All files(*.*) - + Select Project File - + Select Project Filename - + No project file loaded - + Finnish Fins - + English Engels @@ -695,33 +701,38 @@ Do you want to stop the checking and exit Cppcheck?. Nederlands - + + French + + + + Swedish Zweeds - + German Duits - + Russian Russisch - + Polish Pools - + Japanese Japanease - + Serbian @@ -753,28 +764,50 @@ Do you want to stop the checking and exit Cppcheck?. - + + Project + + + + Project: - + Paths: - - - Browse... + + + Add... - - Include paths: + + + Edit - + + + Remove + + + + + Includes + + + + + Include directories: + + + + Defines: @@ -800,18 +833,22 @@ Do you want to stop the checking and exit Cppcheck?. QObject - Incorrect language specified! - Ongeldige taal gespecifieerd! + Ongeldige taal gespecifieerd! - + + Unknown language specified! + + + + Language file %1 not found! Language file %1.qm not found! Kon het taalbestand niet vinden: %1! - + Failed to load translation for language %1 from file %2 Failed to load translation for language %1 from file %2.qm Kon de vertaling voor taal %1 in bestand %2 niet laden @@ -821,71 +858,71 @@ Do you want to stop the checking and exit Cppcheck?. ResultsTree - + File Bestand - + Severity Ernst - + Line Regel - + Summary - + Undefined file Niet gedefinieerd bestand - + Copy filename Kopier bestandsnaam - + Copy full path Kopieer volledig pad - + Copy message - + Hide - + Cppcheck Cppcheck - + Configure the text file viewer program in Cppcheck preferences/Applications. You can open this error by specifying applications in program's settings. U dient een applicatie te configureren in de instellingen om deze fout in te openen. - + Could not find the file! - + Could not start %1 Please check the application path and parameters are correct. @@ -894,44 +931,44 @@ Please check the application path and parameters are correct. Gelieve te controleren of de het pad en de parameters correct zijn. - + Could not find file: %1 Please select the directory where file is located. - + Select Directory - + style Stijlfouten - + error Fouten - + warning - + performance - + portability - + information @@ -1003,98 +1040,121 @@ Gebruik het uitzicht menu om te selecteren welke fouten getoond worden.Algemeen - + Include paths: - + + Add... - + Number of threads: Aantal threads: - + Ideal count: - + TextLabel - + Force checking all #ifdef configurations Check all #ifdef configurations Controleer alle #ifdef combinaties - + Show full path of files Toon het volledige pad van bestanden - + Show "No errors found" message when no errors found Toon "Geen fouten gevonden" indien geen fouten gevonden werden - + Show internal warnings in log - + Enable inline suppressions - + + Paths + + + + + Edit + + + + + + Remove + + + + Applications Applicaties - + + Edit... + + + + + Set as default + + + Add application - Applicatie toevoegen + Applicatie toevoegen - Delete application - Applicatie verwijderen + Applicatie verwijderen - Modify application - Applicatie wijzigen + Applicatie wijzigen - Set as default application - Configureer als standaard applicatie + Configureer als standaard applicatie - + Reports Rapporten - + Save all errors when creating report Alle fouten opslaan - + Save full path to files in reports Volledig pad opslaan - + Language @@ -1102,22 +1162,27 @@ Gebruik het uitzicht menu om te selecteren welke fouten getoond worden. SettingsDialog - + N/A - + Add a new application Nieuwe applicatie toevoegen - + Modify an application Applicatie wijzigen - + + [Default] + + + + Select include directory diff --git a/gui/cppcheck_pl.ts b/gui/cppcheck_pl.ts index f80b37956..e00aa58de 100644 --- a/gui/cppcheck_pl.ts +++ b/gui/cppcheck_pl.ts @@ -209,12 +209,12 @@ kate -l(line) (file) MainWindow - - - - - - + + + + + + Cppcheck @@ -526,143 +526,141 @@ kate -l(line) (file) - + No suitable files found to check! - + You must close the project file before selecting new files or directories! - + Select files to check - + Select directory to check - - - + + + Project: - + Open the report file - + License - + Authors - + XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) - + Save the report file - + XML files version 1 (*.xml) - + XML files version 2 (*.xml) + + Failed to change the language: + +%1 + + + + - Cppcheck Help - + Failed to load help file (not found) - + Failed to load help file - + Select Project Filename - + No project file loaded - + XML files (*.xml) - + Checking is running. Do you want to stop the checking and exit Cppcheck?. - + Text files (*.txt) - + CSV files (*.csv) - + Cppcheck - %1 - - Failed to change the language: - -%1 - - - - - - - + + Project files (*.cppcheck);;All files(*.*) - + Select Project File - + English @@ -672,38 +670,43 @@ Do you want to stop the checking and exit Cppcheck?. - + Finnish - + + French + + + + Swedish - + German - + Russian - + Polish - + Japanese Japanease - + Serbian @@ -735,28 +738,50 @@ Do you want to stop the checking and exit Cppcheck?. - + + Project + + + + Project: - + Paths: - - - Browse... + + + Add... - - Include paths: + + + Edit - + + + Remove + + + + + Includes + + + + + Include directories: + + + + Defines: @@ -782,17 +807,17 @@ Do you want to stop the checking and exit Cppcheck?. QObject - - Incorrect language specified! + + Unknown language specified! - + Language file %1 not found! - + Failed to load translation for language %1 from file %2 @@ -801,114 +826,114 @@ Do you want to stop the checking and exit Cppcheck?. ResultsTree - + File - + Severity - + Line - + Summary - + Undefined file - + Copy filename - + Copy full path - + Copy message - + Hide - + Cppcheck - + Configure the text file viewer program in Cppcheck preferences/Applications. - + Could not find the file! - + Could not start %1 Please check the application path and parameters are correct. - + Could not find file: %1 Please select the directory where file is located. - + Select Directory - + style - + error - + warning - + performance - + portability - + information @@ -979,98 +1004,105 @@ To toggle what kind of errors are shown, open view menu. - + Include paths: - + + Add... - + Number of threads: - + Ideal count: - + TextLabel - + Force checking all #ifdef configurations Check all #ifdef configurations - + Show full path of files - + Show "No errors found" message when no errors found - + Show internal warnings in log - + Enable inline suppressions - + + Paths + + + + + Edit + + + + + + Remove + + + + Applications - - Add application + + Edit... - - Delete application + + Set as default - - Modify application - - - - - Set as default application - - - - + Reports - + Save all errors when creating report - + Save full path to files in reports - + Language @@ -1078,22 +1110,27 @@ To toggle what kind of errors are shown, open view menu. SettingsDialog - + N/A - + Add a new application - + Modify an application - + + [Default] + + + + Select include directory diff --git a/gui/cppcheck_ru.ts b/gui/cppcheck_ru.ts index 9bc1aecb2..8f66703e5 100644 --- a/gui/cppcheck_ru.ts +++ b/gui/cppcheck_ru.ts @@ -212,12 +212,12 @@ kate -l(line) (file) MainWindow - - - - - - + + + + + + Cppcheck Cppcheck @@ -529,97 +529,103 @@ kate -l(line) (file) Помощь - + Select files to check Выберите файлы для проверки - + Select directory to check Выберите каталог для проверки - + No suitable files found to check! - + License Лицензия - + Authors Авторы - + XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) - + Save the report file - + XML files (*.xml) - + You must close the project file before selecting new files or directories! - - - + + + Project: - + Open the report file - + Checking is running. Do you want to stop the checking and exit Cppcheck?. - + XML files version 1 (*.xml) - + XML files version 2 (*.xml) - + Text files (*.txt) Текстовые файлы (*.txt) - + CSV files (*.csv) - + Cppcheck - %1 Cppcheck - %1 - + + Failed to change the language: + +%1 + + + Failed to change the language: %1 @@ -628,56 +634,56 @@ Do you want to stop the checking and exit Cppcheck?. Failed to change language: %1 - Невозможно изменить язык приложения: + Невозможно изменить язык приложения: %1 + - Cppcheck Help - + Failed to load help file (not found) - + Failed to load help file - - + + Project files (*.cppcheck);;All files(*.*) - + Select Project File - + Select Project Filename - + No project file loaded - + Finnish Финский - + English Английский @@ -687,33 +693,38 @@ Do you want to stop the checking and exit Cppcheck?. - + + French + + + + Swedish Швецкий - + German Немецкий - + Russian Русский - + Polish - + Japanese Japanease - + Serbian @@ -745,28 +756,50 @@ Do you want to stop the checking and exit Cppcheck?. - + + Project + + + + Project: - + Paths: - - - Browse... + + + Add... - - Include paths: + + + Edit - + + + Remove + + + + + Includes + + + + + Include directories: + + + + Defines: @@ -792,18 +825,22 @@ Do you want to stop the checking and exit Cppcheck?. QObject - Incorrect language specified! - Выбран неверный язык! + Выбран неверный язык! - + + Unknown language specified! + + + + Language file %1 not found! Language file %1.qm not found! - + Failed to load translation for language %1 from file %2 Failed to load translation for language %1 from file %2.qm Ошибка загрузки переводов для языка %1 из файла %2 @@ -813,115 +850,115 @@ Do you want to stop the checking and exit Cppcheck?. ResultsTree - + File Файл - + Severity Важность - + Line Строка - + Summary - + Undefined file - + Copy filename Скопировать имя файла - + Copy full path Скопировать полный путь - + Copy message - + Hide - + Cppcheck Cppcheck - + Configure the text file viewer program in Cppcheck preferences/Applications. You can open this error by specifying applications in program's settings. - + Could not find the file! - + Could not start %1 Please check the application path and parameters are correct. - + Could not find file: %1 Please select the directory where file is located. - + Select Directory - + style - + error - + warning - + performance - + portability - + information @@ -992,98 +1029,105 @@ To toggle what kind of errors are shown, open view menu. Общие - + Include paths: - + + Add... - + Number of threads: Количество потоков исполнения: - + Ideal count: - + TextLabel - + Force checking all #ifdef configurations Check all #ifdef configurations Проверять все варианты #ifdef конфигураций - + Show full path of files Показывать полные пути к файлам - + Show "No errors found" message when no errors found Показывать сообщение, если ошибок не найдено - + Show internal warnings in log - + Enable inline suppressions - + + Paths + + + + + Edit + + + + + + Remove + + + + Applications - - Add application + + Edit... - - Delete application + + Set as default - - Modify application - - - - - Set as default application - - - - + Reports Отчёты - + Save all errors when creating report Сохранять все ошибки при создании отчёта - + Save full path to files in reports Сохранять полные пути к файлам в отчётах - + Language @@ -1091,22 +1135,27 @@ To toggle what kind of errors are shown, open view menu. SettingsDialog - + N/A - + Add a new application - + Modify an application - + + [Default] + + + + Select include directory diff --git a/gui/cppcheck_se.ts b/gui/cppcheck_se.ts index 593a59fa7..3cdea4876 100644 --- a/gui/cppcheck_se.ts +++ b/gui/cppcheck_se.ts @@ -222,12 +222,12 @@ kate -l(line) (file) MainWindow - - - - - - + + + + + + Cppcheck Cppcheck @@ -540,65 +540,65 @@ kate -l(line) (file) &Hjälp - + Select files to check Välj filer att kontrollera - + Select directory to check Välj katalog som skall kontrolleras - + No suitable files found to check! Inga lämpliga filer hittades! - + License Licens - + Authors Utvecklare - + XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) XML filer (*.xml);;Text filer (*.txt);;CSV filer (*.csv) - + Save the report file Spara rapport - + XML files (*.xml) XML filer (*.xml) - + You must close the project file before selecting new files or directories! Du måste stänga projektfilen innan nya filer eller sökvägar kan väljas! - - - + + + Project: Projekt. - + Open the report file Öppna rapportfilen - + Checking is running. Do you want to stop the checking and exit Cppcheck?. @@ -607,32 +607,38 @@ Do you want to stop the checking and exit Cppcheck?. Vill du stoppa analysen och avsluta Cppcheck? - + XML files version 1 (*.xml) - + XML files version 2 (*.xml) - + Text files (*.txt) Text filer (*.txt) - + CSV files (*.csv) CSV filer (*.csv) - + Cppcheck - %1 Cppcheck - %1 - + + Failed to change the language: + +%1 + + + Failed to change the language: %1 @@ -641,56 +647,56 @@ Vill du stoppa analysen och avsluta Cppcheck? Failed to change language: %1 - Misslyckades med att byta språk: + Misslyckades med att byta språk: %1 + - Cppcheck Help Cppcheck Hjälp - + Failed to load help file (not found) Misslyckades att öppna hjälpfilen (hittades ej) - + Failed to load help file Misslykades att öppna hjälpfilen - - + + Project files (*.cppcheck);;All files(*.*) Projektfiler (*.cppcheck);;Alla filer(*.*) - + Select Project File Välj projektfil - + Select Project Filename Välj Projektfil - + No project file loaded Inget projekt laddat - + Finnish Finska - + English Engelska @@ -700,33 +706,38 @@ Vill du stoppa analysen och avsluta Cppcheck? Nederländska - + + French + + + + Swedish Svenska - + German Tyska - + Russian Ryska - + Polish Polska - + Japanese Japanease Japanska - + Serbian Serbiska @@ -758,28 +769,58 @@ Vill du stoppa analysen och avsluta Cppcheck? Projektfil - + + Project + Projekt + + + Project: Projekt: - + Paths: Sökvägar: - - + + + Add... + Lägg till... + + + + + Edit + + + + + + Remove + + + + + Includes + + + + + Include directories: + + + Browse... - Bläddra... + Bläddra... - Include paths: - Include sökvägar: + Include sökvägar: - + Defines: Defines: @@ -805,18 +846,22 @@ Vill du stoppa analysen och avsluta Cppcheck? QObject - Incorrect language specified! - valt språk är ej korrekt! + valt språk är ej korrekt! - + + Unknown language specified! + + + + Language file %1 not found! Language file %1.qm not found! Språk filen %1 hittades ej! - + Failed to load translation for language %1 from file %2 Failed to load translation for language %1 from file %2.qm Misslyckades med att ladda översättningen för %1 från filen %2 @@ -826,71 +871,71 @@ Vill du stoppa analysen och avsluta Cppcheck? ResultsTree - + File Fil - + Severity Typ - + Line Rad - + Summary Sammanfattning - + Undefined file Odefinierad fil - + Copy filename Kopiera filnamn - + Copy full path Kopiera full sökväg - + Copy message Kopiera meddelande - + Hide Dölj - + Cppcheck Cppcheck - + Configure the text file viewer program in Cppcheck preferences/Applications. You can open this error by specifying applications in program's settings. Konfigurera program i inställningar/program. - + Could not find the file! Kunde inte hitta filen! - + Could not start %1 Please check the application path and parameters are correct. @@ -899,7 +944,7 @@ Please check the application path and parameters are correct. Kontrollera att sökvägen och parametrarna är korrekta. - + Could not find file: %1 Please select the directory where file is located. @@ -908,37 +953,37 @@ Please select the directory where file is located. Välj mappen där filen finns. - + Select Directory Välj mapp - + style stil - + error fel - + warning varning - + performance prestanda - + portability portabilitet - + information information @@ -1010,98 +1055,121 @@ För att ställa in vilka fel som skall visas använd visa menyn. Allmänt - + Include paths: Include sökvägar: - + + Add... Lägg till... - + Number of threads: Antal trådar: - + Ideal count: Optimalt värde: - + TextLabel TextLabel - + Force checking all #ifdef configurations Check all #ifdef configurations Kontrollera alla #ifdef konfigurationer - + Show full path of files Visa den fulla sökvägen för filer - + Show "No errors found" message when no errors found Visa "Inga fel hittades" meddelande när inga fel hittas - + Show internal warnings in log Visa interna fel i loggen - + Enable inline suppressions Använd inline suppressions - + + Paths + + + + + Edit + + + + + + Remove + + + + Applications Program - + + Edit... + + + + + Set as default + + + Add application - Lägg till program + Lägg till program - Delete application - Ta bort program + Ta bort program - Modify application - Ändra program + Ändra program - Set as default application - Ange som standard program + Ange som standard program - + Reports Rapporter - + Save all errors when creating report Spara alla fel - + Save full path to files in reports Spara fulla sökvägar - + Language Språk @@ -1109,22 +1177,27 @@ För att ställa in vilka fel som skall visas använd visa menyn. SettingsDialog - + N/A Ej tillgängligt - + Add a new application Lägg till program - + Modify an application Ändra program - + + [Default] + + + + Select include directory Välj include mapp diff --git a/gui/cppcheck_sr.ts b/gui/cppcheck_sr.ts index 91eb79c7a..fa23f823a 100644 --- a/gui/cppcheck_sr.ts +++ b/gui/cppcheck_sr.ts @@ -222,12 +222,12 @@ kate -l(line) (file) MainWindow - - - - - - + + + + + + Cppcheck Cppcheck @@ -539,97 +539,103 @@ kate -l(line) (file) &Help - + Select files to check Select files to check - + Select directory to check Select directory to check - + No suitable files found to check! No suitable files found to check! - + License License - + Authors Authors - + XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) - + Save the report file Save the report file - + XML files (*.xml) XML files (*.xml) - + You must close the project file before selecting new files or directories! - - - + + + Project: - + Open the report file - + Checking is running. Do you want to stop the checking and exit Cppcheck?. - + XML files version 1 (*.xml) - + XML files version 2 (*.xml) - + Text files (*.txt) Text files (*.txt) - + CSV files (*.csv) - + Cppcheck - %1 Cppcheck - %1 - + + Failed to change the language: + +%1 + + + Failed to change the language: %1 @@ -638,54 +644,54 @@ Do you want to stop the checking and exit Cppcheck?. Failed to change language: %1 - Failed to change language: + Failed to change language: %1 + - Cppcheck Help - + Failed to load help file (not found) - + Failed to load help file - - + + Project files (*.cppcheck);;All files(*.*) - + Select Project File - + Select Project Filename - + No project file loaded - + Finnish Finski - + English Engleski @@ -695,33 +701,38 @@ Do you want to stop the checking and exit Cppcheck?. Holandski - + + French + + + + Swedish Švedski - + German Nemački - + Russian Ruski - + Polish Poljski - + Japanese Japanease Japanski - + Serbian Srpski @@ -753,28 +764,50 @@ Do you want to stop the checking and exit Cppcheck?. - + + Project + + + + Project: - + Paths: - - - Browse... + + + Add... - - Include paths: + + + Edit - + + + Remove + + + + + Includes + + + + + Include directories: + + + + Defines: @@ -800,18 +833,22 @@ Do you want to stop the checking and exit Cppcheck?. QObject - Incorrect language specified! - Incorrect language specified! + Incorrect language specified! - + + Unknown language specified! + + + + Language file %1 not found! Language file %1.qm not found! Could not find the file: %1! - + Failed to load translation for language %1 from file %2 Failed to load translation for language %1 from file %2.qm Failed to load translation for language %1 from file %2 @@ -821,71 +858,71 @@ Do you want to stop the checking and exit Cppcheck?. ResultsTree - + File File - + Severity Severity - + Line Line - + Summary - + Undefined file Undefined file - + Copy filename Copy filename - + Copy full path Copy full path - + Copy message - + Hide - + Cppcheck Cppcheck - + Configure the text file viewer program in Cppcheck preferences/Applications. You can open this error by specifying applications in program's settings. You can open this error by specifying applications in program's settings. - + Could not find the file! - + Could not start %1 Please check the application path and parameters are correct. @@ -894,44 +931,44 @@ Please check the application path and parameters are correct. Please check the application path and parameters are correct. - + Could not find file: %1 Please select the directory where file is located. - + Select Directory - + style Style - + error Error - + warning - + performance - + portability - + information @@ -1003,98 +1040,121 @@ To toggle what kind of errors are shown, open view menu. General - + Include paths: - + + Add... - + Number of threads: Number of threads: - + Ideal count: - + TextLabel - + Force checking all #ifdef configurations Check all #ifdef configurations Check all #ifdef configurations - + Show full path of files Show full path of files - + Show "No errors found" message when no errors found Show "No errors found" message when no errors found - + Show internal warnings in log - + Enable inline suppressions - + + Paths + + + + + Edit + + + + + + Remove + + + + Applications Applications - + + Edit... + + + + + Set as default + + + Add application - Add application + Add application - Delete application - Delete application + Delete application - Modify application - Modify application + Modify application - Set as default application - Set as default application + Set as default application - + Reports Reports - + Save all errors when creating report Save all errors when creating report - + Save full path to files in reports Save full path to files in reports - + Language @@ -1102,22 +1162,27 @@ To toggle what kind of errors are shown, open view menu. SettingsDialog - + N/A - + Add a new application Add a new application - + Modify an application Modify an application - + + [Default] + + + + Select include directory diff --git a/gui/filelist.cpp b/gui/filelist.cpp index cc1580904..4e26eb1f3 100644 --- a/gui/filelist.cpp +++ b/gui/filelist.cpp @@ -96,12 +96,54 @@ void FileList::AddPathList(const QStringList &paths) QStringList FileList::GetFileList() const { - QStringList names; - QFileInfo item; - foreach(item, mFileList) + if (mIgnoredPaths.empty()) + { + QStringList names; + foreach(QFileInfo item, mFileList) + { + QString name = QDir::fromNativeSeparators(item.canonicalFilePath()); + names << name; + } + return names; + } + else + { + return ApplyIgnoreList(); + } +} + +void FileList::AddIngoreList(const QStringList &paths) +{ + mIgnoredPaths = paths; +} + +QStringList FileList::ApplyIgnoreList() const +{ + QStringList paths; + foreach(QFileInfo item, mFileList) { QString name = QDir::fromNativeSeparators(item.canonicalFilePath()); - names << name; + if (!Match(name)) + paths << name; } - return names; + return paths; +} + +bool FileList::Match(const QString &path) const +{ + for (int i = 0; i < mIgnoredPaths.size(); i++) + { + if (mIgnoredPaths[i].endsWith('/')) + { + const QString pathignore("/" + mIgnoredPaths[i]); + if (path.indexOf(pathignore) != -1) + return true; + } + else + { + if (path.endsWith(mIgnoredPaths[i])) + return true; + } + } + return false; } diff --git a/gui/filelist.h b/gui/filelist.h index 1a1818408..a896e6070 100644 --- a/gui/filelist.h +++ b/gui/filelist.h @@ -30,6 +30,10 @@ * can be also added recursively when all files in subdirectories are added too. * The filenames are matched against the filter and only those files whose * filename extension is included in the filter list are added. + * + * This class also handles filtering of paths against ignore filters given. If + * there is ignore filters then only paths not matching those filters are + * returned. */ class FileList { @@ -60,6 +64,12 @@ public: */ QStringList GetFileList() const; + /** + * @brief Add list of paths to ignore list. + * @param paths Paths to ignore. + */ + void AddIngoreList(const QStringList &paths); + protected: /** @@ -74,8 +84,25 @@ protected: */ bool FilterMatches(const QFileInfo &inf); + /** + * @brief Get filtered list of paths. + * This method takes the list of paths and applies the ignore lists to + * it. And then returns the list of paths that did not match the + * ignore filters. + * @return Filtered list of paths. + */ + QStringList ApplyIgnoreList() const; + + /** + * @brief Test if path matches any of the ignore filters. + * @param path Path to test against filters. + * @return true if any of the filters matches, false otherwise. + */ + bool Match(const QString &path) const; + private: QFileInfoList mFileList; + QStringList mIgnoredPaths; }; #endif // FILELIST_H diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index c7b966b6e..1901b0a08 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -191,6 +191,8 @@ void MainWindow::DoCheckFiles(const QStringList &files) FileList pathList; pathList.AddPathList(files); + if (mProject) + pathList.AddIngoreList(mProject->GetProjectFile()->GetIgnoredPaths()); QStringList fileNames = pathList.GetFileList(); mUI.mResults->Clear(); @@ -724,8 +726,6 @@ void MainWindow::OpenHtmlHelpContents() void MainWindow::OpenProjectFile() { - delete mProject; - const QString filter = tr("Project files (*.cppcheck);;All files(*.*)"); QString filepath = QFileDialog::getOpenFileName(this, tr("Select Project File"), @@ -740,6 +740,7 @@ void MainWindow::OpenProjectFile() mUI.mActionCloseProjectFile->setEnabled(true); mUI.mActionEditProjectFile->setEnabled(true); + delete mProject; mProject = new Project(filepath, this); mProject->Open(); QString rootpath = mProject->GetProjectFile()->GetRootPath(); diff --git a/gui/project.cpp b/gui/project.cpp index 963fcfeee..3467da289 100644 --- a/gui/project.cpp +++ b/gui/project.cpp @@ -85,6 +85,9 @@ void Project::Edit() dlg.SetDefines(defines); QStringList paths = mPFile->GetCheckPaths(); dlg.SetPaths(paths); + QStringList ignorepaths = mPFile->GetIgnoredPaths(); + dlg.SetIgnorePaths(ignorepaths); + int rv = dlg.exec(); if (rv == QDialog::Accepted) { @@ -96,6 +99,9 @@ void Project::Edit() mPFile->SetDefines(defines); QStringList paths = dlg.GetPaths(); mPFile->SetCheckPaths(paths); + QStringList ignorepaths = dlg.GetIgnorePaths(); + mPFile->SetIgnoredPaths(ignorepaths); + bool writeSuccess = mPFile->Write(); if (!writeSuccess) { diff --git a/gui/projectfile.cpp b/gui/projectfile.cpp index abd82ebcd..f227cdfa4 100644 --- a/gui/projectfile.cpp +++ b/gui/projectfile.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "projectfile.h" static const char ProjectElementName[] = "project"; @@ -37,6 +38,9 @@ static const char PathName[] = "dir"; static const char PathNameAttrib[] = "name"; static const char RootPathName[] = "root"; static const char RootPathNameAttrib[] = "name"; +static const char IgnoreElementName[] = "ignore"; +static const char IgnorePathName[] = "path"; +static const char IgnorePathNameAttrib[] = "name"; ProjectFile::ProjectFile(QObject *parent) : QObject(parent) @@ -87,6 +91,10 @@ bool ProjectFile::Read(const QString &filename) if (insideProject && xmlReader.name() == DefinesElementName) ReadDefines(xmlReader); + // Find ignore list from inside project element + if (insideProject && xmlReader.name() == IgnoreElementName) + ReadIgnores(xmlReader); + break; case QXmlStreamReader::EndElement: @@ -117,7 +125,12 @@ bool ProjectFile::Read(const QString &filename) QStringList ProjectFile::GetIncludeDirs() const { - return mIncludeDirs; + QStringList dirs; + foreach(QString path, mIncludeDirs) + { + dirs << QDir::fromNativeSeparators(path); + } + return dirs; } QStringList ProjectFile::GetDefines() const @@ -127,7 +140,22 @@ QStringList ProjectFile::GetDefines() const QStringList ProjectFile::GetCheckPaths() const { - return mPaths; + QStringList paths; + foreach(QString path, mPaths) + { + paths << QDir::fromNativeSeparators(path); + } + return paths; +} + +QStringList ProjectFile::GetIgnoredPaths() const +{ + QStringList paths; + foreach(QString path, mIgnoredPaths) + { + paths << QDir::fromNativeSeparators(path); + } + return paths; } void ProjectFile::ReadRootPath(QXmlStreamReader &reader) @@ -263,21 +291,67 @@ void ProjectFile::ReadCheckPaths(QXmlStreamReader &reader) while (!allRead); } -void ProjectFile::SetIncludes(QStringList includes) +void ProjectFile::ReadIgnores(QXmlStreamReader &reader) +{ + QXmlStreamReader::TokenType type; + bool allRead = false; + do + { + type = reader.readNext(); + switch (type) + { + case QXmlStreamReader::StartElement: + // Read define-elements + if (reader.name().toString() == IgnorePathName) + { + QXmlStreamAttributes attribs = reader.attributes(); + QString name = attribs.value("", IgnorePathNameAttrib).toString(); + if (!name.isEmpty()) + mIgnoredPaths << name; + } + break; + + case QXmlStreamReader::EndElement: + if (reader.name().toString() == IgnoreElementName) + allRead = true; + break; + + // Not handled + case QXmlStreamReader::NoToken: + case QXmlStreamReader::Invalid: + case QXmlStreamReader::StartDocument: + case QXmlStreamReader::EndDocument: + case QXmlStreamReader::Characters: + case QXmlStreamReader::Comment: + case QXmlStreamReader::DTD: + case QXmlStreamReader::EntityReference: + case QXmlStreamReader::ProcessingInstruction: + break; + } + } + while (!allRead); +} + +void ProjectFile::SetIncludes(const QStringList &includes) { mIncludeDirs = includes; } -void ProjectFile::SetDefines(QStringList defines) +void ProjectFile::SetDefines(const QStringList &defines) { mDefines = defines; } -void ProjectFile::SetCheckPaths(QStringList paths) +void ProjectFile::SetCheckPaths(const QStringList &paths) { mPaths = paths; } +void ProjectFile::SetIgnoredPaths(const QStringList &paths) +{ + mIgnoredPaths = paths; +} + bool ProjectFile::Write(const QString &filename) { if (!filename.isEmpty()) @@ -303,8 +377,7 @@ bool ProjectFile::Write(const QString &filename) if (!mIncludeDirs.isEmpty()) { xmlWriter.writeStartElement(IncludDirElementName); - QString incdir; - foreach(incdir, mIncludeDirs) + foreach(QString incdir, mIncludeDirs) { xmlWriter.writeStartElement(DirElementName); xmlWriter.writeAttribute(DirNameAttrib, incdir); @@ -316,8 +389,7 @@ bool ProjectFile::Write(const QString &filename) if (!mDefines.isEmpty()) { xmlWriter.writeStartElement(DefinesElementName); - QString define; - foreach(define, mDefines) + foreach(QString define, mDefines) { xmlWriter.writeStartElement(DefineName); xmlWriter.writeAttribute(DefineNameAttrib, define); @@ -329,8 +401,7 @@ bool ProjectFile::Write(const QString &filename) if (!mPaths.isEmpty()) { xmlWriter.writeStartElement(PathsElementName); - QString path; - foreach(path, mPaths) + foreach(QString path, mPaths) { xmlWriter.writeStartElement(PathName); xmlWriter.writeAttribute(PathNameAttrib, path); @@ -339,6 +410,18 @@ bool ProjectFile::Write(const QString &filename) xmlWriter.writeEndElement(); } + if (!mIgnoredPaths.isEmpty()) + { + xmlWriter.writeStartElement(IgnoreElementName); + foreach(QString path, mIgnoredPaths) + { + xmlWriter.writeStartElement(IgnorePathName); + xmlWriter.writeAttribute(IgnorePathNameAttrib, path); + xmlWriter.writeEndElement(); + } + xmlWriter.writeEndElement(); + } + xmlWriter.writeEndDocument(); file.close(); return true; diff --git a/gui/projectfile.h b/gui/projectfile.h index 23496c90c..2986f11a7 100644 --- a/gui/projectfile.h +++ b/gui/projectfile.h @@ -74,6 +74,12 @@ public: */ QStringList GetCheckPaths() const; + /** + * @brief Get list of paths to ignore. + * @return list of paths. + */ + QStringList GetIgnoredPaths() const; + /** * @brief Set project root path. * @param rootpath new project root path. @@ -87,19 +93,25 @@ public: * @brief Set list of includes. * @param includes List of defines. */ - void SetIncludes(QStringList includes); + void SetIncludes(const QStringList &includes); /** * @brief Set list of defines. * @param defines List of defines. */ - void SetDefines(QStringList defines); + void SetDefines(const QStringList &defines); /** * @brief Set list of paths to check. * @param defines List of paths. */ - void SetCheckPaths(QStringList paths); + void SetCheckPaths(const QStringList &paths); + + /** + * @brief Set list of paths to ignore. + * @param defines List of paths. + */ + void SetIgnoredPaths(const QStringList &paths); /** * @brief Write project file (to disk). @@ -142,6 +154,12 @@ protected: */ void ReadCheckPaths(QXmlStreamReader &reader); + /** + * @brief Read lists of ignores. + * @param reader XML stream reader. + */ + void ReadIgnores(QXmlStreamReader &reader); + private: /** @@ -171,6 +189,11 @@ private: * @brief List of paths to check. */ QStringList mPaths; + + /** + * @brief Paths ignored from the check. + */ + QStringList mIgnoredPaths; }; /// @} #endif // PROJECT_FILE_H diff --git a/gui/projectfile.txt b/gui/projectfile.txt index 2724e1eba..eed96379b 100644 --- a/gui/projectfile.txt +++ b/gui/projectfile.txt @@ -27,6 +27,9 @@ program. The format is: + + + where: @@ -42,5 +45,7 @@ where: recommended that relative paths are used for paths inside the project root folder for better portability. - defines element contains a list of C/C++ preprocessor defines. +- ignore element contains list of paths to ignore. The path can be a + directory (must end with path separator) or file. See also gui.cppcheck file in gui-directory of cppcheck sources. diff --git a/gui/projectfile.ui b/gui/projectfile.ui index 6cc570c31..9afb0f83e 100644 --- a/gui/projectfile.ui +++ b/gui/projectfile.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 159 + 467 + 329 @@ -15,99 +15,247 @@ - - - - - Project: - - - mEditProjectRoot - - - - - - - - - - - - - - Paths: - - - mEditPaths - - - - - - - - - - Browse... - - - - - - - - - - - Include paths: - - - mEditIncludePaths - - - - - - - - - - Browse... - - - - - - - - - - - Defines: - - - mEditDefines - - - - - - - - - - - - Qt::Vertical + + + 2 - - - 20 - 40 - - - + + + Project + + + + + + + + + + Project: + + + mEditProjectRoot + + + + + + + + + + + + + + Defines: + + + mEditDefines + + + + + + + + + + + + + + + + Paths: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + Add... + + + + + + + Edit + + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + Includes + + + + + + Include directories: + + + + + + + + + QAbstractItemView::SelectRows + + + + + + + + + Add... + + + + + + + Edit + + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + Ignore + + + + + + Paths: + + + + + + + + + + + + + + Add... + + + + + + + Edit + + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + @@ -122,13 +270,18 @@ - mEditProjectRoot - mEditPaths - mBtnBrowsePaths - mEditIncludePaths - mBtnBrowseIncludes - mEditDefines mButtons + tabWidget + mEditProjectRoot + mEditDefines + mListPaths + mBtnAddPath + mBtnEditPath + mBtnRemovePath + mListIncludeDirs + mBtnAddInclude + mBtnEditInclude + mBtnRemoveInclude @@ -139,8 +292,8 @@ accept() - 257 - 148 + 266 + 319 157 @@ -155,8 +308,8 @@ reject() - 325 - 148 + 334 + 319 286 diff --git a/gui/projectfiledialog.cpp b/gui/projectfiledialog.cpp index 2eaddf2d3..89bfd2b2b 100644 --- a/gui/projectfiledialog.cpp +++ b/gui/projectfiledialog.cpp @@ -37,31 +37,68 @@ ProjectFileDialog::ProjectFileDialog(const QString &path, QWidget *parent) setWindowTitle(title); connect(mUI.mButtons, SIGNAL(accepted()), this, SLOT(accept())); - connect(mUI.mBtnBrowseIncludes, SIGNAL(clicked()), this, SLOT(BrowseIncludes())); - connect(mUI.mBtnBrowsePaths, SIGNAL(clicked()), this, SLOT(BrowsePaths())); + connect(mUI.mBtnAddInclude, SIGNAL(clicked()), this, SLOT(AddIncludeDir())); + connect(mUI.mBtnAddPath, SIGNAL(clicked()), this, SLOT(AddPath())); + connect(mUI.mBtnEditInclude, SIGNAL(clicked()), this, SLOT(EditIncludeDir())); + connect(mUI.mBtnRemoveInclude, SIGNAL(clicked()), this, SLOT(RemoveIncludeDir())); + connect(mUI.mBtnEditPath, SIGNAL(clicked()), this, SLOT(EditPath())); + connect(mUI.mBtnRemovePath, SIGNAL(clicked()), this, SLOT(RemovePath())); + connect(mUI.mBtnAddIgnorePath, SIGNAL(clicked()), this, SLOT(AddIgnorePath())); + connect(mUI.mBtnEditIgnorePath, SIGNAL(clicked()), this, SLOT(EditIgnorePath())); + connect(mUI.mBtnRemoveIgnorePath, SIGNAL(clicked()), this, SLOT(RemoveIgnorePath())); +} + +void ProjectFileDialog::AddIncludeDir(const QString &dir) +{ + if (dir.isNull() || dir.isEmpty()) + return; + + const QString newdir = QDir::toNativeSeparators(dir); + QListWidgetItem *item = new QListWidgetItem(newdir); + item->setFlags(item->flags() | Qt::ItemIsEditable); + mUI.mListIncludeDirs->addItem(item); +} + +void ProjectFileDialog::AddPath(const QString &path) +{ + if (path.isNull() || path.isEmpty()) + return; + + const QString newpath = QDir::toNativeSeparators(path); + QListWidgetItem *item = new QListWidgetItem(newpath); + item->setFlags(item->flags() | Qt::ItemIsEditable); + mUI.mListPaths->addItem(item); +} + +void ProjectFileDialog::AddIgnorePath(const QString &path) +{ + if (path.isNull() || path.isEmpty()) + return; + + const QString newpath = QDir::toNativeSeparators(path); + QListWidgetItem *item = new QListWidgetItem(newpath); + item->setFlags(item->flags() | Qt::ItemIsEditable); + mUI.mListIgnoredPaths->addItem(item); } QString ProjectFileDialog::GetRootPath() const { QString root = mUI.mEditProjectRoot->text(); root = root.trimmed(); + root = QDir::fromNativeSeparators(root); return root; } QStringList ProjectFileDialog::GetIncludePaths() const { - QString include = mUI.mEditIncludePaths->text(); - QStringList includes; - if (!include.isEmpty()) + const int count = mUI.mListIncludeDirs->count(); + QStringList includePaths; + for (int i = 0; i < count; i++) { - include = include.trimmed(); - include = QDir::fromNativeSeparators(include); - if (include.indexOf(';') != -1) - includes = include.split(";"); - else - includes.append(include); + QListWidgetItem *item = mUI.mListIncludeDirs->item(i); + includePaths << QDir::fromNativeSeparators(item->text()); } - return includes; + return includePaths; } QStringList ProjectFileDialog::GetDefines() const @@ -81,39 +118,40 @@ QStringList ProjectFileDialog::GetDefines() const QStringList ProjectFileDialog::GetPaths() const { - QString path = mUI.mEditPaths->text(); + const int count = mUI.mListPaths->count(); QStringList paths; - if (!path.isEmpty()) + for (int i = 0; i < count; i++) { - path = path.trimmed(); - path = QDir::fromNativeSeparators(path); - if (path.indexOf(';') != -1) - paths = path.split(";"); - else - paths.append(path); + QListWidgetItem *item = mUI.mListPaths->item(i); + paths << QDir::fromNativeSeparators(item->text()); + } + return paths; +} + +QStringList ProjectFileDialog::GetIgnorePaths() const +{ + const int count = mUI.mListIgnoredPaths->count(); + QStringList paths; + for (int i = 0; i < count; i++) + { + QListWidgetItem *item = mUI.mListIgnoredPaths->item(i); + paths << QDir::fromNativeSeparators(item->text()); } return paths; } void ProjectFileDialog::SetRootPath(const QString &root) { - mUI.mEditProjectRoot->setText(root); + QString newroot = QDir::toNativeSeparators(root); + mUI.mEditProjectRoot->setText(newroot); } void ProjectFileDialog::SetIncludepaths(const QStringList &includes) { - QString includestr; - QString dir; - foreach(dir, includes) + foreach(QString dir, includes) { - includestr += dir; - includestr += ";"; + AddIncludeDir(dir); } - // Remove ; from the end of the string - if (includestr.endsWith(';')) - includestr = includestr.left(includestr.length() - 1); - includestr = QDir::toNativeSeparators(includestr); - mUI.mEditIncludePaths->setText(includestr); } void ProjectFileDialog::SetDefines(const QStringList &defines) @@ -133,21 +171,21 @@ void ProjectFileDialog::SetDefines(const QStringList &defines) void ProjectFileDialog::SetPaths(const QStringList &paths) { - QString pathstr; - QString path; - foreach(path, paths) + foreach(QString path, paths) { - pathstr += path; - pathstr += ";"; + AddPath(path); } - // Remove ; from the end of the string - if (pathstr.endsWith(';')) - pathstr = pathstr.left(pathstr.length() - 1); - pathstr = QDir::toNativeSeparators(pathstr); - mUI.mEditPaths->setText(pathstr); } -void ProjectFileDialog::BrowseIncludes() +void ProjectFileDialog::SetIgnorePaths(const QStringList &paths) +{ + foreach(QString path, paths) + { + AddIgnorePath(path); + } +} + +void ProjectFileDialog::AddIncludeDir() { QString selectedDir = QFileDialog::getExistingDirectory(this, tr("Select include directory"), @@ -155,11 +193,11 @@ void ProjectFileDialog::BrowseIncludes() if (!selectedDir.isEmpty()) { - AppendDirname(mUI.mEditIncludePaths, selectedDir); + AddIncludeDir(selectedDir); } } -void ProjectFileDialog::BrowsePaths() +void ProjectFileDialog::AddPath() { QString selectedDir = QFileDialog::getExistingDirectory(this, tr("Select directory to check"), @@ -167,16 +205,59 @@ void ProjectFileDialog::BrowsePaths() if (!selectedDir.isEmpty()) { - AppendDirname(mUI.mEditPaths, selectedDir); + AddPath(selectedDir); } } -void ProjectFileDialog::AppendDirname(QLineEdit *edit, const QString &dir) +void ProjectFileDialog::RemoveIncludeDir() { - QString wholeText = edit->text(); - wholeText += ";"; - wholeText += dir; - if (!wholeText.endsWith(QDir::separator())) - wholeText += QDir::separator(); - edit->setText(wholeText); + const int row = mUI.mListIncludeDirs->currentRow(); + QListWidgetItem *item = mUI.mListIncludeDirs->takeItem(row); + delete item; +} + +void ProjectFileDialog::EditIncludeDir() +{ + QListWidgetItem *item = mUI.mListIncludeDirs->currentItem(); + mUI.mListIncludeDirs->editItem(item); +} + +void ProjectFileDialog::EditPath() +{ + QListWidgetItem *item = mUI.mListPaths->currentItem(); + mUI.mListPaths->editItem(item); +} + +void ProjectFileDialog::RemovePath() +{ + const int row = mUI.mListPaths->currentRow(); + QListWidgetItem *item = mUI.mListPaths->takeItem(row); + delete item; +} + +void ProjectFileDialog::AddIgnorePath() +{ + QString selectedDir = QFileDialog::getExistingDirectory(this, + tr("Select directory to ignore"), + QString()); + + if (!selectedDir.isEmpty()) + { + if (!selectedDir.endsWith('/')) + selectedDir += '/'; + AddIgnorePath(selectedDir); + } +} + +void ProjectFileDialog::EditIgnorePath() +{ + QListWidgetItem *item = mUI.mListIgnoredPaths->currentItem(); + mUI.mListIgnoredPaths->editItem(item); +} + +void ProjectFileDialog::RemoveIgnorePath() +{ + const int row = mUI.mListIgnoredPaths->currentRow(); + QListWidgetItem *item = mUI.mListIgnoredPaths->takeItem(row); + delete item; } diff --git a/gui/projectfiledialog.h b/gui/projectfiledialog.h index acfd45667..0d904ab38 100644 --- a/gui/projectfiledialog.h +++ b/gui/projectfiledialog.h @@ -66,6 +66,12 @@ public: */ QStringList GetPaths() const; + /** + * @brief Return ignored paths from the dialog control. + * @return List of ignored paths. + */ + QStringList GetIgnorePaths() const; + /** * @brief Set project root path to dialog control. * @param root Project root path to set to dialog control. @@ -90,25 +96,78 @@ public: */ void SetPaths(const QStringList &paths); + /** + * @brief Set ignored paths to dialog control. + * @param paths List of path names to set to dialog control. + */ + void SetIgnorePaths(const QStringList &paths); + protected slots: /** * @brief Browse for include directory. - * Allow user to choose new include directory. + * Allow user to add new include directory to the list. */ - void BrowseIncludes(); + void AddIncludeDir(); + /** - * @brief Browse for checked directory. - * Allow user to choose new checked directory. + * @brief Add new path to check. */ - void BrowsePaths(); + void AddPath(); + + /** + * @brief Remove include directory from the list. + */ + void RemoveIncludeDir(); + + /** + * @brief Edit include directory in the list. + */ + void EditIncludeDir(); + + /** + * @brief Edit path in the list. + */ + void EditPath(); + + /** + * @brief Remove path from the list. + */ + void RemovePath(); + + /** + * @brief Add new path to ignore. + */ + void AddIgnorePath(); + + /** + * @brief Edit ignored path in the list. + */ + void EditIgnorePath(); + + /** + * @brief Remove ignored path from the list. + */ + void RemoveIgnorePath(); protected: + /** - * @brief Append new path to the edit control. - * @param edit Edit control to modify. - * @param dir Path to add. + * @brief Add new indlude directory. + * @param dir Directory to add. */ - void AppendDirname(QLineEdit *edit, const QString &dir); + void AddIncludeDir(const QString &dir); + + /** + * @brief Add new path to check. + * @param path Path to add. + */ + void AddPath(const QString &path); + + /** + * @brief Add new path to ignore list. + * @param path Path to add. + */ + void AddIgnorePath(const QString &path); private: Ui::ProjectFile mUI; diff --git a/gui/resultstree.cpp b/gui/resultstree.cpp index 82ebd62fd..5f2630c53 100644 --- a/gui/resultstree.cpp +++ b/gui/resultstree.cpp @@ -564,6 +564,9 @@ void ResultsTree::StartApplication(QStandardItem *target, int application) return; } + if (application == -1) + application = mApplications->GetDefaultApplication(); + if (target && application >= 0 && application < mApplications->GetApplicationCount() && target->parent()) { // Make sure we are working with the first column @@ -704,7 +707,7 @@ void ResultsTree::Context(int application) void ResultsTree::QuickStartApplication(const QModelIndex &index) { - StartApplication(mModel.itemFromIndex(index), 0); + StartApplication(mModel.itemFromIndex(index)); } void ResultsTree::CopyPath(QStandardItem *target, bool fullPath) diff --git a/gui/resultstree.h b/gui/resultstree.h index 8dbd7e0a7..99448261e 100644 --- a/gui/resultstree.h +++ b/gui/resultstree.h @@ -238,9 +238,10 @@ protected: * @brief Helper function to open an error within target with application* * * @param target Error tree item to open - * @param application Index of the application to open with + * @param application Index of the application to open with. Giving -1 + * (default value) will open the default application. */ - void StartApplication(QStandardItem *target, int application); + void StartApplication(QStandardItem *target, int application = -1); /** * @brief Helper function to copy filename/full path to the clipboard diff --git a/gui/settings.ui b/gui/settings.ui index 8d6fc2e3d..f4366013f 100644 --- a/gui/settings.ui +++ b/gui/settings.ui @@ -7,7 +7,7 @@ 0 0 589 - 313 + 319 @@ -17,37 +17,13 @@ - 0 + 2 General - - - - - - Include paths: - - - mEditIncludePaths - - - - - - - - - - Add... - - - - - @@ -182,41 +158,125 @@ + + + Paths + + + + + + Include paths: + + + + + + + + + QAbstractItemView::SelectRows + + + + + + + + + Add... + + + + + + + Edit + + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Applications - + - - - - - - Add application - - - - - - - Delete application - - - - - - - Modify application - - - - - - - Set as default application - - + + + + + + + + + + Add... + + + + + + + Edit... + + + + + + + Remove + + + + + + + Set as default + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + @@ -284,18 +344,15 @@ tabWidget - mEditIncludePaths - mBtnAddIncludePath mJobs mForce mShowFullPath mShowNoErrorsMessage mShowDebugWarnings mListWidget - mButtonAdd - mButtonDelete - mButtonModify - mButtonDefault + mBtnAddApplication + mBtnEditApplication + mBtnDefaultApplication mSaveAllErrors mSaveFullPath mButtons diff --git a/gui/settingsdialog.cpp b/gui/settingsdialog.cpp index 2301950fa..ca78c1d9d 100644 --- a/gui/settingsdialog.cpp +++ b/gui/settingsdialog.cpp @@ -46,7 +46,6 @@ SettingsDialog::SettingsDialog(QSettings *programSettings, mUI.setupUi(this); mTempApplications->Copy(list); - mUI.mEditIncludePaths->setText(programSettings->value(SETTINGS_GLOBAL_INCLUDE_PATHS).toString()); mUI.mJobs->setText(programSettings->value(SETTINGS_CHECK_THREADS, 1).toString()); mUI.mForce->setCheckState(BoolToCheckState(programSettings->value(SETTINGS_CHECK_FORCE, false).toBool())); mUI.mShowFullPath->setCheckState(BoolToCheckState(programSettings->value(SETTINGS_SHOW_FULL_PATH, false).toBool())); @@ -58,21 +57,25 @@ SettingsDialog::SettingsDialog(QSettings *programSettings, connect(mUI.mButtons, SIGNAL(accepted()), this, SLOT(Ok())); connect(mUI.mButtons, SIGNAL(rejected()), this, SLOT(reject())); - connect(mUI.mButtonAdd, SIGNAL(clicked()), + connect(mUI.mBtnAddApplication, SIGNAL(clicked()), this, SLOT(AddApplication())); - connect(mUI.mButtonDelete, SIGNAL(clicked()), - this, SLOT(DeleteApplication())); - connect(mUI.mButtonModify, SIGNAL(clicked()), - this, SLOT(ModifyApplication())); - connect(mUI.mButtonDefault, SIGNAL(clicked()), + connect(mUI.mBtnRemoveApplication, SIGNAL(clicked()), + this, SLOT(RemoveApplication())); + connect(mUI.mBtnEditApplication, SIGNAL(clicked()), + this, SLOT(EditApplication())); + connect(mUI.mBtnDefaultApplication, SIGNAL(clicked()), this, SLOT(DefaultApplication())); connect(mUI.mListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem *)), - this, SLOT(ModifyApplication())); + this, SLOT(EditApplication())); connect(mUI.mBtnAddIncludePath, SIGNAL(clicked()), this, SLOT(AddIncludePath())); + connect(mUI.mBtnRemoveIncludePath, SIGNAL(clicked()), + this, SLOT(RemoveIncludePath())); + connect(mUI.mBtnEditIncludePath, SIGNAL(clicked()), + this, SLOT(EditIncludePath())); mUI.mListWidget->setSortingEnabled(false); - PopulateListWidget(); + PopulateApplicationList(); const int count = QThread::idealThreadCount(); if (count != -1) @@ -82,6 +85,7 @@ SettingsDialog::SettingsDialog(QSettings *programSettings, LoadSettings(); InitTranslationsList(); + InitIncludepathsList(); } SettingsDialog::~SettingsDialog() @@ -89,6 +93,26 @@ SettingsDialog::~SettingsDialog() SaveSettings(); } +void SettingsDialog::AddIncludePath(const QString &path) +{ + if (path.isNull() || path.isEmpty()) + return; + + QListWidgetItem *item = new QListWidgetItem(path); + item->setFlags(item->flags() | Qt::ItemIsEditable); + mUI.mListIncludePaths->addItem(item); +} + +void SettingsDialog::InitIncludepathsList() +{ + const QString allPaths = mSettings->value(SETTINGS_GLOBAL_INCLUDE_PATHS).toString(); + const QStringList paths = allPaths.split(";", QString::SkipEmptyParts); + foreach(QString path, paths) + { + AddIncludePath(path); + } +} + void SettingsDialog::InitTranslationsList() { const QString current = mTranslator->GetCurrentLanguage(); @@ -151,11 +175,20 @@ void SettingsDialog::SaveSettingValues() SaveCheckboxValue(mUI.mShowNoErrorsMessage, SETTINGS_SHOW_NO_ERRORS); SaveCheckboxValue(mUI.mShowDebugWarnings, SETTINGS_SHOW_DEBUG_WARNINGS); SaveCheckboxValue(mUI.mInlineSuppressions, SETTINGS_INLINE_SUPPRESSIONS); - mSettings->setValue(SETTINGS_GLOBAL_INCLUDE_PATHS, mUI.mEditIncludePaths->text()); QListWidgetItem *currentLang = mUI.mListLanguages->currentItem(); const QString langcode = currentLang->data(LangCodeRole).toString(); mSettings->setValue(SETTINGS_LANGUAGE, langcode); + + const int count = mUI.mListIncludePaths->count(); + QString includePaths; + for (int i = 0; i < count; i++) + { + QListWidgetItem *item = mUI.mListIncludePaths->item(i); + includePaths += item->text(); + includePaths += ";"; + } + mSettings->setValue(SETTINGS_GLOBAL_INCLUDE_PATHS, includePaths); } void SettingsDialog::SaveCheckboxValue(QCheckBox *box, const QString &name) @@ -169,26 +202,31 @@ void SettingsDialog::AddApplication() if (dialog.exec() == QDialog::Accepted) { - mTempApplications->AddApplicationType(dialog.GetName(), dialog.GetPath()); + mTempApplications->AddApplication(dialog.GetName(), dialog.GetPath()); mUI.mListWidget->addItem(dialog.GetName()); } } -void SettingsDialog::DeleteApplication() +void SettingsDialog::RemoveApplication() { - QList selected = mUI.mListWidget->selectedItems(); - QListWidgetItem *item = 0; - - foreach(item, selected) + foreach(QListWidgetItem *item, selected) { - mTempApplications->RemoveApplication(mUI.mListWidget->row(item)); - mUI.mListWidget->clear(); - PopulateListWidget(); + const int removeIndex = mUI.mListWidget->row(item); + const int currentDefault = mTempApplications->GetDefaultApplication(); + mTempApplications->RemoveApplication(removeIndex); + if (removeIndex == currentDefault) + // If default app is removed set default to unknown + mTempApplications->SetDefault(-1); + else if (removeIndex < currentDefault) + // Move default app one up if earlier app was removed + mTempApplications->SetDefault(currentDefault - 1); } + mUI.mListWidget->clear(); + PopulateApplicationList(); } -void SettingsDialog::ModifyApplication() +void SettingsDialog::EditApplication() { QList selected = mUI.mListWidget->selectedItems(); QListWidgetItem *item = 0; @@ -202,7 +240,7 @@ void SettingsDialog::ModifyApplication() if (dialog.exec() == QDialog::Accepted) { - mTempApplications->SetApplicationType(row, dialog.GetName(), dialog.GetPath()); + mTempApplications->SetApplication(row, dialog.GetName(), dialog.GetPath()); item->setText(dialog.GetName()); } } @@ -214,23 +252,36 @@ void SettingsDialog::DefaultApplication() if (selected.size() > 0) { int index = mUI.mListWidget->row(selected[0]); - mTempApplications->MoveFirst(index); + mTempApplications->SetDefault(index); mUI.mListWidget->clear(); - PopulateListWidget(); + PopulateApplicationList(); } } -void SettingsDialog::PopulateListWidget() +void SettingsDialog::PopulateApplicationList() { + const int defapp = mTempApplications->GetDefaultApplication(); for (int i = 0; i < mTempApplications->GetApplicationCount(); i++) { - mUI.mListWidget->addItem(mTempApplications->GetApplicationName(i)); + QString name = mTempApplications->GetApplicationName(i); + if (i == defapp) + { + name += " "; + name += tr("[Default]"); + } + mUI.mListWidget->addItem(name); } - // If list contains items select first item - if (mTempApplications->GetApplicationCount()) - { + // Select default application, or if there is no default app then the + // first item. + if (defapp == -1) mUI.mListWidget->setCurrentRow(0); + else + { + if (mTempApplications->GetApplicationCount() > defapp) + mUI.mListWidget->setCurrentRow(defapp); + else + mUI.mListWidget->setCurrentRow(0); } } @@ -268,10 +319,19 @@ void SettingsDialog::AddIncludePath() if (!selectedDir.isEmpty()) { - QString text = mUI.mEditIncludePaths->text(); - if (!text.isEmpty()) - text += ';'; - text += selectedDir; - mUI.mEditIncludePaths->setText(text); + AddIncludePath(selectedDir); } } + +void SettingsDialog::RemoveIncludePath() +{ + const int row = mUI.mListIncludePaths->currentRow(); + QListWidgetItem *item = mUI.mListIncludePaths->takeItem(row); + delete item; +} + +void SettingsDialog::EditIncludePath() +{ + QListWidgetItem *item = mUI.mListIncludePaths->currentItem(); + mUI.mListIncludePaths->editItem(item); +} diff --git a/gui/settingsdialog.h b/gui/settingsdialog.h index d2a9e11ad..22d3c3253 100644 --- a/gui/settingsdialog.h +++ b/gui/settingsdialog.h @@ -98,13 +98,13 @@ protected slots: * @brief Slot for deleting an application from the list * */ - void DeleteApplication(); + void RemoveApplication(); /** * @brief Slot for modifying an application in the list * */ - void ModifyApplication(); + void EditApplication(); /** * @brief Slot for making the selected application as the default (first) @@ -118,19 +118,38 @@ protected slots: */ void AddIncludePath(); + /** + * @brief Slot for removing an include path. + * + */ + void RemoveIncludePath(); + + /** + * @brief Slot for editing an include path. + * + */ + void EditIncludePath(); + protected: + /** + * @brief Add new include path to the list. + * @param path Path to add. + * + */ + void AddIncludePath(const QString &path); + /** * @brief Clear all applications from the list and re insert them from mTempApplications * */ - void PopulateListWidget(); + void PopulateApplicationList(); /** - * @brief Load saved values - * Loads dialog size and column widths. - * - */ + * @brief Load saved values + * Loads dialog size and column widths. + * + */ void SaveSettings(); /** @@ -165,6 +184,11 @@ protected: */ bool CheckStateToBool(Qt::CheckState state) const; + /** + * @brief Populate the include paths-list. + */ + void InitIncludepathsList(); + /** * @brief Populate the translations list. */ diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index b13143d80..569f4ed9d 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -695,6 +695,8 @@ void CheckClass::unusedPrivateFunctionError(const Token *tok, const std::string void CheckClass::noMemset() { + createSymbolDatabase(); + // Locate all 'memset' tokens.. for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { @@ -712,6 +714,13 @@ void CheckClass::noMemset() type = tok->strAt(10); else if (Token::Match(tok, "%type% ( %var% , %var% , sizeof ( %type% ) )")) type = tok->strAt(8); + else if (Token::Match(tok, "memset ( & %var% , %num% , sizeof ( %var% ) )")) + { + unsigned int varid = tok->tokAt(3)->varId(); + const Variable *var = symbolDatabase->getVariableFromVarId(varid); + if (var && var->typeStartToken() == var->typeEndToken()) + type = var->typeStartToken()->str(); + } // No type defined => The tokens didn't match if (type.empty()) @@ -719,7 +728,14 @@ void CheckClass::noMemset() // Warn if type is a class or struct that contains any std::* variables const std::string pattern2(std::string("struct|class ") + type + " {"); - for (const Token *tstruct = Token::findmatch(_tokenizer->tokens(), pattern2.c_str()); tstruct; tstruct = tstruct->next()) + const Token *tstruct = Token::findmatch(_tokenizer->tokens(), pattern2.c_str()); + + if (!tstruct) + continue; + + const std::string &typeName = tstruct->str(); + + for (; tstruct; tstruct = tstruct->next()) { if (tstruct->str() == "}") break; @@ -739,7 +755,7 @@ void CheckClass::noMemset() tstruct->str().find(":") != std::string::npos) { if (Token::Match(tstruct->next(), "std :: %type% %var% ;")) - memsetStructError(tok, tok->str(), tstruct->strAt(3)); + memsetError(tok, tok->str(), tstruct->strAt(3), typeName); else if (Token::Match(tstruct->next(), "std :: %type% <")) { @@ -767,21 +783,16 @@ void CheckClass::noMemset() // found error => report if (Token::Match(tstruct, "> %var% ;")) - memsetStructError(tok, tok->str(), typestr); + memsetError(tok, tok->str(), typestr, typeName); } } } } } -void CheckClass::memsetClassError(const Token *tok, const std::string &memfunc) +void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type) { - reportError(tok, Severity::error, "memsetClass", "Using '" + memfunc + "' on class"); -} - -void CheckClass::memsetStructError(const Token *tok, const std::string &memfunc, const std::string &classname) -{ - reportError(tok, Severity::error, "memsetStruct", "Using '" + memfunc + "' on struct that contains a 'std::" + classname + "'"); + reportError(tok, Severity::error, "memsetClass", "Using '" + memfunc + "' on " + type + " that contains a 'std::" + classname + "'"); } //--------------------------------------------------------------------------- diff --git a/lib/checkclass.h b/lib/checkclass.h index cc550c36b..2dd238f83 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -117,8 +117,7 @@ private: void uninitVarError(const Token *tok, const std::string &classname, const std::string &varname); void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname); void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname); - void memsetClassError(const Token *tok, const std::string &memfunc); - void memsetStructError(const Token *tok, const std::string &memfunc, const std::string &classname); + void memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type); void operatorEqReturnError(const Token *tok); void virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived); void thisSubtractionError(const Token *tok); @@ -134,8 +133,7 @@ private: c.uninitVarError(0, "classname", "varname"); c.operatorEqVarError(0, "classname", ""); c.unusedPrivateFunctionError(0, "classname", "funcname"); - c.memsetClassError(0, "memfunc"); - c.memsetStructError(0, "memfunc", "classname"); + c.memsetError(0, "memfunc", "classname", "class"); c.operatorEqReturnError(0); //c.virtualDestructorError(0, "Base", "Derived"); c.thisSubtractionError(0); diff --git a/lib/checkobsoletefunctions.h b/lib/checkobsoletefunctions.h index 706803aa8..3c56516e2 100644 --- a/lib/checkobsoletefunctions.h +++ b/lib/checkobsoletefunctions.h @@ -75,7 +75,7 @@ private: "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.")); _obsoleteFunctions.push_back(std::make_pair("bcmp","Found obsolete function 'bcmp'. It is recommended that new applications use the 'memcmp' function")); - _obsoleteFunctions.push_back(std::make_pair("bcopy","Found obsolete function 'bcopy'. It is recommended that new applications use the 'memmove' function")); + _obsoleteFunctions.push_back(std::make_pair("bcopy","Found obsolete function 'bcopy'. It is recommended that new applications use the 'memmove' or 'memcpy' functions")); _obsoleteFunctions.push_back(std::make_pair("bzero","Found obsolete function 'bzero'. It is recommended that new applications use the 'memset' function")); _obsoleteFunctions.push_back(std::make_pair("ecvt","Found obsolete function 'ecvt'. It is recommended that new applications use the 'sprintf' function")); diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 07132a2d0..8588e3666 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -608,6 +608,35 @@ void CheckOther::invalidScanf() } } +//--------------------------------------------------------------------------- +// if (!x==3) <- Probably meant to be "x!=3" +//--------------------------------------------------------------------------- +void CheckOther::checkComparisonOfBoolWithInt() +{ + if (!_settings->_checkCodingStyle) + return; + + for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) + { + if (Token::Match(tok, "( ! %var% ==|!= %num% )")) + { + const Token *numTok = tok->tokAt(4); + if (numTok && numTok->str() != "0") + { + comparisonOfBoolWithIntError(numTok, tok->strAt(2)); + } + } + else if (Token::Match(tok, "( %num% ==|!= ! %var% )")) + { + const Token *numTok = tok->tokAt(1); + if (numTok && numTok->str() != "0") + { + comparisonOfBoolWithIntError(numTok, tok->strAt(4)); + } + } + } +} + void CheckOther::sizeofForArrayParameterError(const Token *tok) { reportError(tok, Severity::error, @@ -3016,3 +3045,10 @@ void CheckOther::incorrectStringCompareError(const Token *tok, const std::string { reportError(tok, Severity::warning, "incorrectStringCompare", "String literal " + string + " doesn't match length argument for " + func + "(" + len + ")."); } + +void CheckOther::comparisonOfBoolWithIntError(const Token *tok, const std::string &varname) +{ + reportError(tok, Severity::warning, "comparisonOfBoolWithInt", + "Comparison of a boolean with a non-zero integer\n" + "The expression \"!" + varname + "\" is of type 'bool' but is compared against a non-zero 'int'."); +} diff --git a/lib/checkother.h b/lib/checkother.h index cb0266cc1..d43c4c413 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -89,6 +89,7 @@ public: checkOther.checkMemsetZeroBytes(); checkOther.checkIncorrectStringCompare(); checkOther.checkIncrementBoolean(); + checkOther.checkComparisonOfBoolWithInt(); } /** @brief Clarify calculation for ".. a * b ? .." */ @@ -188,6 +189,9 @@ public: /** @brief %Check for using postfix increment on bool */ void checkIncrementBoolean(); + /** @brief %Check for suspicious comparison of a bool and a non-zero (and non-one) value (e.g. "if (!x==4)") */ + void checkComparisonOfBoolWithInt(); + // Error messages.. void cstyleCastError(const Token *tok); void dangerousUsageStrtolError(const Token *tok); @@ -214,6 +218,7 @@ public: void sizeofForArrayParameterError(const Token *tok); void incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string, const std::string &len); void incrementBooleanError(const Token *tok); + void comparisonOfBoolWithIntError(const Token *tok, const std::string &varname); void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) { @@ -255,6 +260,7 @@ public: c.clarifyCalculationError(0); c.incorrectStringCompareError(0, "substr", "\"Hello World\"", "12"); c.incrementBooleanError(0); + c.comparisonOfBoolWithIntError(0, "varname"); } std::string myName() const @@ -296,6 +302,7 @@ public: "* exception caught by value instead of by reference\n" "* Clarify calculation with parantheses\n" "* using increment on boolean\n" + "* comparison of a boolean with a non-zero integer\n" // optimisations "* optimisation: detect post increment/decrement\n"; diff --git a/lib/checkpostfixoperator.cpp b/lib/checkpostfixoperator.cpp index 5c0578c40..7294e688d 100644 --- a/lib/checkpostfixoperator.cpp +++ b/lib/checkpostfixoperator.cpp @@ -74,10 +74,10 @@ void CheckPostfixOperator::postfixOperator() if (result && tok->previous()->varId()) { const Token *decltok = Token::findmatch(_tokenizer->tokens(), "%varid%", tok->previous()->varId()); - if (!Token::Match(decltok->tokAt(-1), "%type%")) + if (decltok == NULL || !Token::Match(decltok->tokAt(-1), "%type%")) continue; - if (decltok && Token::Match(decltok->previous(), "iterator|const_iterator|reverse_iterator|const_reverse_iterator")) + if (Token::Match(decltok->previous(), "iterator|const_iterator|reverse_iterator|const_reverse_iterator")) { // the variable is an iterator postfixOperatorError(tok); diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index c1f5f28e6..3235c6443 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -603,7 +603,10 @@ private: std::list var; CheckNullPointer::parseFunctionCall(tok, var, 1); for (std::list::const_iterator it = var.begin(); it != var.end(); ++it) + { use_array(checks, *it); + use_dead_pointer(checks, *it); + } // Using uninitialized pointer is bad if using null pointer is bad std::list var2; diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 2f5c33795..17963f673 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -178,6 +178,10 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename, // Remove all comments.. result = removeComments(result, filename, settings); + // Remove '#if 0' blocks + if (result.find("#if 0\n") != std::string::npos) + result = removeIf0(result); + // ------------------------------------------------------------------------------------------ // // Clean up all preprocessor statements @@ -547,6 +551,37 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri return code.str(); } +std::string Preprocessor::removeIf0(const std::string &code) +{ + std::ostringstream ret; + std::istringstream istr(code); + std::string line; + while (std::getline(istr,line)) + { + if (line != "#if 0") + ret << line << "\n"; + else + { + // replace '#if 0' with empty line + ret << "\n"; + + // goto the end of the '#if 0' block + unsigned int level = 1; + while (level > 0 && std::getline(istr,line)) + { + if (line.compare(0,3,"#if") == 0) + ++level; + else if (line == "#endif") + --level; + + // replace code within '#if 0' block with empty lines + ret << "\n"; + } + } + } + return ret.str(); +} + std::string Preprocessor::removeParantheses(const std::string &str) { @@ -927,7 +962,18 @@ std::list Preprocessor::getcfgs(const std::string &filedata, const if (line.compare(0, 8, "#define ") == 0) { - if (line.find(" ", 8) == std::string::npos) + bool valid = true; + for (std::string::size_type pos = 8; pos < line.size() && line[pos] != ' '; ++pos) + { + char ch = line[pos]; + if (ch=='_' || (ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (pos>8 && ch>='0' && ch<='9')) + continue; + valid = false; + break; + } + if (!valid) + line.clear(); + else if (line.find(" ", 8) == std::string::npos) defines.insert(line.substr(8)); else { @@ -1278,8 +1324,12 @@ void Preprocessor::simplifyCondition(const std::map &v if (Token::Match(tokenizer.tokens(), "( %var% )")) { - if (variables.find(tokenizer.tokens()->strAt(1)) != variables.end()) - condition = "1"; + std::map::const_iterator var = variables.find(tokenizer.tokens()->strAt(1)); + if (var != variables.end()) + { + const std::string &value = (*var).second; + condition = (value == "0") ? "0" : "1"; + } else if (match) condition = "0"; return; diff --git a/lib/preprocessor.h b/lib/preprocessor.h index 82f5da2bd..e871f8562 100644 --- a/lib/preprocessor.h +++ b/lib/preprocessor.h @@ -144,6 +144,13 @@ protected: */ std::string removeComments(const std::string &str, const std::string &filename, Settings *settings); + /** + * Cleanup 'if 0' from the code + * @param str Code processed by read(). + * @return code without 'if 0' + */ + static std::string removeIf0(const std::string &code); + /** * Remove redundant parentheses from preprocessor commands. This should only be called from read(). * @param str Code processed by read(). diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index a600a1a3a..03ccd8b00 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -399,6 +399,68 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti } } } + else if (scope->type == Scope::eFunction || scope->isLocal()) + { + if (Token::simpleMatch(tok, "if (") && + Token::simpleMatch(tok->next()->link(), ") {")) + { + scope = new Scope(this, tok, scope, Scope::eIf, tok->next()->link()->next()); + tok = tok->next()->link()->next(); + scopeList.push_back(scope); + } + else if (Token::simpleMatch(tok, "else {")) + { + scope = new Scope(this, tok, scope, Scope::eElse, tok->next()); + tok = tok->next(); + scopeList.push_back(scope); + } + else if (Token::simpleMatch(tok, "else if (") && + Token::simpleMatch(tok->next()->next()->link(), ") {")) + { + scope = new Scope(this, tok, scope, Scope::eElseIf, tok->next()->next()->link()->next()); + tok = tok->next()->next()->link()->next(); + scopeList.push_back(scope); + } + else if (Token::simpleMatch(tok, "for (") && + Token::simpleMatch(tok->next()->link(), ") {")) + { + scope = new Scope(this, tok, scope, Scope::eFor, tok->next()->link()->next()); + tok = tok->next()->link()->next(); + scopeList.push_back(scope); + } + else if (Token::simpleMatch(tok, "while (") && + Token::simpleMatch(tok->next()->link(), ") {")) + { + scope = new Scope(this, tok, scope, Scope::eWhile, tok->next()->link()->next()); + tok = tok->next()->link()->next(); + scopeList.push_back(scope); + } + else if (Token::simpleMatch(tok, "do {")) + { + scope = new Scope(this, tok, scope, Scope::eDo, tok->next()); + tok = tok->next(); + scopeList.push_back(scope); + } + else if (Token::simpleMatch(tok, "switch (") && + Token::simpleMatch(tok->next()->link(), ") {")) + { + scope = new Scope(this, tok, scope, Scope::eSwitch, tok->next()->link()->next()); + tok = tok->next()->link()->next(); + scopeList.push_back(scope); + } + else if (tok->str() == "{") + { + if (!Token::Match(tok->previous(), "=|,|{")) + { + scope = new Scope(this, tok, scope, Scope::eUnconditional, tok); + scopeList.push_back(scope); + } + else + { + tok = tok->link(); + } + } + } } } @@ -448,11 +510,21 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti { scope = *it; - // skip functions - if (scope->type != Scope::eFunction) + // find variables + scope->getVariableList(); + } + + // fill in function arguments + for (it = scopeList.begin(); it != scopeList.end(); ++it) + { + scope = *it; + + std::list::iterator func; + + for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { - // find variables - scope->getVariableList(); + // add arguments + func->addArguments(this, scope); } } @@ -569,6 +641,46 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti } } } + + // create variable symbol table + _variableList.resize(_tokenizer->varIdCount() + 1); + fill_n(_variableList.begin(), _variableList.size(), (const Variable*)NULL); + + // check all scopes for variables + for (it = scopeList.begin(); it != scopeList.end(); ++it) + { + scope = *it; + + // add all variables + std::list::const_iterator var; + for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var) + { + unsigned int varId = var->varId(); + if (varId) + _variableList[varId] = &*var; + } + + // add all function paramaters + std::list::const_iterator func; + for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) + { + // ignore function without implementations + if (!func->hasBody) + continue; + + std::list::const_iterator arg; + for (arg = func->argumentList.begin(); arg != func->argumentList.end(); ++arg) + { + // check for named parameters + if (arg->nameToken() && arg->varId()) + { + unsigned int varId = arg->varId(); + if (varId) + _variableList[varId] = &*arg; + } + } + } + } } SymbolDatabase::~SymbolDatabase() @@ -1002,8 +1114,75 @@ unsigned int Function::initializedArgCount() const return count; } +void Function::addArguments(const SymbolDatabase *symbolDatabase, const Scope *scope) +{ + // check for non-empty argument list "( ... )" + if (arg->link() != arg->next()) + { + unsigned int count = 0; + const Token *startTok; + const Token *endTok; + const Token *nameTok; + bool isConstVar; + const Token *tok = arg->next(); + for (;;) + { + startTok = tok; + endTok = NULL; + nameTok = NULL; + isConstVar = bool(tok->str() == "const"); + + while (tok->str() != "," && tok->str() != ")") + { + if (tok->varId() != 0) + { + nameTok = tok; + endTok = tok->previous(); + } + tok = tok->next(); + } + + // check for argument with no name + if (!endTok) + endTok = tok->previous(); + + const Token *typeTok = startTok; + if (isConstVar) + typeTok = typeTok->next(); + + const Scope *argType = NULL; + if (!typeTok->isStandardType()) + argType = symbolDatabase->findVariableType(scope, typeTok); + + bool isClassVar = startTok == endTok && !startTok->isStandardType(); + + argumentList.push_back(Variable(nameTok, startTok, endTok, count++, Argument, false, false, isConstVar, isClassVar, argType, scope, false)); + + if (tok->str() == ")") + break; + + tok = tok->next(); + } + } +} + //--------------------------------------------------------------------------- +Scope::Scope(SymbolDatabase *check_, const Token *classDef_, Scope *nestedIn_, ScopeType type_, const Token *start_) : + check(check_), + type(type_), + classDef(classDef_), + classStart(start_), + classEnd(start_->link()), + nestedIn(nestedIn_), + access(Public), + numConstructors(0), + needInitialization(Scope::Unknown), + functionOf(NULL) +{ + nestedIn->nestedList.push_back(this); +} + Scope::Scope(SymbolDatabase *check_, const Token *classDef_, Scope *nestedIn_) : check(check_), classDef(classDef_), @@ -1071,10 +1250,31 @@ Scope::hasDefaultConstructor() const return false; } +AccessControl Scope::defaultAccess() const +{ + switch (type) + { + case eGlobal: + return Global; + case eClass: + return Private; + case eStruct: + return Public; + case eUnion: + return Public; + case eNamespace: + return Namespace; + default: + return Local; + } + + return Public; +} + // Get variable list.. void Scope::getVariableList() { - AccessControl varaccess = type == eClass ? Private : Public; + AccessControl varaccess = defaultAccess(); const Token *start; if (classStart) @@ -1163,8 +1363,16 @@ void Scope::getVariableList() else if (tok->str() == "__property") continue; + // skip return and delete + else if (Token::Match(tok, "return|delete")) + { + while (tok->next()->str() != ";") + tok = tok->next(); + continue; + } + // Search for start of statement.. - else if (!tok->previous() || !Token::Match(tok->previous(), ";|{|}|public:|protected:|private:")) + else if (tok->previous() && !Token::Match(tok->previous(), ";|{|}|public:|protected:|private:")) continue; else if (Token::Match(tok, ";|{|}")) continue; @@ -1210,7 +1418,9 @@ void Scope::getVariableList() tok = tok->next(); } - if (isVariableDeclaration(tok, vartok, typetok)) + bool isArray = false; + + if (isVariableDeclaration(tok, vartok, typetok, isArray)) { isClass = (!typetok->isStandardType() && vartok->previous()->str() != "*"); tok = vartok->next(); @@ -1219,7 +1429,7 @@ void Scope::getVariableList() // If the vartok was set in the if-blocks above, create a entry for this variable.. if (vartok && vartok->str() != "operator") { - if (vartok->varId() == 0 && check->_settings->debugwarnings) + if (vartok->varId() == 0 && !vartok->isBoolean() && check->_settings->debugwarnings) { std::list locationList; ErrorLogger::ErrorMessage::FileLocation loc; @@ -1242,7 +1452,7 @@ void Scope::getVariableList() if (typetok) scope = check->findVariableType(this, typetok); - addVariable(vartok, typestart, varaccess, isMutable, isStatic, isConst, isClass, scope); + addVariable(vartok, typestart, vartok->previous(), varaccess, isMutable, isStatic, isConst, isClass, scope, this, isArray); } } } @@ -1275,7 +1485,7 @@ const Token* skipPointers(const Token* tok) return ret; } -bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const +bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray) const { const Token* localTypeTok = skipScopeIdentifiers(tok); const Token* localVarTok = NULL; @@ -1288,7 +1498,7 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const { localVarTok = skipPointers(closeTok->next()); - if (Token::Match(localVarTok, ":: %type% %var% ;")) + if (Token::Match(localVarTok, ":: %type% %var% ;|=")) { localTypeTok = localVarTok->next(); localVarTok = localVarTok->tokAt(2); @@ -1300,10 +1510,17 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const localVarTok = skipPointers(localTypeTok->next()); } - if (isSimpleVariable(localVarTok) || isArrayVariable(localVarTok)) + if (isSimpleVariable(localVarTok)) { vartok = localVarTok; typetok = localTypeTok; + isArray = false; + } + else if (isArrayVariable(localVarTok)) + { + vartok = localVarTok; + typetok = localTypeTok; + isArray = true; } return NULL != vartok; @@ -1311,7 +1528,7 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const bool Scope::isSimpleVariable(const Token* tok) const { - return Token::Match(tok, "%var% ;"); + return Token::Match(tok, "%var% ;|="); } bool Scope::isArrayVariable(const Token* tok) const @@ -1325,7 +1542,7 @@ bool Scope::findClosingBracket(const Token* tok, const Token*& close) const if (NULL != tok && tok->str() == "<") { unsigned int depth = 0; - for (close = tok; (close != NULL) && (close->str() != ";"); close = close->next()) + for (close = tok; (close != NULL) && (close->str() != ";") && (close->str() != "="); close = close->next()) { if (close->str() == "<") { diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index b21417c51..3e11805b3 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -38,7 +38,7 @@ class SymbolDatabase; /** * @brief Access control enumerations. */ -enum AccessControl { Public, Protected, Private }; +enum AccessControl { Public, Protected, Private, Global, Namespace, Argument, Local }; /** @brief Information about a member variable. */ class Variable @@ -49,7 +49,8 @@ class Variable fIsMutable = (1 << 0), /** @brief mutable variable */ fIsStatic = (1 << 1), /** @brief static variable */ fIsConst = (1 << 2), /** @brief const variable */ - fIsClass = (1 << 3) /** @brief user defined type */ + fIsClass = (1 << 3), /** @brief user defined type */ + fIsArray = (1 << 4) /** @brief array variable */ }; /** @@ -73,20 +74,24 @@ class Variable } public: - Variable(const Token *name_, const Token *start_, std::size_t index_, - AccessControl access_, bool mutable_, bool static_, bool const_, - bool class_, const Scope *type_) + Variable(const Token *name_, const Token *start_, const Token *end_, + std::size_t index_, AccessControl access_, bool mutable_, + bool static_, bool const_, bool class_, const Scope *type_, + const Scope *scope_, bool array_) : _name(name_), _start(start_), + _end(end_), _index(index_), _access(access_), _flags(0), - _type(type_) + _type(type_), + _scope(scope_) { setFlag(fIsMutable, mutable_); setFlag(fIsStatic, static_); setFlag(fIsConst, const_); setFlag(fIsClass, class_); + setFlag(fIsArray, array_); } /** @@ -107,13 +112,28 @@ public: return _start; } + /** + * Get type end token. + * @return type end token + */ + const Token *typeEndToken() const + { + return _end; + } + /** * Get name string. * @return name string */ const std::string &name() const { - return _name->str(); + static const std::string noname; + + // name may not exist for function arguments + if (_name) + return _name->str(); + + return noname; } /** @@ -122,7 +142,11 @@ public: */ unsigned int varId() const { - return _name->varId(); + // name may not exist for function arguments + if (_name) + return _name->varId(); + + return 0; } /** @@ -161,6 +185,42 @@ public: return _access == Private; } + /** + * Is variable global. + * @return true if global, false if not + */ + bool isGlobal() const + { + return _access == Global; + } + + /** + * Is variable in a namespace. + * @return true if in a namespace, false if not + */ + bool isNamespace() const + { + return _access == Namespace; + } + + /** + * Is variable a function argument. + * @return true if a function argument, false if not + */ + bool isArgument() const + { + return _access == Argument; + } + + /** + * Is variable local. + * @return true if local, false if not + */ + bool isLocal() const + { + return _access == Local; + } + /** * Is variable mutable. * @return true if mutable, false if not @@ -197,6 +257,15 @@ public: return getFlag(fIsClass); } + /** + * Is variable an array. + * @return true if array, false if not + */ + bool isArray() const + { + return getFlag(fIsArray); + } + /** * Get Scope pointer of known type. * @return pointer to type if known, NULL if not known @@ -206,6 +275,15 @@ public: return _type; } + /** + * Get Scope pointer of enclosing scope. + * @return pointer to enclosing scope + */ + const Scope *scope() const + { + return _scope; + } + private: /** @brief variable name token */ const Token *_name; @@ -213,6 +291,9 @@ private: /** @brief variable type start token */ const Token *_start; + /** @brief variable type end token */ + const Token *_end; + /** @brief order declared */ std::size_t _index; @@ -224,6 +305,9 @@ private: /** @brief pointer to user defined type info (for known types) */ const Scope *_type; + + /** @brief pointer to scope this variable is in */ + const Scope *_scope; }; class Function @@ -254,6 +338,7 @@ public: unsigned int argCount() const; unsigned int initializedArgCount() const; + void addArguments(const SymbolDatabase *symbolDatabase, const Scope *scope); const Token *tokenDef; // function name token in class definition const Token *argDef; // function argument start '(' in class definition @@ -272,6 +357,7 @@ public: bool isOperator; // is operator bool retFuncPtr; // returns function pointer Type type; // constructor, destructor, ... + std::list argumentList; // argument list }; class Scope @@ -293,10 +379,11 @@ public: Scope *scope; }; - enum ScopeType { eGlobal, eClass, eStruct, eUnion, eNamespace, eFunction }; + enum ScopeType { eGlobal, eClass, eStruct, eUnion, eNamespace, eFunction, eIf, eElse, eElseIf, eFor, eWhile, eDo, eSwitch, eUnconditional }; enum NeedInitialization { Unknown, True, False }; Scope(SymbolDatabase *check_, const Token *classDef_, Scope *nestedIn_); + Scope(SymbolDatabase *check_, const Token *classDef_, Scope *nestedIn_, ScopeType type_, const Token *start_); SymbolDatabase *check; ScopeType type; @@ -313,13 +400,19 @@ public: AccessControl access; unsigned int numConstructors; NeedInitialization needInitialization; - Scope * functionOf; // class/struct this function belongs to + Scope *functionOf; // class/struct this function belongs to bool isClassOrStruct() const { return (type == eClass || type == eStruct); } + bool isLocal() const + { + return (type == eIf || type == eElse || type == eElseIf || + type == eFor || type == eWhile || type == eDo || + type == eSwitch || type == eUnconditional); + } /** * @brief find if name is in nested list * @param name name of nested scope @@ -332,9 +425,14 @@ public: */ Scope * findInNestedListRecursive(const std::string & name); - void addVariable(const Token *token_, const Token *start_, AccessControl access_, bool mutable_, bool static_, bool const_, bool class_, const Scope *type_) + void addVariable(const Token *token_, const Token *start_, + const Token *end_, AccessControl access_, bool mutable_, + bool static_, bool const_, bool class_, const Scope *type_, + const Scope *scope_, bool array_) { - varlist.push_back(Variable(token_, start_, varlist.size(), access_, mutable_, static_, const_, class_, type_)); + varlist.push_back(Variable(token_, start_, end_, varlist.size(), + access_, mutable_, static_, const_, class_, + type_, scope_, array_)); } /** @brief initialize varlist */ @@ -352,15 +450,18 @@ public: bool hasDefaultConstructor() const; + AccessControl defaultAccess() const; + private: /** * @brief helper function for getVariableList() * @param tok pointer to token to check * @param vartok populated with pointer to the variable token, if found * @param typetok populated with pointer to the type token, if found + * @param isArray reference to variable to set if array is found * @return true if tok points to a variable declaration, false otherwise */ - bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const; + bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok, bool &isArray) const; bool isSimpleVariable(const Token* tok) const; bool isArrayVariable(const Token* tok) const; bool findClosingBracket(const Token* tok, const Token*& close) const; @@ -394,6 +495,11 @@ public: return bool(classAndStructTypes.find(type) != classAndStructTypes.end()); } + const Variable *getVariableFromVarId(unsigned int varId) const + { + return _variableList[varId]; + } + private: // Needed by Borland C++: @@ -410,6 +516,9 @@ private: const Tokenizer *_tokenizer; const Settings *_settings; ErrorLogger *_errorLogger; + + /** variable symbol table */ + std::vector _variableList; }; #endif diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 54639fc35..7460faf3b 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -58,6 +58,9 @@ Tokenizer::Tokenizer() // symbol database _symbolDatabase = NULL; + + // variable count + _varId = 0; } Tokenizer::Tokenizer(const Settings *settings, ErrorLogger *errorLogger) @@ -75,6 +78,9 @@ Tokenizer::Tokenizer(const Settings *settings, ErrorLogger *errorLogger) // symbol database _symbolDatabase = NULL; + + // variable count + _varId = 0; } Tokenizer::~Tokenizer() @@ -886,6 +892,9 @@ static Token *processFunc(Token *tok2, bool inOperator) tok2 = tok2->tokAt(4)->link()->next(); else if (Token::Match(tok2->next(), "* ( * %type% (")) tok2 = tok2->tokAt(5)->link()->next(); + else if (Token::Match(tok2->next(), "* [") && + Token::simpleMatch(tok2->tokAt(2)->link(), "] ;")) + tok2 = tok2->next(); else { if (tok2->next()->str() == "(") @@ -3268,7 +3277,7 @@ void Tokenizer::setVarId() tok->varId(0); // Set variable ids.. - unsigned int _varId = 0; + _varId = 0; for (Token *tok = _tokens; tok; tok = tok->next()) { if (tok != _tokens && !Token::Match(tok, "[;{}(,] %type%")) @@ -3915,10 +3924,14 @@ void Tokenizer::simplifySizeof() --parlevel; if (Token::Match(tempToken, "%var%")) { - while (tempToken->next()->str() == "[") + while (tempToken && tempToken->next() && tempToken->next()->str() == "[") { tempToken = tempToken->next()->link(); } + if (!tempToken || !tempToken->next()) + { + break; + } if (tempToken->next()->str() == ".") { @@ -4656,6 +4669,8 @@ void Tokenizer::simplifyIfAddBraces() break; } tempToken = tempToken->link(); + if (!tempToken || !tempToken->next()) + break; if (tempToken->next()->isName() && tempToken->next()->str() != "else") break; continue; @@ -6341,6 +6356,22 @@ bool Tokenizer::simplifyKnownVariables() ret |= simplifyKnownVariablesSimplify(&tok2, tok3, varid, structname, value, valueVarId, valueIsPointer, valueToken, indentlevel); } + + else if (Token::Match(tok2, "strcpy ( %var% , %str% ) ;")) + { + const unsigned int varid(tok2->tokAt(2)->varId()); + if (varid == 0) + continue; + const std::string structname(""); + const Token * const valueToken = tok2->tokAt(4); + std::string value(valueToken->str()); + const unsigned int valueVarId(0); + const bool valueIsPointer(false); + Token *tok3 = tok2; + for (int i = 0; i < 6; ++i) + tok3 = tok3->next(); + ret |= simplifyKnownVariablesSimplify(&tok2, tok3, varid, structname, value, valueVarId, valueIsPointer, valueToken, indentlevel); + } } if (tok2) @@ -9375,7 +9406,8 @@ void Tokenizer::removeUnnecessaryQualification() classInfo.pop(); else if (tok->str() == classInfo.top().className && Token::Match(tok, "%type% :: %type% (") && - Token::Match(tok->tokAt(3)->link(), ") const| {|;")) + Token::Match(tok->tokAt(3)->link(), ") const| {|;") && + tok->previous()->str() != ":") { std::list locationList; ErrorLogger::ErrorMessage::FileLocation loc; diff --git a/lib/tokenize.h b/lib/tokenize.h index d5faa0812..a9b5c556d 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -650,6 +650,15 @@ public: Token *deleteInvalidTypedef(Token *typeDef); + /** + * Get variable count. + * @return number of variables + */ + unsigned int varIdCount() const + { + return _varId; + } + private: /** Disable copy constructor, no implementation */ Tokenizer(const Tokenizer &); @@ -684,6 +693,9 @@ private: /** Symbol database that all checks etc can use */ mutable SymbolDatabase *_symbolDatabase; + + /** variable count */ + unsigned int _varId; }; /// @} diff --git a/man/cppcheck.1.xml b/man/cppcheck.1.xml index 9332a09ae..d0aae70a0 100644 --- a/man/cppcheck.1.xml +++ b/man/cppcheck.1.xml @@ -120,6 +120,7 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/ + @@ -303,12 +304,19 @@ Directory name is matched to all parts of the path. Deprecated, use --enable=style + + + + Suppress a specific warning. The format of <spec> is: [error id]:[filename]:[line]. + The [filename] and [line] are optional. + [filename] may contain the wildcard characters * or ?. + + - Suppress warnings listed in the file. Filename and line are optional. The format of the single line in file is: [error id]:[filename]:[line]. - You can use --template or --xml to see the error id. - The filename may contain the wildcard characters * or ?. + Suppress warnings listed in the file. + Each suppression is in the format of <spec> above. diff --git a/man/manual.docbook b/man/manual.docbook index 07285513a..c3c16bb61 100644 --- a/man/manual.docbook +++ b/man/manual.docbook @@ -374,7 +374,8 @@ gui/test.cpp,16,error,mismatchAllocDealloc,Mismatching allocation and deallocati Suppressions If you want to filter out certain errors you can suppress these. - First you need to create a suppressions file. The format is: + The --suppress= command line option is used to specify + suppressions on the command line. The format is one of: [error id]:[filename]:[line] [error id]:[filename2] @@ -389,6 +390,11 @@ gui/test.cpp,16,error,mismatchAllocDealloc,Mismatching allocation and deallocati * or ?, which match any sequence of characters or any single character respectively. + cppcheck --suppress=memleak:file1.cpp src/ + + If you have more than a couple of suppressions, create a suppressions + file with one line per suppression as above. + Here is an example: memleak:file1.cpp diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index ecc3c7554..f3a74a4b6 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -850,27 +850,17 @@ private: void array_index_24() { // ticket #1492 and #1539 - if (CHAR_MAX == SCHAR_MAX) // plain char is signed - { - check("void f(char n) {\n" - " int a[n];\n" // n <= CHAR_MAX - " a[-1] = 0;\n" // negative index - " a[128] = 0;\n" // 128 > CHAR_MAX - "}\n"); - ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[128]' index 128 out of bounds\n" - "[test.cpp:3]: (error) Array index -1 is out of bounds\n", errout.str()); - - } - else // plain char is unsigned - { - check("void f(char n) {\n" - " int a[n];\n" // n <= CHAR_MAX - " a[-1] = 0;\n" // negative index - " a[256] = 0;\n" // 256 > CHAR_MAX - "}\n"); - ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[256]' index 256 out of bounds\n" - "[test.cpp:3]: (error) Array index -1 out of bounds\n", errout.str()); - } + // CHAR_MAX can be equal to SCHAR_MAX or UCHAR_MAX depending on the environment. + // This test should work for both environments. + std::ostringstream charMaxPlusOne; + charMaxPlusOne << (CHAR_MAX+1); + check(("void f(char n) {\n" + " int a[n];\n" // n <= CHAR_MAX + " a[-1] = 0;\n" // negative index + " a[" + charMaxPlusOne.str() + "] = 0;\n" // 128/256 > CHAR_MAX + "}\n").c_str()); + ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a["+charMaxPlusOne.str()+"]' index "+charMaxPlusOne.str()+" out of bounds\n" + "[test.cpp:3]: (error) Array index -1 is out of bounds\n", errout.str()); check("void f(signed char n) {\n" " int a[n];\n" // n <= SCHAR_MAX diff --git a/test/testclass.cpp b/test/testclass.cpp index a4f727618..d49d5abe3 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -2908,7 +2908,52 @@ private: void memsetOnClass() { - checkNoMemset("class A\n" + checkNoMemset("class Fred\n" + "{\n" + "};\n" + "void f()\n" + "{\n" + " Fred fred;\n" + " memset(&fred, 0, sizeof(Fred));\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + checkNoMemset("class Fred\n" + "{\n" + " std::string b; \n" + "};\n" + "void f()\n" + "{\n" + " Fred fred;\n" + " memset(&fred, 0, sizeof(Fred));\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on class that contains a 'std::string'\n", errout.str()); + + checkNoMemset("class Fred\n" + "{\n" + "};\n" + "void f()\n" + "{\n" + " Fred fred;\n" + " memset(&fred, 0, sizeof(fred));\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + checkNoMemset("class Fred\n" + "{\n" + " std::string s;\n" + "};\n" + "void f()\n" + "{\n" + " Fred fred;\n" + " memset(&fred, 0, sizeof(fred));\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on class that contains a 'std::string'\n", errout.str()); + } + + void memsetOnStruct() + { + checkNoMemset("struct A\n" "{\n" "};\n" "void f()\n" @@ -2924,23 +2969,24 @@ private: "void f()\n" "{\n" " struct A a;\n" - " memset(&a, 0, sizeof(A));\n" + " memset(&a, 0, sizeof(struct A));\n" "}\n"); ASSERT_EQUALS("", errout.str()); - } - void memsetOnStruct() - { - checkNoMemset("class A\n" + checkNoMemset("struct A\n" "{\n" - " void g( struct sockaddr_in6& a);\n" - "private:\n" - " std::string b; \n" "};\n" "void f()\n" "{\n" - " struct sockaddr_in6 fail;\n" - " memset(&fail, 0, sizeof(struct sockaddr_in6));\n" + " struct A a;\n" + " memset(&a, 0, sizeof(A));\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + checkNoMemset("void f()\n" + "{\n" + " struct sockaddr_in6 fail;\n" + " memset(&fail, 0, sizeof(struct sockaddr_in6));\n" "}\n"); ASSERT_EQUALS("", errout.str()); @@ -2966,18 +3012,68 @@ private: " Fred fred;\n" " memset(&fred, 0, sizeof(fred));\n" "}\n"); - TODO_ASSERT_EQUALS("error", "", errout.str()); + ASSERT_EQUALS("[test.cpp:8]: (error) Using 'memset' on struct that contains a 'std::string'\n", errout.str()); } void memsetVector() { + checkNoMemset("class A\n" + "{ std::vector ints; }\n" + "\n" + "void f()\n" + "{\n" + " A a;\n" + " memset(&a, 0, sizeof(A));\n" + "}"); + ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on class that contains a 'std::vector'\n", errout.str()); + checkNoMemset("struct A\n" "{ std::vector ints; }\n" "\n" "void f()\n" "{\n" " A a;\n" - " memset(a, 0, sizeof(A));\n" + " memset(&a, 0, sizeof(A));\n" + "}"); + ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str()); + + checkNoMemset("struct A\n" + "{ std::vector ints; }\n" + "\n" + "void f()\n" + "{\n" + " A a;\n" + " memset(&a, 0, sizeof(struct A));\n" + "}"); + ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str()); + + checkNoMemset("struct A\n" + "{ std::vector ints; }\n" + "\n" + "void f()\n" + "{\n" + " A a;\n" + " memset(&a, 0, sizeof(a));\n" + "}"); + ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str()); + + checkNoMemset("class A\n" + "{ std::vector< std::vector > ints; }\n" + "\n" + "void f()\n" + "{\n" + " A a;\n" + " memset(&a, 0, sizeof(A));\n" + "}"); + ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on class that contains a 'std::vector'\n", errout.str()); + + checkNoMemset("struct A\n" + "{ std::vector< std::vector > ints; }\n" + "\n" + "void f()\n" + "{\n" + " A a;\n" + " memset(&a, 0, sizeof(A));\n" "}"); ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str()); @@ -2987,7 +3083,7 @@ private: "void f()\n" "{\n" " A a;\n" - " memset(a, 0, sizeof(A));\n" + " memset(&a, 0, sizeof(a));\n" "}"); ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str()); @@ -2997,7 +3093,7 @@ private: "void f()\n" "{\n" " A a;\n" - " memset(a, 0, sizeof(A));\n" + " memset(&a, 0, sizeof(A));\n" "}"); ASSERT_EQUALS("[test.cpp:7]: (error) Using 'memset' on struct that contains a 'std::vector'\n", errout.str()); } diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index bdbd1e4d7..ad2a03b89 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -77,6 +77,8 @@ private: TEST_CASE(suppressionsOld); // TODO: Create and test real suppression file TEST_CASE(suppressions) TEST_CASE(suppressionsNoFile) + TEST_CASE(suppressionSingle) + TEST_CASE(suppressionSingleFile) TEST_CASE(templates); TEST_CASE(templatesGcc); TEST_CASE(templatesVs); @@ -554,6 +556,26 @@ private: ASSERT(!parser.ParseFromArgs(3, argv)); } + void suppressionSingle() + { + REDIRECT; + const char *argv[] = {"cppcheck", "--suppress=uninitvar", "file.cpp"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(parser.ParseFromArgs(3, argv)); + ASSERT_EQUALS(true, settings.nomsg.isSuppressed("uninitvar", "file.cpp", 1U)); + } + + void suppressionSingleFile() + { + REDIRECT; + const char *argv[] = {"cppcheck", "--suppress=uninitvar:file.cpp", "file.cpp"}; + Settings settings; + CmdLineParser parser(&settings); + ASSERT(parser.ParseFromArgs(3, argv)); + ASSERT_EQUALS(true, settings.nomsg.isSuppressed("uninitvar", "file.cpp", 1U)); + } + void templates() { REDIRECT; diff --git a/test/testother.cpp b/test/testother.cpp index 428e77ba2..5707fc264 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -106,6 +106,7 @@ private: TEST_CASE(incorrectStringCompare); TEST_CASE(incrementBoolean); + TEST_CASE(comparisonOfBoolWithInt); } void check(const char code[], const char *filename = NULL) @@ -144,6 +145,7 @@ private: checkOther.clarifyCalculation(); checkOther.checkIncorrectStringCompare(); checkOther.checkIncrementBoolean(); + checkOther.checkComparisonOfBoolWithInt(); } @@ -1923,6 +1925,51 @@ private: "}"); ASSERT_EQUALS("", errout.str()); } + + void comparisonOfBoolWithInt() + { + check("void f(int x) {\n" + " if (!x == 10) {\n" + " printf(\"x not equal to 10\");\n" + " }\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with a non-zero integer\n", errout.str()); + + check("void f(int x) {\n" + " if (!x != 10) {\n" + " printf(\"x not equal to 10\");\n" + " }\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with a non-zero integer\n", errout.str()); + + check("void f(int x) {\n" + " if (x != 10) {\n" + " printf(\"x not equal to 10\");\n" + " }\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("void f(int x) {\n" + " if (10 == !x) {\n" + " printf(\"x not equal to 10\");\n" + " }\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with a non-zero integer\n", errout.str()); + + check("void f(int x) {\n" + " if (10 != !x) {\n" + " printf(\"x not equal to 10\");\n" + " }\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (warning) Comparison of a boolean with a non-zero integer\n", errout.str()); + + check("void f(int x) {\n" + " if (10 != x) {\n" + " printf(\"x not equal to 10\");\n" + " }\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } }; REGISTER_TEST(TestOther) diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index faba401a5..37df95c61 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -92,6 +92,10 @@ private: TEST_CASE(error3); + // Don't handle include in a #if 0 block + TEST_CASE(if0_include_1); + TEST_CASE(if0_include_2); + // Handling include guards (don't create extra configuration for it) TEST_CASE(includeguard1); TEST_CASE(includeguard2); @@ -114,7 +118,6 @@ private: TEST_CASE(if_cond4); TEST_CASE(if_cond5); TEST_CASE(if_cond6); - TEST_CASE(if_cond7); TEST_CASE(if_cond8); TEST_CASE(if_cond9); TEST_CASE(if_cond10); @@ -195,6 +198,7 @@ private: TEST_CASE(ifdef_ifdefined); // define and then ifdef + TEST_CASE(define_if); TEST_CASE(define_ifdef); TEST_CASE(define_ifndef1); TEST_CASE(define_ifndef2); @@ -206,6 +210,8 @@ private: TEST_CASE(testPreprocessorRead2); TEST_CASE(testPreprocessorRead3); TEST_CASE(testPreprocessorRead4); + + TEST_CASE(invalid_define); // #2605 - hang for: '#define =' } @@ -635,6 +641,32 @@ private: ASSERT_EQUALS("[test.c:1]: (error) #error hello world!\n", errout.str()); } + void if0_include_1() + { + Settings settings; + Preprocessor preprocessor(&settings, this); + + std::istringstream code("#if 0\n" + "#include \"a.h\"\n" + "#endif\n" + "AB\n"); + ASSERT_EQUALS("\n\n\nAB\n", preprocessor.read(code,"",NULL)); + } + + void if0_include_2() + { + Settings settings; + Preprocessor preprocessor(&settings, this); + + std::istringstream code("#if 0\n" + "#include \"a.h\"\n" + "#ifdef WIN32\n" + "#else\n" + "#endif\n" + "#endif\n" + "AB\n"); + ASSERT_EQUALS("\n\n\n\n\n\nAB\n", preprocessor.read(code,"",NULL)); + } void includeguard1() { @@ -1232,48 +1264,6 @@ private: ASSERT_EQUALS("[file.c:2]: (error) mismatching number of '(' and ')' in this line: defined(A)&&defined(B))\n", errout.str()); } - void if_cond7() - { - { - const char filedata[] = "#define A 1\n" - "#if A==1\n" - "a1;\n" - "#endif\n"; - - // Preprocess => actual result.. - std::istringstream istr(filedata); - std::map actual; - Settings settings; - Preprocessor preprocessor(&settings, this); - preprocessor.preprocess(istr, actual, "file.c"); - - // Compare results.. - ASSERT_EQUALS(1, (int)actual.size()); - ASSERT_EQUALS("\n\na1;\n\n", actual[""]); - } - - { - const char filedata[] = "#define A 0\n" - "#if A\n" - "foo();\n" - "#endif\n"; - - // Preprocess => actual result.. - std::istringstream istr(filedata); - std::map actual; - Settings settings; - Preprocessor preprocessor(&settings, this); - preprocessor.preprocess(istr, actual, "file.c"); - - // Compare results.. - TODO_ASSERT_EQUALS(2, - 1, static_cast(actual.size())); - TODO_ASSERT_EQUALS("\n\n\n\n", - "\n\nfoo();\n\n", actual[""]); - } - } - - void if_cond8() { const char filedata[] = "#if defined(A) + defined(B) + defined(C) != 1\n" @@ -2440,6 +2430,24 @@ private: ASSERT_EQUALS(2, static_cast(actual.size())); } + void define_if() + { + { + const char filedata[] = "#define A 0\n" + "#if A\n" + "FOO\n" + "#endif"; + ASSERT_EQUALS("\n\n\n\n", Preprocessor::getcode(filedata,"","",NULL,NULL)); + } + { + const char filedata[] = "#define A 1\n" + "#if A==1\n" + "FOO\n" + "#endif"; + ASSERT_EQUALS("\n\nFOO\n\n", Preprocessor::getcode(filedata,"","",NULL,NULL)); + } + } + void define_ifdef() { { @@ -2720,6 +2728,18 @@ private: ASSERT_EQUALS("#define A \" \\\\\\\\\" \" \"", preprocessor.read(istr, "test.cpp", 0)); } } + + void invalid_define() + { + Settings settings; + Preprocessor preprocessor(&settings, this); + + std::istringstream src("#define =\n"); + std::string processedFile; + std::list cfg; + std::list paths; + preprocessor.preprocess(src, processedFile, cfg, "", paths); // don't hang + } }; REGISTER_TEST(TestPreprocessor) diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 3ee94725f..a546b3654 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -85,6 +85,7 @@ private: TEST_CASE(sizeof20); // #2024 - sizeof a) TEST_CASE(sizeof21); // #2232 - sizeof...(Args) TEST_CASE(sizeof22); // #2599 + TEST_CASE(sizeof23); // #2604 TEST_CASE(sizeofsizeof); TEST_CASE(casting); @@ -241,6 +242,7 @@ private: TEST_CASE(simplifyTypedef79); // ticket #2348 TEST_CASE(simplifyTypedef80); // ticket #2587 TEST_CASE(simplifyTypedef81); // ticket #2603 + TEST_CASE(simplifyTypedef82); // ticket #2403 TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -326,7 +328,8 @@ private: TEST_CASE(simplifyFunctionReturn); - TEST_CASE(removeUnnecessaryQualification); + TEST_CASE(removeUnnecessaryQualification1); + TEST_CASE(removeUnnecessaryQualification2); TEST_CASE(simplifyIfNotNull); } @@ -1432,6 +1435,15 @@ private: tok(code); } + void sizeof23() + { + // ticket #2604 segmentation fault + const char code[] = "sizeof <= A\n"; + + // don't segfault + tok(code); + } + void sizeofsizeof() { @@ -4931,6 +4943,24 @@ private: ASSERT_EQUALS("[test.cpp:1]: (error) syntax error\n", errout.str()); } + void simplifyTypedef82() // ticket #2403 + { + checkSimplifyTypedef("class A {\n" + "public:\n" + " typedef int F(int idx);\n" + "};\n" + "class B {\n" + "public:\n" + " A::F ** f;\n" + "};\n" + "int main()\n" + "{\n" + " B * b = new B;\n" + " b->f = new A::F * [ 10 ];\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } + void simplifyTypedefFunction1() { { @@ -6521,7 +6551,7 @@ private: ASSERT_EQUALS(expected, tok(code, false)); } - void removeUnnecessaryQualification() + void removeUnnecessaryQualification1() { const char code[] = "class Fred { Fred::Fred() {} };"; const char expected[] = "class Fred { Fred ( ) { } } ;"; @@ -6529,6 +6559,16 @@ private: ASSERT_EQUALS("[test.cpp:1]: (portability) Extra qualification 'Fred::' unnecessary and considered an error by many compilers.\n", errout.str()); } + void removeUnnecessaryQualification2() + { + const char code[] = "template\n" + "struct grammar : qi::grammar {\n" + " grammar() : grammar::base_type(start) { }\n" + "};\n"; + tok(code, false); + ASSERT_EQUALS("", errout.str()); + } + void simplifyIfNotNull() // ticket # 2601 segmentation fault { const char code[] = "|| #if #define <="; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index bfcb71b60..241929c74 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -38,6 +38,7 @@ public: ,typetok(NULL) ,t(NULL) ,found(false) + ,isArray(false) {} private: @@ -46,6 +47,7 @@ private: const Token* typetok; const Token* t; bool found; + bool isArray; void reset() { @@ -53,6 +55,7 @@ private: typetok = NULL; t = NULL; found = false; + isArray = false; } void run() @@ -93,213 +96,238 @@ private: TEST_CASE(hasInlineClassFunctionReturningFunctionPointer); TEST_CASE(hasMissingInlineClassFunctionReturningFunctionPointer); TEST_CASE(hasClassFunctionReturningFunctionPointer); + + TEST_CASE(hasGlobalVariables1); + TEST_CASE(hasGlobalVariables2); + TEST_CASE(hasGlobalVariables3); } void test_isVariableDeclarationCanHandleNull() { reset(); - bool result = si.isVariableDeclaration(NULL, vartok, typetok); + bool result = si.isVariableDeclaration(NULL, vartok, typetok, isArray); ASSERT_EQUALS(false, result); ASSERT(NULL == vartok); ASSERT(NULL == typetok); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesSimpleDeclaration() { reset(); givenACodeSampleToTokenize simpleDeclaration("int x;"); - bool result = si.isVariableDeclaration(simpleDeclaration.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(simpleDeclaration.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("x", vartok->str()); ASSERT_EQUALS("int", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesScopedDeclaration() { reset(); givenACodeSampleToTokenize ScopedDeclaration("::int x;"); - bool result = si.isVariableDeclaration(ScopedDeclaration.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(ScopedDeclaration.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("x", vartok->str()); ASSERT_EQUALS("int", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesStdDeclaration() { reset(); givenACodeSampleToTokenize StdDeclaration("std::string x;"); - bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("x", vartok->str()); ASSERT_EQUALS("string", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesScopedStdDeclaration() { reset(); givenACodeSampleToTokenize StdDeclaration("::std::string x;"); - bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(StdDeclaration.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("x", vartok->str()); ASSERT_EQUALS("string", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesManyScopes() { reset(); givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE x;"); - bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("x", vartok->str()); ASSERT_EQUALS("EE", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesPointers() { reset(); givenACodeSampleToTokenize pointer("int* p;"); - bool result = si.isVariableDeclaration(pointer.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(pointer.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("p", vartok->str()); ASSERT_EQUALS("int", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationDoesNotIdentifyConstness() { reset(); givenACodeSampleToTokenize constness("const int* cp;"); - bool result = si.isVariableDeclaration(constness.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(constness.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(false, result); ASSERT(NULL == vartok); ASSERT(NULL == typetok); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesFirstOfManyVariables() { reset(); givenACodeSampleToTokenize multipleDeclaration("int first, second;"); - bool result = si.isVariableDeclaration(multipleDeclaration.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(multipleDeclaration.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("first", vartok->str()); ASSERT_EQUALS("int", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesScopedPointerDeclaration() { reset(); givenACodeSampleToTokenize manyScopes("AA::BB::CC::DD::EE* p;"); - bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(manyScopes.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("p", vartok->str()); ASSERT_EQUALS("EE", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesDeclarationWithIndirection() { reset(); givenACodeSampleToTokenize pointerToPointer("int** pp;"); - bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("pp", vartok->str()); ASSERT_EQUALS("int", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesDeclarationWithMultipleIndirection() { reset(); givenACodeSampleToTokenize pointerToPointer("int***** p;"); - bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(pointerToPointer.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("p", vartok->str()); ASSERT_EQUALS("int", typetok->str()); + ASSERT(false == isArray); } void test_isVariableDeclarationIdentifiesArray() { reset(); givenACodeSampleToTokenize array("::std::string v[3];"); - bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("v", vartok->str()); ASSERT_EQUALS("string", typetok->str()); + ASSERT(true == isArray); } void test_isVariableDeclarationIdentifiesOfArrayPointers() { reset(); givenACodeSampleToTokenize array("A *a[5];"); - bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(array.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("a", vartok->str()); ASSERT_EQUALS("A", typetok->str()); + ASSERT(true == isArray); } void isVariableDeclarationIdentifiesTemplatedPointerVariable() { reset(); givenACodeSampleToTokenize var("std::set* chars;"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("chars", vartok->str()); ASSERT_EQUALS("set", typetok->str()); + ASSERT(false == isArray); } void isVariableDeclarationIdentifiesTemplatedPointerToPointerVariable() { reset(); givenACodeSampleToTokenize var("std::deque*** ints;"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("ints", vartok->str()); ASSERT_EQUALS("deque", typetok->str()); + ASSERT(false == isArray); } void isVariableDeclarationIdentifiesTemplatedArrayVariable() { reset(); givenACodeSampleToTokenize var("std::deque ints[3];"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("ints", vartok->str()); ASSERT_EQUALS("deque", typetok->str()); + ASSERT(true == isArray); } void isVariableDeclarationIdentifiesTemplatedVariable() { reset(); givenACodeSampleToTokenize var("std::vector ints;"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("ints", vartok->str()); ASSERT_EQUALS("vector", typetok->str()); + ASSERT(false == isArray); } void isVariableDeclarationIdentifiesTemplatedVariableIterator() { reset(); givenACodeSampleToTokenize var("std::list::const_iterator floats;"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("floats", vartok->str()); ASSERT_EQUALS("const_iterator", typetok->str()); + ASSERT(false == isArray); } void isVariableDeclarationIdentifiesNestedTemplateVariable() { reset(); givenACodeSampleToTokenize var("std::deque > intsets;"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(true, result); ASSERT_EQUALS("intsets", vartok->str()); ASSERT_EQUALS("deque", typetok->str()); + ASSERT(false == isArray); } void isVariableDeclarationDoesNotIdentifyTemplateClass() { reset(); givenACodeSampleToTokenize var("template class SomeClass{};"); - bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok); + bool result = si.isVariableDeclaration(var.tokens(), vartok, typetok, isArray); ASSERT_EQUALS(false, result); + ASSERT(false == isArray); } void canFindMatchingBracketsNeedsOpen() @@ -522,6 +550,60 @@ private: ASSERT(function && function->hasBody && !function->isInline && function->retFuncPtr); } } + + void hasGlobalVariables1() + { + GET_SYMBOL_DB("int i;\n") + + ASSERT(db && db->scopeList.size() == 1); + if (db && db->scopeList.size() == 1) + { + std::list::const_iterator it = db->scopeList.begin(); + ASSERT((*it)->varlist.size() == 1); + if ((*it)->varlist.size() == 1) + { + std::list::const_iterator var = (*it)->varlist.begin(); + ASSERT(var->name() == "i"); + ASSERT(var->typeStartToken()->str() == "int"); + } + } + } + + void hasGlobalVariables2() + { + GET_SYMBOL_DB("int array[2][2];\n") + + ASSERT(db && db->scopeList.size() == 1); + if (db && db->scopeList.size() == 1) + { + std::list::const_iterator it = db->scopeList.begin(); + ASSERT((*it)->varlist.size() == 1); + if ((*it)->varlist.size() == 1) + { + std::list::const_iterator var = (*it)->varlist.begin(); + ASSERT(var->name() == "array"); + ASSERT(var->typeStartToken()->str() == "int"); + } + } + } + + void hasGlobalVariables3() + { + GET_SYMBOL_DB("int array[2][2] = { { 0, 0 }, { 0, 0 } };\n") + + ASSERT(db && db->scopeList.size() == 1); + if (db && db->scopeList.size() == 1) + { + std::list::const_iterator it = db->scopeList.begin(); + ASSERT((*it)->varlist.size() == 1); + if ((*it)->varlist.size() == 1) + { + std::list::const_iterator var = (*it)->varlist.begin(); + ASSERT(var->name() == "array"); + ASSERT(var->typeStartToken()->str() == "int"); + } + } + } }; REGISTER_TEST(TestSymbolDatabase) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 7b35ea570..c25552845 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -79,6 +79,7 @@ private: TEST_CASE(ifAddBraces11); TEST_CASE(ifAddBraces12); TEST_CASE(ifAddBraces13); + TEST_CASE(ifAddBraces14); // #2610 - segfault: if()<{} TEST_CASE(whileAddBraces); TEST_CASE(doWhileAddBraces); @@ -128,6 +129,7 @@ private: TEST_CASE(simplifyKnownVariables39); TEST_CASE(simplifyKnownVariables40); TEST_CASE(simplifyKnownVariables41); // p=&x; if (p) .. + TEST_CASE(simplifyKnownVariables42); // ticket #2031 - known string value after strcpy TEST_CASE(simplifyKnownVariablesBailOutAssign); TEST_CASE(simplifyKnownVariablesBailOutFor1); TEST_CASE(simplifyKnownVariablesBailOutFor2); @@ -850,6 +852,13 @@ private: ASSERT_EQUALS(expected2, tokenizeAndStringify(code2, true)); } + void ifAddBraces14() + { + // ticket #2610 (segfault) + tokenizeAndStringify("if()<{}", false); + } + + void whileAddBraces() { const char code[] = ";while(a);"; @@ -2032,6 +2041,21 @@ private: ASSERT_EQUALS("void f ( ) {\nint x ; x = 0 ;\nconst int * p ; p = & x ;\nif ( & x ) { return 0 ; }\n}", tokenizeAndStringify(code, true)); } + void simplifyKnownVariables42() + { + const char code[] = "void f() {\n" + " char str1[10], str2[10];\n" + " strcpy(str1, \"abc\");\n" + " strcpy(str2, str1);\n" + "}"; + const char expected[] = "void f ( ) {\n" + "char str1 [ 10 ] ; char str2 [ 10 ] ;\n" + "strcpy ( str1 , \"abc\" ) ;\n" + "strcpy ( str2 , \"abc\" ) ;\n" + "}"; + ASSERT_EQUALS(expected, tokenizeAndStringify(code, true)); + } + void simplifyKnownVariablesBailOutAssign() { const char code[] = "int foo() {\n" diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index fbd29681d..796c7a71c 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -46,7 +46,8 @@ private: TEST_CASE(uninitvar_references); // references TEST_CASE(uninitvar_strncpy); // strncpy doesn't always 0-terminate TEST_CASE(uninitvar_func); // analyse functions - TEST_CASE(uninitvar_func2); // usage of 'void a(int *p) { *p = 0; }' + TEST_CASE(func_uninit_var); // analyse function calls for: 'int a(int x) { return x+x; }' + TEST_CASE(func_uninit_pointer); // analyse function calls for: 'void a(int *p) { *p = 0; }' TEST_CASE(uninitvar_typeof); // typeof } @@ -1436,8 +1437,29 @@ private: ASSERT_EQUALS("", errout.str()); } + // valid and invalid use of 'int a(int x) { return x + x; }' + void func_uninit_var() + { + const std::string funca("int a(int x) { return x + x; }\n"); + + checkUninitVar((funca + + "void b() {\n" + " int x;\n" + " a(x);\n" + "}").c_str()); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: x\n", errout.str()); + + checkUninitVar((funca + + "void b() {\n" + " int *p;\n" + " a(*p);\n" + "}").c_str()); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str()); + } + + // valid and invalid use of 'void a(int *p) { *p = 0; }' - void uninitvar_func2() + void func_uninit_pointer() { const std::string funca("void a(int *p) { *p = 0; }\n"); @@ -1455,7 +1477,7 @@ private: " int *p;\n" " a(p);\n" "}\n").c_str()); - TODO_ASSERT_EQUALS("error", "", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str()); } void uninitvar_typeof()