Hi, Karthik. It’s true that the suppress-null-return-paths option suppresses many real errors. However, it also handles keeps us from reporting a huge number of false positives. Consider this silly example involving DenseMap:
llvm::DenseMap<const void*, const MemRegion *> map;
const MemRegion *getBaseRegion(const void *key) {
return map[key]->getBaseRegion();
}
In this case, “key” is known to be in the map, so we just look up the value and immediately dereference it. However, the analyzer isn’t smart enough to model a DenseMap, so it considers the case where the key is not in the map, which means a default-constructed value is inserted and returned (in this case, a null pointer). And we get a warning. Using an assert to silence the warning requires rewriting the code in terms of find(), which is not as clean.
Another instance is a case where some API wraps a dyn_cast (or equivalent):
RValue *getOperand(int i) {
return dyn_cast(getRawOperand(i));
}
In the general case, you don’t know if the operand is actually an RValue, but in some particular case (such as dealing with the arguments of a known builtin), you might have that information already. But again, the analyzer doesn’t know that, so if you try to use the result of getOperand() immediately, we get a warning.
if (getOperand(0)->isConstant()) { … }
Silencing this warning requires introducing a new temporary variable. It’s not impossible, but it’s the sort of hassle that makes people give up on the static analyzer.
These two examples are based on a ridiculous number of false positives reported in LLVM before we added this suppression. I think Anna and Ted and I all agree that it could be much better, to catch cases where the use really is plausible and accidental. But it’s hard to differentiate those. So, patches and suggestions welcome.
Hope that answers your question. (This should probably be put in some advanced analyzer FAQ somewhere…)
Jordan