[clang] [analyzer] Trust base to derived casts for dynamic types (PR #69057)

Balazs Benics via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 6 10:22:43 PST 2024


steakhal wrote:

> > However, what should we do if multiple (N) classes implement Base? Trying each N, and basically splitting the state to (N+1) ways is not going to scale. Unless N is of course really small, like 2 or 3 at most.
> 
> That's kind of what I imagined - try them all. The Analyzer has a built-in timeout mechanism that will come into play.
> 
> If you wanted to be fancy, there could be an obscure config option, with a default of N=3. If config value is not set, and N>3 it asserts, alerting the user to the situation. If config value is set, it limits to analyzing the first N.

I re-read the thread, and I think the most promising approach would be to to split the path N ways to see the outcome.

An alternative workaround would be to somehow annotate the code to force it to split into N ways and then inject a static cast to each way doing the relevant base->derived cast that this PR already instrument and do the desired behavior.
Something like this:
```c++
template <class U, class T> void clang_analyzer_try_cast(const T *base) {
    extern bool analyzer_internal_coin();
    if (analyzer_internal_coin())
      (void)static_cast<const U*>(base);
}

template <class... Ts, class T>
void clang_analyzer_split_n_ways(const T *base) {
  static_assert(sizeof...(Ts) > 0);
  (clang_analyzer_try_cast<Ts>(base), ...);
}

struct Base {};
struct A : Base {};
struct B : Base {};
struct C : Base {};

void test(const Base *p) {
  clang_analyzer_split_n_ways<A, B, C>(p);  // <--- This is how the no-op static casts would split into A, B, C.
  // We should have like 3 paths here, plus the conservatively eval called path.
}


https://github.com/llvm/llvm-project/pull/69057


More information about the cfe-commits mailing list