Skip to content

Fix #720 (#if: wrong macro usage for macros defined before the #if) - #721

Merged
danmar merged 2 commits into
masterfrom
fix-720
Nov 6, 2026
Merged

danmar merged 2 commits into
masterfrom
fix-720

Conversation

@danmar

@danmar danmar commented Nov 6, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

@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 fix works for the cases in #720. Uses in #if X, #if defined(X), #elif, function-like macros and nested macros are now each reported once, at the right location. I found no regressions and every test suite passes.

There is one case the PR does not handle: defined(X) does not record a use when X is not yet defined. Everything else does record a use for an undefined name that gets defined later: #ifdef/#ifndef (lines 3910/3919) and, with this PR, a plain #if X (line 4010). So with #if !defined(GUARD) / #define GUARD, GUARD gets no usage entry, while #ifndef GUARD / #define GUARD does. That is the common include-guard pattern. Tools that use macroUsage to find unused macros, such as cppcheck dump output and MISRA 2.5, will then wrongly report the guard as unused. Base did not report it either, because it recorded the name defined, so this is a gap left by the fix rather than a regression. It is still the obvious remaining case of the same issue.

Testing

Builds and test suites (all pass):

  • make -j8 testrunner simplecpp CXXOPTS=-Werror in pr/ builds cleanly.
  • ./testrunner: 0 failed.
  • python3 run-tests.py: 176 tests, 0 failed.
  • pytest integration_test.py: 128 passed.
  • ./selfcheck.sh: exit code 0.

Comparing base and PR: the command-line tool does not print macro usage, so I wrote a small driver (scratch/drv.cpp). It calls simplecpp::preprocess with a macroUsage list, prints each entry, and is linked against base/simplecpp.o and pr/simplecpp.o.

Input base PR
#define F(a) a / #if F(1) F reported twice F reported once
#define A B / #define B 1 / #if A A twice, B once A once, B once
#define X 1 / #if defined X && X one use (2:18) two uses (2:13 and 2:18)
#define X / #if 0 / #elif defined(X) none X use:3:15
#if 1 && Y / #endif / #define Y 1 none Y use:1:10
#define F(a) a / #if F F twice F once

#undef X / #if X / later #define X gives the same result in both.

Case still missing:

#if !defined(X)
#define X 1
#endif

The driver prints nothing for both base and PR. With #ifndef X instead, both print X def:2 use:1:9. With #if defined(X) || X / #endif / #define X 1, the PR records only the plain X (X def:3 use:1:19), not the defined(X) one.


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

Comment thread simplecpp.cpp Resolved
@danmar
danmar merged commit ab23e4a into master Nov 6, 2026
58 of 59 checks passed
@danmar
danmar deleted the fix-720 branch November 6, 2026 16:30
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