Skip to content

Fix #15193 Wrong type for hex literals that do not fit in 32-bit long - #9026

Open
wjakobsson wants to merge 2 commits into
cppcheck-opensource:mainfrom
wjakobsson:hex-literal-type
Open

wjakobsson wants to merge 2 commits into
cppcheck-opensource:mainfrom
wjakobsson:hex-literal-type

Conversation

@wjakobsson

Copy link
Copy Markdown
Collaborator

No description provided.

@wjakobsson wjakobsson changed the title #15193 Wrong type for hex literals that do not fit in 32-bit long Fix #15193 Wrong type for hex literals that do not fit in 32-bit long Nov 13, 2026

@dmcppcheck dmcppcheck left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review

I found no problems in the change. Switching from value >> 2 to value >> 1 makes the "fits in unsigned int/long" check exact. For a biguint, value >> 1 <= INT_MAX is the same as value <= UINT_MAX. On unix32, unix64 and win64 every hex and binary literal I tried now gets the type the C standard gives it. The U and L suffixes work too.

One case is still wrong, and the PR does not cause it. MathLib::isDec() counts octal literals as decimal. So on unix32 037777777777 (= 0xFFFFFFFF) gets the type signed long long instead of unsigned int, in both base and PR. The bug is in the same !MathLib::isDec(tokStr) condition the PR edits, so it could be fixed here or in a separate ticket.

Testing

  • Built cppcheck and testrunner in pr/, and cppcheck in base/. Both built cleanly.
  • ./testrunner TestSymbolDatabase TestValueFlow TestType TestOther TestCondition: 863 tests, 0 failed.
  • Compared the valueType of literals in --dump output between base and PR on unix32, unix64 and win64, using:
    void f(void) {
        (void)0xFFFFFFFF; (void)0x1FFFFFFFF; (void)0x100000000; (void)0xFFFFFFFFU; (void)0x100000000U;
        (void)037777777777; (void)077777777777; (void)0x8000000000000000; (void)0xFFFFFFFFFFFFFFFFL;
        (void)0x100000000L; (void)0x80000000L; (void)0x8000000000000000L;
    }
    • Base gave wrong types, for example 0x100000000 → unsigned int and 0x100000000L → unsigned long on unix32.
    • The PR gives the right types: signed long long on unix32/win64 and signed long on unix64. 0x100000000U → unsigned long long/unsigned long. 0xFFFFFFFF stays unsigned int, and 0x80000000L stays unsigned long on 32-bit long platforms.
    • Binary literals are also right, for example 0b1…1 (32 ones) → unsigned int.
  • Older bug found again, the same in base and PR: octal 037777777777 → signed long long on unix32. It should be unsigned int, because MathLib::isDec treats octal as decimal.
  • Older bug found again, the same in base and PR: an out-of-range literal 0x10000000000000000 gives internalError from MathLib::toBigUNumber.

Automated review of e9f7fde by Claude. The pull request was built and tested locally.

Comment thread lib/symboldatabase.cpp
if (type <= ValueType::Type::INT && mSettings.platform.isIntValue(unsignedSuffix ? (value >> 1) : value))
type = ValueType::Type::INT;
else if (type <= ValueType::Type::INT && !MathLib::isDec(tokStr) && mSettings.platform.isIntValue(value >> 2)) {
else if (type <= ValueType::Type::INT && !MathLib::isDec(tokStr) && mSettings.platform.isIntValue(value >> 1)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review

This is not caused by the PR, but it is the same condition: MathLib::isDec() returns true for octal literals. Octal literals follow the same type rules as hex (C11 6.4.4.1), but they never reach this branch. For example, with --platform=unix32 the literal 037777777777 (= 0xFFFFFFFF) gets the type signed long long instead of unsigned int, in both base and PR. You could fix it here, or open a follow-up ticket.

@dmcppcheck

Copy link
Copy Markdown
Contributor

Test results for commit e9f7fde (tools/test-my-pr.py, main compared to this PR):

Test: http://ec2-16-170-140-253.eu-north-1.compute.amazonaws.com/pr-9026/
packages: 100
Differing warnings: 0 (+0 -0)
Timing: -1.9% (http://ec2-16-170-140-253.eu-north-1.compute.amazonaws.com/pr-9026/2026-11-13_14-22-25-e9f7fde2ec4d_timing.html)

Posted automatically by the cppcheck PR test runner. +N: warnings only with this PR, -N: warnings only with main. The AI review is written by Claude and can be wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants