From e12b29b1de1766de5ab71f7fa9ebe281c32d992d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 31 Jan 2026 10:52:17 +0100 Subject: [PATCH 1/4] Fix #14457 (ValueType: char expression without signedness) --- lib/symboldatabase.cpp | 6 ++---- test/testsymboldatabase.cpp | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 58253d14bff..3d14b78815a 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -7636,9 +7636,7 @@ static const Token* parsedecl(const Token* type, // Set signedness for integral types.. if (valuetype->isIntegral() && valuetype->sign == ValueType::Sign::UNKNOWN_SIGN) { - if (valuetype->type == ValueType::Type::CHAR) - valuetype->sign = defaultSignedness; - else if (valuetype->type >= ValueType::Type::SHORT) + if (valuetype->type >= ValueType::Type::SHORT) valuetype->sign = ValueType::Sign::SIGNED; } @@ -8756,7 +8754,7 @@ ValueType::MatchResult ValueType::matchParameter(const ValueType *call, const Va return ValueType::MatchResult::UNKNOWN; } - if (call->isIntegral() && func->isIntegral() && call->sign != ValueType::Sign::UNKNOWN_SIGN && func->sign != ValueType::Sign::UNKNOWN_SIGN && call->sign != func->sign) + if (call->isIntegral() && func->isIntegral() && call->sign != func->sign) return ValueType::MatchResult::FALLBACK1; if (func->reference != Reference::None && (func->constness > call->constness || func->volatileness > call->volatileness)) diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index cc7464c70fc..92c8bbebdf4 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -586,6 +586,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(valueType2); TEST_CASE(valueType3); TEST_CASE(valueTypeThis); + TEST_CASE(valueTypeChar); TEST_CASE(variadic1); // #7453 TEST_CASE(variadic2); // #7649 @@ -7796,20 +7797,12 @@ class TestSymbolDatabase : public TestFixture { f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v7 ) ) ;"); ASSERT(f); ASSERT(f->function()); - if (std::numeric_limits::is_signed) { - ASSERT_EQUALS(10, f->function()->tokenDef->linenr()); - } else { - ASSERT_EQUALS(5, f->function()->tokenDef->linenr()); - } + ASSERT_EQUALS(10, f->function()->tokenDef->linenr()); f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v8 ) ) ;"); ASSERT(f); ASSERT(f->function()); - if (std::numeric_limits::is_signed) { - ASSERT_EQUALS(5, f->function()->tokenDef->linenr()); - } else { - ASSERT_EQUALS(11, f->function()->tokenDef->linenr()); - } + ASSERT_EQUALS(11, f->function()->tokenDef->linenr()); f = Token::findsimplematch(tokenizer.tokens(), "get ( get ( v9 ) ) ;"); ASSERT(f); @@ -10145,6 +10138,13 @@ class TestSymbolDatabase : public TestFixture { ASSERT_EQUALS("const C *", typeOf("class C { void foo() const; }; void C::foo() const { *this = 0; }", "this")); } + void valueTypeChar() { + Settings s = settings2; + s.platform.defaultSign = 's'; + ASSERT_EQUALS("char", typeOf("char c; c = 'x';", "c =", true, &s)); + ASSERT_EQUALS("char", typeOf("char buf[10]; buf[0] = 'x';", "[ 0 ]", true, &s)); + } + void variadic1() { // #7453 { GET_SYMBOL_DB("CBase* create(const char *c1, ...);\n" From 5dcc535cb164aa5cac4828b33ffc25dbe6f9ddca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 31 Jan 2026 11:21:07 +0100 Subject: [PATCH 2/4] testrunner --- test/testclangimport.cpp | 2 +- test/testother.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/testclangimport.cpp b/test/testclangimport.cpp index c67767db0ba..ff670a172d8 100644 --- a/test/testclangimport.cpp +++ b/test/testclangimport.cpp @@ -1328,7 +1328,7 @@ class TestClangImport : public TestFixture { const Token *tok = Token::findsimplematch(tokenizer.tokens(), "\"hello\""); ASSERT(!!tok); ASSERT(!!tok->valueType()); - ASSERT_EQUALS("const signed char *", tok->valueType()->str()); + ASSERT_EQUALS("const char *", tok->valueType()->str()); } void stdinLoc() { diff --git a/test/testother.cpp b/test/testother.cpp index 964abceca78..55fbe3830f1 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2341,7 +2341,7 @@ class TestOther : public TestFixture { checkInvalidPointerCast("void test(float* data) {\n" " f.write((char*)data,sizeof(float));\n" "}", dinit(CheckInvalidPointerCastOptions, $.inconclusive = true)); // #3639 - ASSERT_EQUALS("[test.cpp:2:13]: (portability, inconclusive) Casting from float * to signed char * is not portable due to different binary data representations on different platforms. [invalidPointerCast]\n", errout_str()); + ASSERT_EQUALS("[test.cpp:2:13]: (portability, inconclusive) Casting from float * to char * is not portable due to different binary data representations on different platforms. [invalidPointerCast]\n", errout_str()); checkInvalidPointerCast("long long* test(float* f) {\n" From b13e2aebeaf50dd17cc859d7b5a4c1ada5bb790d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 31 Jan 2026 13:11:38 +0100 Subject: [PATCH 3/4] fix --- lib/symboldatabase.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 3d14b78815a..1de93cc437a 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1915,7 +1915,10 @@ void SymbolDatabase::setArrayDimensionsUsingValueFlow() } if (bits > 0 && bits <= 62) { - if (dimension.tok->valueType()->sign == ValueType::Sign::UNSIGNED) + auto sign = dimension.tok->valueType()->sign; + if (sign == ValueType::Sign::UNKNOWN_SIGN && dimension.tok->valueType()->type == ValueType::Type::CHAR) + sign = mDefaultSignedness; + if (sign == ValueType::Sign::UNSIGNED) dimension.num = 1LL << bits; else dimension.num = 1LL << (bits - 1); From c34bd8a109d2c9593974dd3d47a64606475b1c1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 31 Jan 2026 13:33:19 +0100 Subject: [PATCH 4/4] TestCondition --- test/testcondition.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 186fe842b06..b9de521e67c 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -4601,11 +4601,7 @@ class TestCondition : public TestFixture { " if (o[1] == '\\0') {}\n" " }\n" "}\n"); - if (std::numeric_limits::is_signed) { - ASSERT_EQUALS("[test.cpp:6:18]: (style) Condition 'o[1]=='\\0'' is always false [knownConditionTrueFalse]\n", errout_str()); - } else { - ASSERT_EQUALS("[test.cpp:4:25] -> [test.cpp:6:18]: (style) Condition 'o[1]=='\\0'' is always false [knownConditionTrueFalse]\n", errout_str()); - } + ASSERT_EQUALS("[test.cpp:6:18]: (style) Condition 'o[1]=='\\0'' is always false [knownConditionTrueFalse]\n", errout_str()); check("void f(int x) {\n" // #11449 " int i = x;\n" @@ -5341,11 +5337,7 @@ class TestCondition : public TestFixture { " buffer.back() == '\\n' ||\n" " buffer.back() == '\\0') {}\n" "}\n"); - if (std::numeric_limits::is_signed) { - ASSERT_EQUALS("[test.cpp:5:22]: (style) Condition 'buffer.back()=='\\0'' is always false [knownConditionTrueFalse]\n", errout_str()); - } else { - ASSERT_EQUALS("[test.cpp:3:22] -> [test.cpp:5:22]: (style) Condition 'buffer.back()=='\\0'' is always false [knownConditionTrueFalse]\n", errout_str()); - } + ASSERT_EQUALS("[test.cpp:5:22]: (style) Condition 'buffer.back()=='\\0'' is always false [knownConditionTrueFalse]\n", errout_str()); // #9353 check("struct X { std::string s; };\n"