Tracking values through expressions and the stores is fundamental
for producing clear diagnostics. However, the main components
participating in this process, namely trackExpressionValue and
FindLastStoreBRVisitor, became pretty bloated. They have an
interesting dynamic between them (and some other visitors) that
one might call a "chain reaction". trackExpressionValue adds
FindLastStoreBRVisitor, and the latter calls trackExpressionValue.
Because of this design, individual checkers couldn't affect what's
going to happen somewhere in the middle of that chain. Whether they
want to produce a more informative note or keep the overall tracking
going by utilizing some of the domain expertise. This all lead to two
biggest problems that I see:
- Some checkers don't use it
This should probably never be the case for path-sensitive checks.
- Some checkers incorporated their logic directly into those components
This doesn't make the maintenance easier, breaks multiple
architecture principles, and makes the code harder to read adn
understand, thus, increasing the probability of the first case.
This commit introduces a prototype for a new interface that will be
responsible for tracking. My main idea here was to make operations
that I want have as a checker developer easy to implement and hook
directly into the tracking process.
After that I intend to make the following changes:
- Put all of the trackExpressionValue into one handler and replace calls to trackExpressionValue to Tracker::track
- Change visitors that call trackExpressionValue to have a parent Tracker, so they re-use the actual tracker that spawned them.
- Split trackExpressionValue implementation (at this point some big handler) into smaller handlers based on their semantics.
- Refactor all of the note producing code out of the FindLastStoreBRVisitor into a big clunky StoreHandler and call Tracker::handle instead.
- Split that one handler into smaller handlers based on their semantics.
- Extract certain handlers into checkers
I vaguely remember we wanting to put this defensive check suppression in the related checkers. If that is the case, I wonder if this option belongs here.