Skip to content

Unify C file-scope redeclarations in tokenizer and symbol database - #8890

Open
KiritoYG wants to merge 2 commits into
cppcheck-opensource:mainfrom
KiritoYG:codex/unify-c-global-redeclarations
Open

KiritoYG wants to merge 2 commits into
cppcheck-opensource:mainfrom
KiritoYG:codex/unify-c-global-redeclarations

Conversation

@KiritoYG

@KiritoYG KiritoYG commented Sep 24, 2026 •

Copy link
Copy Markdown

C file-scope declarations such as int x; int x; and extern int x; int x; currently receive different variable IDs and separate Variable objects. This fixes both parts of Trac #6418, including the symbol-database issue noted in comment 2.

Reuse the ID in the actual file-scope variable map, then combine C global declarations before assigning symbol pointers. Prefer the initialized/non-extern declaration while preserving linkage flags and previously complete array dimensions. Function parameters, local shadows, record members and C++ declaration identities remain separate.

Two supporting changes prevent regressions exposed by the shared identity: a late static initializer must not restore a constant value after an earlier function write or address escape, and a later unsized array initializer must not shrink a bound provided by an earlier declaration. The resulting analysis finds out-of-bounds accesses both before and after a complete array declaration, while accepting in-bounds accesses with partial initializers.

Preserve each merged declaration's original tokens and storage/initialization flags, and expose them as additive <declaration> children in the XML dump. The Python parser retains one canonical variable and accepts older dumps. MISRA declaration checks and cross-file summaries use the occurrence metadata, so earlier extern declarations remain visible and declarations are not counted as ordinary uses. Internal and definition summaries retain one object identity.

Validation on Windows with Clang 22.1.8 and CMake/Ninja (Debug, PCH disabled, serial build):

  • Both original identity regressions fail on unchanged production code and pass with the fix.
  • All 5,302 native unit tests pass, with 351 existing TODO assertions. Eight new cases cover identity, metadata, scope isolation, bounds and late initialization. Existing C alignment expectations now use one object; a shadow warning's related location now cites the selected definition rather than its earlier extern declaration.
  • Twelve actual CLI controls pass. Eleven valid fixtures pass Clang C11 syntax checking; a deliberately conflicting declaration remains a no-crash control. The intermediate late-initializer regression was reproduced and eliminated.
  • The original MISRA cross-file command now passes after reproducing its failure on the initial PR. C89, C11 and C++ MISRA verification fixtures pass, as do all 29 addon pytest cases under -Werror --strict-markers, including four new parser/declaration/CTU cases. Original suppression expectations are unchanged. The CTU reader now closes its input files deterministically.
  • The native suite passes after the metadata change; a further focused case covers extern → tentative → initialized → extern replacement history. Uncrustify 0.80.1, pylint with the Python 3.7 target and git diff --check pass. The GCC range-loop warning in the new value-flow test is fixed.
  • Separate public-fork Linux validation passes on code identical to f775f03 (the helper commit adds only its verification workflow): Ubuntu 22.04/GCC 11.4, standalone -Werror and -Werror=range-loop-construct, 5,364 native tests with 360 existing TODOs and zero failures; 29 addon tests; 112 dump-parser tests with 3 expected failures; original MISRA CTU and C89/C11 verification. Compiler commands and logs are attached to that run. This is independent validation; the new upstream workflows still require maintainer approval. GUI was not tested in this follow-up.

This covers compatible C file-scope redeclarations; it does not implement block-scope extern merging or full declaration compatibility checking.

Please assign this work to KiritoYG if needed and consider it under the published $10 bounty schedule, subject to acceptance and the required ticket closure. Please confirm eligibility and the supported settlement route; GitHub Sponsors is available if accepted. No award or payment is being claimed.

Comment thread lib/symboldatabase.cpp Fixed
Comment thread lib/symboldatabase.cpp
// find variables
scope.getVariableList();

if (mTokenizer.isC() && scope.type == ScopeType::eGlobal) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is an AI review take it with a grain of salt. Please feel free to reject it by clicking on Resolve button

I checked this for new false positives, built against its merge-base:

  • C corpus: ~370 open-source C files (mbedtls, wpa_supplicant crypto/ap, STM32 HAL) plus test/cfg/*.c and samples, with --enable=style,warning,performance,portability --inconclusive. The output was identical: 3715 warnings in both.
  • MISRA addon on addons/test/misra/misra-test.c, the CTU tests and a probe file: the only difference is 4 fewer misra-c2012-8.9 warnings, which were false positives (e.g. static int s; void w(void){ s = 5; } static int s = 0; void r(void){ ... s ... }). Base counted each declaration as an object used in only one function.
  • Targeted probes: write before a late initializer, address escape via a function pointer, extern int a[10]; int a[] = {1,2,3};, tentative definition after an initialized one, globals shadowed by parameters, static locals and block-scope extern. The PR removes 3 false positives that the merge-base has (two knownConditionTrueFalse, one arrayIndexOutOfBounds on a[9] for extern int a[10]; int a[] = {1,2,3};) and adds none.

So from the false-positive point of view this looks safe to me. One unrelated existing issue I noticed: int g; void f(void) { extern int g; g = 4; } gives shadowVariable on both builds. Block-scope extern is out of scope for this PR, as the description says.

@danmar

danmar commented Oct 2, 2026

Copy link
Copy Markdown
Collaborator

can you please clarify if you used AI for some of these changes?

I fear we can't start accepting AI generated fixes in tokenizer/symboldatabase/valueflow.

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