A C++ name is looked up from where it is written, and a class that a
source file defines belongs to that file's translation unit, so only that
file sees it (#2538). A header that declares `struct Rep;` and
`std::unique_ptr<Rep> rep_;` writes the name for a `Table::Rep` that its
source file defines, and code in that file reads the member through it.
The lookup ran from the header, saw no source file's classes and found
nothing. The call was then guessed by the method's name, often onto the
calling class's own method:
- leveldb's `rep_->index_block->NewIterator(…)` reached
`Table::NewIterator`;
- rocksdb's `rep->write_batch.GetDataSize()` reached
`WriteBatchWithIndex::GetDataSize`;
- rocksdb's `level_iters_[i]->status()` reached `ForwardIterator::status`.
cppClassWritten's lookup now also sees the classes of the file the
reference is in, the translation unit that includes the header
(visibleFrom(file, unit)). classNode filters by that same visibility
instead of recomputing the header's.
A member-chain diagnostic on main 81fd0078 found 99 rocksdb and 7 leveldb
chain calls through a `Rep` whose class couldn't be placed.
Kit A/B against main 5994edb3:
| repo | removed | added | retargeted | same target, now typed |
|---|---|---|---|---|
| rocksdb | 34 | 40 | 43 | 56 |
| fmt | 0 | 27 | 0 | 1 |
| protobuf | 25 | 1 | 2 | 2 |
| leveldb | 0 | 1 | 3 | 3 |
| redis | identical | | | |
- Retargeted: from the calling class's own method or a namesake to the
member's class:
- rocksdb: WriteBatch, ForwardLevelIterator, IndexBuilder and
PartitionedIndexBuilder, RangeDelBlockBuilder, Env, MemFile;
- leveldb: Block::NewIterator;
- protobuf: DescriptorPool::Tables::FindSymbol.
- Removed: calls on library members reached this way, which had linked to
namesakes:
- `std::stack::pop` (BinaryHeap::pop);
- `std::vector::size` (Block::size);
- `std::thread::join` (WindowsThread::join);
- absl::flat_hash_set's `clear` (Map::clear);
- `std::optional`'s `has_value` and `reset` (Option,
ScopedPythonPtr).
- Added:
- WriteBatch's Put, Delete, Merge and the rest, through
WriteBatchWithIndex's `rep->write_batch`;
- gtest's UnitTestImpl through `impl()`, in fmt's and rocksdb's vendored
gtest;
- leveldb's FilterPolicy::Name.
- About 35 changed sites read by hand were all right.
Mutations: dropping the unit from visibleFrom, or from the lookup's call,
fails the new tests. classNode's own filter only chooses among several
declarations of one class, and nothing on the kit or in the tests has two,
so dropping it survives.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>