From 4d23f2b0f67ba6b4f1f76690ca27328276cf33ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Tue, 27 Jan 2026 16:29:28 +0100 Subject: [PATCH 1/4] Add test for 14444 --- test/testtokenize.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index b9978261914..38611c803e0 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -423,6 +423,7 @@ class TestTokenizer : public TestFixture { TEST_CASE(astdesignatedinit); TEST_CASE(astrvaluedecl); TEST_CASE(astorkeyword); + TEST_CASE(astenumdecl); TEST_CASE(startOfExecutableScope); @@ -7389,6 +7390,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) { From a4d40899bd26aa072b45810fc1b2b10c387437c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Tue, 27 Jan 2026 16:10:13 +0100 Subject: [PATCH 2/4] Fix #14444 --- lib/tokenlist.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 7fccbb89f1d..1138b410ddd 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 { From 79f4b71cf08ea7c92deffb21c5bdad75ff19fbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Tue, 27 Jan 2026 14:55:10 +0100 Subject: [PATCH 3/4] Add test for #14419 --- test/testsymboldatabase.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) 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" From 0adbfa70f597141faee04b8fbf2bc2e9c5d953ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Sun, 25 Jan 2026 14:01:21 +0100 Subject: [PATCH 4/4] Fix #14419 --- lib/symboldatabase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 1c77a365a1b..4b3a67861e0 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -6852,7 +6852,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())