|
For correctness, I now realize that we need to consider the full transitive
closure of whitelisted items, including blacklisted items that we would
otherwise not consider as whitelisted. We need this so that the data flow
propagates properly through dependencies that may or may not be blacklisted.
This means that tracing infrastructure needs to trace items regardless if they
are hidden or blacklisted. It is now the responsibility of consumers of a
traversal to filter out such items if they are unwanted. I did this by turning
the `ir::context::WhitelistedItems` type alias into a proper struct that
performs the filtering. This approach avoids changing the many callers of
whitelisted items traversal iteration.
Additionally, and equally importantly, I realized that the case of template
instantiations' template usages were subtly wrong. Before this commit, we only
considered a template argument used if it itself was a template parameter. This
breaks down in the face of template instantiations used as arguments to another
template instantiation. If the inner instantiation used a template parameter, we
would accidentally lose that usage. For example:
```c++
template <class T>
struct Foo {
// Direct usage of a template parameter T in an instantiation always worked.
Bar<T> member;
// While indirect usage of a template parameter nested within another
// instantiation did NOT previously work.
Bar< Qux<T> > another_member;
};
```
The solution is to take the union of each template arguments' template usages,
not the template arguments themselves but only if they were themselves a
template parameter. Obvious in retrospect!
|