Skip to content

fix(c,cpp): a member whose type a macro renames links what the macro names - #3173

Merged
colbymchenry merged 1 commit into
mainfrom
claude/fix-c-macro-renames
Nov 1, 2026
Merged

colbymchenry merged 1 commit into
mainfrom
claude/fix-c-macro-renames

Conversation

@colbymchenry

Copy link
Copy Markdown
Owner

Summary

A struct member whose type a macro renames now links what the macro names. redis-cli.c's sds members are hiredis's hisds, not src/sds.h's namesake typedef.

Second of a stack of four, on top of #3172.

Root cause

redis-cli.c and redis-benchmark.c include hiredis's sdscompat.h, which has #define sds hisds. The parser sees sds, and a macro with no parameters has no node, so #3144 linked 24 members to the only sds the project declares.

The fix

matchCppDeclaredType asks what the name is renamed to where it is written (src/resolution/c-macro-renames.ts).

  • Finding renames. Headers are read once per resolver, by a search for define, into an index by macro name. A name nothing renames costs one lookup. The scan stops at 16 MB of headers: betaflight has 109 MB, nearly all vendor register maps.
  • When one counts. As the preprocessor applies it: the translation unit from the asking file must have certainly defined the macro by that line. isCppMacroDefinedAt is the existing include walk, following one object-like macro. So not above the #include or the #define, and not under a flag no file sets.
  • When it doesn't. Two arms that disagree say nothing, and a new name that is no project type leaves the name as written.

The same rule corrected two more that nobody had read:

  • redis's core sets REDISMODULE_CORE, so RedisModuleString is robj in module.c, 19 edges. A module that includes the same header keeps the typedef.
  • jq's #define YYLTYPE location: bison's struct is compiled out, 3 edges.

Validation

Windows 11, main 4499d00.

Tests. 5 of the 7 new tests fail on main and all pass. 9 mutations each fail a test.

A/B against main.

Repo Language Result
redis C 43 moved: 24 to hisds, 19 to robj, each checked against the includes and the flag. Nothing lost
jq C 3 moved to location, right
glfw, betaflight, rocksdb, leveldb C, C++ nothing from this commit
gin, flask controls identical

No extraction change.

Cost. A resolver's scan is 26 ms on redis and 81 ms on rocksdb, once per worker; 49 ms of a redis index's profile in all. Whole-index CPU in the same run: redis +0.6%. rocksdb, 3 interleaved rounds on a busy machine: 132.3 to 129.7 s, level.

Left out. 551 calls edges in redis's CLI files have the same problem on both arms: #define sdslen hi_sdslen means sdslen(x) is hiredis's, and it links to src/sds.c's. The index added here would serve for that, but it is a change to call resolution and not on my list.

Suite. 857 files passed and 6 skipped, 10,651 tests passed, 2 expected fail, 87 skipped, 4 workers, with the kernel, on the stack one clean rebase back (719ea417 on main 3bd9949). After the rebase onto 087de4c, whose hunks are apart from these: 138 files and 2,224 tests of the C, C++, Objective-C, Python and extraction suites pass on the tip.

🤖 Generated with Claude Code

Base automatically changed from claude/fix-c-macro-statements to main November 1, 2026 05:10
…names

redis-cli.c and redis-benchmark.c include hiredis's sdscompat.h, which has
`#define sds hisds`. Their 24 `sds` members were linked to src/sds.h's
namesake typedef, a false edge new in PR 3144: the parser sees `sds`, and a
macro with no parameters has no node.

matchCppDeclaredType now asks what the name is renamed to where it is
written. Headers are read once per resolver, by a search for `define`, into
an index by macro name, so a name nothing renames costs one lookup. A rename
counts as the preprocessor applies it: the translation unit from the asking
file must have certainly defined the macro by that line
(isCppMacroDefinedAt, the existing include walk following one object-like
macro). So not above the `#include` or the `#define`, not under a flag no
file sets, and not when two arms disagree. A new name that is no project type
leaves the name as written. The scan stops at 16 MB of headers per resolver:
betaflight has 109 MB, nearly all vendor register maps.

The same rule corrects two more that nobody had read:
- redis's core sets REDISMODULE_CORE, so `RedisModuleString` is `robj` in
  module.c, 19 edges. A module that includes the same header keeps the
  typedef, as does the header read on its own.
- jq's `#define YYLTYPE location`: bison's struct is compiled out, 3 edges.

Validation against main 4499d00:
- Tests: 5 of 7 fail on main, all pass. 9 mutations each fail a test.
- redis 43 edges moved, 24 to `hisds` and 19 to `robj`, each checked against
  the includes and the flag; nothing lost. jq 3 moved, right.
- rocksdb, leveldb, glfw, betaflight, gin, flask: nothing from this commit.
- No extraction change. Cost: a resolver's scan is 26 ms on redis and 81 ms
  on rocksdb, once per worker; 49 ms of a redis index's profile in all.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@colbymchenry
colbymchenry force-pushed the claude/fix-c-macro-renames branch from 6c87525 to c4683d1 Compare November 1, 2026 05:10
@colbymchenry
colbymchenry merged commit cb1e13d into main Nov 1, 2026
@colbymchenry
colbymchenry deleted the claude/fix-c-macro-renames branch November 1, 2026 05:10
bompus added a commit to bompus/codegraph that referenced this pull request Nov 2, 2026
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.

1 participant