diff --git a/.github/workflows/cppcheck-premium.yml b/.github/workflows/cppcheck-premium.yml
index 42bca8a6ebb..5cb63ca4d5e 100644
--- a/.github/workflows/cppcheck-premium.yml
+++ b/.github/workflows/cppcheck-premium.yml
@@ -45,9 +45,9 @@ jobs:
- name: Generate a license file
run: |
echo cppcheck > cppcheck.lic
- echo 251231 >> cppcheck.lic
+ echo 261231 >> cppcheck.lic
echo 80000 >> cppcheck.lic
- echo 4f8dc8e7c8bb288f >> cppcheck.lic
+ echo 4b64673f03fb6230 >> cppcheck.lic
echo path:lib >> cppcheck.lic
- name: Check
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3595154f7ae..7471d0c1fe6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13)
-project(Cppcheck VERSION 2.18.99 LANGUAGES CXX)
+project(Cppcheck VERSION 2.19.1 LANGUAGES CXX)
include(cmake/options.cmake)
diff --git a/Makefile b/Makefile
index 71b62bab7fc..a1d7066a2f2 100644
--- a/Makefile
+++ b/Makefile
@@ -132,9 +132,11 @@ ifeq (clang++, $(findstring clang++,$(CXX)))
CPPCHK_GLIBCXX_DEBUG=
endif
ifndef CXXFLAGS
- CXXFLAGS=-pedantic -Wall -Wextra -Wcast-qual -Wfloat-equal -Wmissing-declarations -Wmissing-format-attribute -Wno-long-long -Wpacked -Wredundant-decls -Wundef -Wno-sign-compare -Wno-multichar -Woverloaded-virtual -g
+ CXXFLAGS=-O2 -Wall -Wno-sign-compare -Wno-multichar
endif
+override CPPFLAGS += -DNDEBUG
+
ifeq (g++, $(findstring g++,$(CXX)))
override CXXFLAGS += -pipe
endif
@@ -385,7 +387,7 @@ dmake: tools/dmake/dmake.o cli/filelister.o $(libcppdir)/pathmatch.o $(libcppdir
$(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)
run-dmake: dmake
- ./dmake
+ ./dmake --release
clean:
rm -f build/*.cpp build/*.o lib/*.o cli/*.o frontend/*.o test/*.o tools/dmake/*.o externals/*/*.o testrunner dmake cppcheck cppcheck.exe cppcheck.1
diff --git a/cli/main.cpp b/cli/main.cpp
index d2a8417560e..dfe2d17527e 100644
--- a/cli/main.cpp
+++ b/cli/main.cpp
@@ -20,7 +20,7 @@
/**
*
* @mainpage Cppcheck
- * @version 2.18.99
+ * @version 2.19.1
*
* @section overview_sec Overview
* Cppcheck is a simple tool for static analysis of C/C++ code.
diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt
index 458569872c1..ff329ad1163 100644
--- a/gui/CMakeLists.txt
+++ b/gui/CMakeLists.txt
@@ -12,8 +12,11 @@ CheckOptions:
file(GLOB hdrs "*.h")
file(GLOB srcs "*.cpp")
file(GLOB uis "*.ui")
+ file(GLOB tss "*.ts")
QT_WRAP_UI(uis_hdrs ${uis})
QT_ADD_RESOURCES(resources "gui.qrc")
+ # TODO: passing "-no-obsolete" here breaks the translations
+ QT_CREATE_TRANSLATION(qms ${CMAKE_CURRENT_SOURCE_DIR} ${tss})
list(APPEND cppcheck-gui-deps ${hdrs} ${uis_hdrs} ${resources} ${qms})
add_custom_target(gui-build-deps SOURCES ${cppcheck-gui-deps})
diff --git a/gui/cppcheck_ja.ts b/gui/cppcheck_ja.ts
index ce3b3e1911c..461f1ef3f07 100644
--- a/gui/cppcheck_ja.ts
+++ b/gui/cppcheck_ja.ts
@@ -1093,7 +1093,7 @@ Parameters: -l(line) (file)
EULA...
-
+ EULA...
@@ -1773,7 +1773,7 @@ Options:
Reduced -- meant for usage where developer wants results directly. Limited and faster analysis with fewer results.
-
+ #R 限定的 -- 開発者が直接的に結果を得るための解析を意味します。解析は限定的で高速ですがより少ない結果になります。
@@ -1860,7 +1860,7 @@ Options:
2025
- 2025
+ 2025
@@ -2052,7 +2052,7 @@ Options:
Note: Open source Cppcheck does not fully implement Misra C 2012
-
+ 注意: オープンソースのCppcheckはMisra C 2012を完全にサポートしていません。
@@ -2463,12 +2463,12 @@ Options:
Recheck %1 file(s)
-
+ 再チェック %1 件のファイル
Hide %1 result(s)
-
+ 非表示 %1 件の結果
@@ -2883,7 +2883,7 @@ To toggle what kind of errors are shown, open view menu.
Max count:
-
+ #M 最大数:
diff --git a/gui/resultstree.cpp b/gui/resultstree.cpp
index 53f4a5f9ab9..78d56929b48 100644
--- a/gui/resultstree.cpp
+++ b/gui/resultstree.cpp
@@ -239,6 +239,11 @@ bool ResultsTree::addErrorItem(const ErrorItem& errorItem)
if (errorItem.errorPath.isEmpty())
return false;
+ const QString s = errorItem.toString();
+ if (mErrorList.contains(s))
+ return false;
+ mErrorList.append(s);
+
QSharedPointer errorItemPtr{new ErrorItem(errorItem)};
if (mReportType != ReportType::normal) {
@@ -393,6 +398,8 @@ ResultItem *ResultsTree::findFileItem(const QString &name) const
void ResultsTree::clear()
{
+ mErrorList.clear();
+
mModel->removeRows(0, mModel->rowCount());
if (const ProjectFile *activeProject = ProjectFile::getActiveProject()) {
@@ -419,6 +426,7 @@ void ResultsTree::clear(const QString &filename)
if (stripped == fileItem->text() ||
filename == fileItem->errorItem->file0) {
mModel->removeRow(i);
+ mErrorList.removeAll(fileItem->errorItem->toString());
break;
}
}
@@ -436,6 +444,7 @@ void ResultsTree::clearRecheckFile(const QString &filename)
storedfile = ((!mCheckPath.isEmpty() && storedfile.startsWith(mCheckPath)) ? storedfile.mid(mCheckPath.length() + 1) : storedfile);
if (actualfile == storedfile) {
mModel->removeRow(i);
+ mErrorList.removeAll(fileItem->errorItem->toString());
break;
}
}
diff --git a/gui/resultstree.h b/gui/resultstree.h
index 9537d6d929a..87907bc5d95 100644
--- a/gui/resultstree.h
+++ b/gui/resultstree.h
@@ -568,6 +568,9 @@ protected slots:
QStringList mHiddenMessageId;
+ // List of existing errors so we can avoid duplicates
+ QStringList mErrorList;
+
QItemSelectionModel* mSelectionModel{};
ThreadHandler *mThread{};
diff --git a/gui/test/resultstree/testresultstree.cpp b/gui/test/resultstree/testresultstree.cpp
index be09034609f..8208ca0343e 100644
--- a/gui/test/resultstree/testresultstree.cpp
+++ b/gui/test/resultstree/testresultstree.cpp
@@ -134,6 +134,19 @@ void TestResultsTree::test1() const
QCOMPARE(tree.isRowHidden(0,QModelIndex()), false); // Show item
}
+void TestResultsTree::duplicateResults() const
+{
+ // #14359 - filter out duplicate warnings
+ ResultsTree tree(nullptr);
+
+ ErrorItem errorItem;
+ errorItem.summary = errorItem.message = "test";
+ errorItem.severity = Severity::error;
+ errorItem.errorPath << QErrorPathItem();
+ QVERIFY(tree.addErrorItem(errorItem));
+ QVERIFY(!tree.addErrorItem(errorItem));
+}
+
static QErrorPathItem createErrorPathItem(QString file, int line, int column, QString info) {
QErrorPathItem ret;
ret.file = std::move(file);
diff --git a/gui/test/resultstree/testresultstree.h b/gui/test/resultstree/testresultstree.h
index 1e743581bac..108ed098eb5 100644
--- a/gui/test/resultstree/testresultstree.h
+++ b/gui/test/resultstree/testresultstree.h
@@ -23,6 +23,7 @@ class TestResultsTree : public QObject {
private slots:
void test1() const;
+ void duplicateResults() const;
void multiLineResult() const;
void resultsInSameFile() const;
void testReportType() const;
diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp
index d4107884642..498befce004 100644
--- a/lib/symboldatabase.cpp
+++ b/lib/symboldatabase.cpp
@@ -6849,7 +6849,7 @@ void SymbolDatabase::setValueType(Token* tok, const Enumerator& enumerator, cons
if (valuetype.type == ValueType::Type::UNKNOWN_TYPE)
valuetype.fromLibraryType(type->expressionString(), mSettings);
- if (valuetype.isIntegral()) {
+ if (valuetype.sign == ValueType::UNKNOWN_SIGN && valuetype.isIntegral()) {
if (type->isSigned())
valuetype.sign = ValueType::Sign::SIGNED;
else if (type->isUnsigned())
diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp
index 2953b0c895d..8785c10d988 100644
--- a/lib/tokenlist.cpp
+++ b/lib/tokenlist.cpp
@@ -1585,6 +1585,13 @@ static Token * createAstAtToken(Token *tok)
if (Token::Match(tok2, "%var% [;,)]"))
return tok2;
}
+ if (Token::Match(tok, "enum class| %name%| :")) {
+ if (Token::simpleMatch(tok->next(), "class"))
+ tok = tok->next();
+ if (Token::Match(tok->next(), "%name%"))
+ tok = tok->next();
+ return tok->next();
+ }
if (Token *const endTok = skipMethodDeclEnding(tok)) {
Token *tok2 = tok;
do {
diff --git a/lib/version.h b/lib/version.h
index 3a7c5918b45..d35d1f5195c 100644
--- a/lib/version.h
+++ b/lib/version.h
@@ -20,9 +20,9 @@
#ifndef versionH
#define versionH
-#define CPPCHECK_VERSION_STRING "2.19 dev"
-#define CPPCHECK_VERSION 2,18,99,0
+#define CPPCHECK_VERSION_STRING "2.19.1"
+#define CPPCHECK_VERSION 2,19,1,0
-#define LEGALCOPYRIGHT L"Copyright (C) 2007-2025 Cppcheck team."
+#define LEGALCOPYRIGHT L"Copyright (C) 2007-2026 Cppcheck team."
#endif
diff --git a/man/manual.md b/man/manual.md
index d8da119f388..4213cd1318a 100644
--- a/man/manual.md
+++ b/man/manual.md
@@ -1,6 +1,6 @@
---
title: Cppcheck manual
-subtitle: Version 2.19 dev
+subtitle: Version 2.19.1
author: Cppcheck team
lang: en
documentclass: report
diff --git a/man/reference-cfg-format.md b/man/reference-cfg-format.md
index 7a9e3b6dee7..891d44aa528 100644
--- a/man/reference-cfg-format.md
+++ b/man/reference-cfg-format.md
@@ -1,6 +1,6 @@
---
title: Cppcheck .cfg format
-subtitle: Version 2.19 dev
+subtitle: Version 2.19.1
author: Cppcheck team
lang: en
documentclass: report
diff --git a/man/writing-addons.md b/man/writing-addons.md
index da21ea513ad..b33a54e5ff1 100644
--- a/man/writing-addons.md
+++ b/man/writing-addons.md
@@ -1,6 +1,6 @@
---
title: Writing addons
-subtitle: Version 2.19 dev
+subtitle: Version 2.19.1
author: Cppcheck team
lang: en
documentclass: report
diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp
index b33dcdbc30a..cc7464c70fc 100644
--- a/test/testsymboldatabase.cpp
+++ b/test/testsymboldatabase.cpp
@@ -464,6 +464,7 @@ class TestSymbolDatabase : public TestFixture {
TEST_CASE(enum17);
TEST_CASE(enum18);
TEST_CASE(enum19);
+ TEST_CASE(enum20); // #14419
TEST_CASE(struct1);
@@ -6860,6 +6861,23 @@ class TestSymbolDatabase : public TestFixture {
}
}
+ void enum20() { // #14419
+ {
+ GET_SYMBOL_DB("enum class myclass : uint8_t { A = 0U };\n");
+ const Token *A = Token::findsimplematch(tokenizer.tokens(), "A");
+ ASSERT(A && A->valueType() && A->valueType()->isEnum());
+ ASSERT_EQUALS_ENUM(ValueType::CHAR, A->valueType()->type);
+ ASSERT_EQUALS_ENUM(ValueType::UNSIGNED, A->valueType()->sign);
+ }
+ {
+ GET_SYMBOL_DB("enum myclass : uint8_t { A = 0U };\n");
+ const Token *A = Token::findsimplematch(tokenizer.tokens(), "A");
+ ASSERT(A && A->valueType() && A->valueType()->isEnum());
+ ASSERT_EQUALS_ENUM(ValueType::CHAR, A->valueType()->type);
+ ASSERT_EQUALS_ENUM(ValueType::UNSIGNED, A->valueType()->sign);
+ }
+ }
+
void struct1() {
GET_SYMBOL_DB_C("struct deer {\n"
" uint16_t a;\n"
diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp
index c9d1b8336ab..5f3e6e02468 100644
--- a/test/testtokenize.cpp
+++ b/test/testtokenize.cpp
@@ -420,6 +420,7 @@ class TestTokenizer : public TestFixture {
TEST_CASE(astdesignatedinit);
TEST_CASE(astrvaluedecl);
TEST_CASE(astorkeyword);
+ TEST_CASE(astenumdecl);
TEST_CASE(startOfExecutableScope);
@@ -7373,6 +7374,11 @@ class TestTokenizer : public TestFixture {
ASSERT_EQUALS("ifsp.\"\"==sp.0==||(", testAst("void f() { if (s.p == \"\" or s.p == 0) {} }"));
}
+ void astenumdecl() {
+ ASSERT_EQUALS("A0U=", testAst("enum class myclass : unsigned char { A = 0U, };"));
+ ASSERT_EQUALS("A0U=", testAst("enum myclass : unsigned char { A = 0U, };"));
+ }
+
#define isStartOfExecutableScope(offset, code) isStartOfExecutableScope_(offset, code, __FILE__, __LINE__)
template
bool isStartOfExecutableScope_(int offset, const char (&code)[size], const char* file, int line) {
diff --git a/win_installer/productInfo.wxi b/win_installer/productInfo.wxi
index d07ce1136c9..78150400e3e 100644
--- a/win_installer/productInfo.wxi
+++ b/win_installer/productInfo.wxi
@@ -1,8 +1,8 @@
-
+
-
+