Skip to content

Partial fix for #15048 Inconsistent error severity for uninitvar - #8966

Open
chrchr-github wants to merge 5 commits into
cppcheck-opensource:mainfrom
chrchr-github:chr_15048_uv
Open

chrchr-github wants to merge 5 commits into
cppcheck-opensource:mainfrom
chrchr-github:chr_15048_uv

Conversation

@chrchr-github

Copy link
Copy Markdown
Collaborator

No description provided.

@dmcppcheck

Copy link
Copy Markdown
Contributor

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

Test: http://ec2-16-170-140-253.eu-north-1.compute.amazonaws.com/pr-8966/
packages: 100
Differing warnings: 32 (+16 -16)
AI review: 24 improvement, 8 neutral (http://ec2-16-170-140-253.eu-north-1.compute.amazonaws.com/pr-8966/2026-10-26_18-39-33-fe389d3ea5e1-review.txt)
Timing: -0.2% (http://ec2-16-170-140-253.eu-north-1.compute.amazonaws.com/pr-8966/2026-10-26_18-39-33-fe389d3ea5e1_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.

@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

The change makes the severity less consistent and turns definite bugs into warnings. Whether Value::conditional is set depends on the code after the if, not on whether the read is guarded by a condition. Two examples:

  • if (b) return i; return 0; is still reported as an error.
  • if (b) return i; i = 1; return i; is now reported as a warning.

In both functions the read inside the branch is uninitialized every time it runs, so the second case should still be an error. Calls such as if (b) g(i); i = 1; g(i); are also demoted to a warning, although if (b) g(i); alone stays an error.

For if (b) return i; return i;, the read at line 17 is now a warning, while the unconditional return i; on the next line is reported only by legacyUninitvar (as an error). The new test makes the demotion of a definite bug the expected result. I found no crashes.

Testing

I built cppcheck and testrunner in both pr/ and base/.

  • ./testrunner TestUninitVar: all passed.
  • Full ./testrunner: all passed.

Test file b.cpp:

int f1(bool b) {
    int i;
    if (b)
        return i;
    i = 1;
    return i;
}
int f3(bool b) {
    int i;
    if (b)
        return i;
    return 0;
}
int f4(bool b) {
    int i;
    if (b)
        return i;
    return i;
}
int f5(bool b) {
    int i;
    if (b)
        return i + 1;
    i = 2;
    return i;
}
void g(int);
void f6(bool b) {
    int i;
    if (b)
        g(i);
    i = 1;
    g(i);
}

Command: cppcheck -q --template='{line}:{severity}:{id}:{message}' b.cpp

base:

4:error:uninitvar:Uninitialized variable: i
11:error:uninitvar:Uninitialized variable: i
17:error:uninitvar:Uninitialized variable: i
23:error:uninitvar:Uninitialized variable: i
31:error:uninitvar:Uninitialized variable: i
18:error:legacyUninitvar:Uninitialized variable: i

PR:

4:warning:uninitvar:Uninitialized variable: i
11:error:uninitvar:Uninitialized variable: i
17:warning:uninitvar:Uninitialized variable: i
23:warning:uninitvar:Uninitialized variable: i
31:warning:uninitvar:Uninitialized variable: i
18:error:legacyUninitvar:Uninitialized variable: i

Lines 4 and 11 are the same kind of read, but they now get different severities. Lines 4, 17, 23 and 31 are reads that are always uninitialized whenever they run, yet they were demoted from error to warning.

A second set of 14 one-line variants (if (b) g(i);, loops, switch, ?:, &&, nested if, pointer dereference) gave the same results in base and PR, apart from the case above.


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

Comment thread lib/checkuninitvar.cpp
ErrorPath errorPath = v.errorPath;
errorPath.emplace_back(tok, "");
auto severity = v.isKnown() ? Severity::error : Severity::warning;
auto severity = v.isKnown() && !v.conditional ? Severity::error : Severity::warning;

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

conditional is not a reliable sign that the read is only possibly uninitialized. Here it gets set depending on what follows the if.

  • int i; if (b) return i; return 0; still gives error.
  • int i; if (b) return i; i = 1; return i; now gives warning.
  • if (b) g(i); i = 1; g(i); is also demoted to warning.

In each case the read inside the branch is uninitialized every time it executes, so these are definite bugs that used to be errors. The patch makes the severity less consistent instead of more.

Comment thread test/testuninitvar.cpp
" i = 1;\n"
" return i;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4:16]: warning: Uninitialized variable: i [uninitvar]\n"

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 expectation locks in a downgrade: return i; inside if (b) always reads an uninitialized i, and base reports it as an error. If return 0; replaces the i = 1; return i; tail, the same read is still reported as an error, so this test documents the inconsistency instead of fixing it.

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.

3 participants