Some functions uses a platform dependent `ssize_t` (e.g. `read`). Currently, we

provide different summaries for the possible variants depending on the

canonical type of `ssize_t` (int, long, long long). In this patch we get rid of

this burden, thus making the administration of summaries easier. The newly

introduced `LazyRangeInt` is a union of a `RangeInt` and a function pointer. We

get the ranges lazily. By the time we need the ranges we already have a

concrete FunctionDecl set for the summary. When a function pointer is used

amongst the range values then we evaluate the function. This way we can get a

type dependent Max value and instead of providing 3 summaries to `read` we can

provide only one.

# Details

# Diff Detail

- Repository
- rG LLVM Github Monorepo

### Event Timeline

I am a bit unsure what the purpose of these `Max` summaries are? As far as I understand the `Max` represents the largest value for the type of the formal parameter.

Do we really ever need to specify this in a summary? Isn't it always an error to pass a value that is larger than the formal's type can represent?

If the answer is yes, I think we should have a separate checker for catching those overflows. If the answer is no, we might want to express a simpler summary, something like `cannot overflow on argument X`.

What do you think?

Yes, that's right. The tricky part here is that, when we write the summary we may not know what is going to be the type. In some cases (e.g. `read` with `ssize_t`) it turns out only after we looked up the `FunctionDecl`.

Isn't it always an error to pass a value that is larger than the formal's type can represent?

If the answer is yes, I think we should have a separate checker for catching those overflows. If the answer is no, we might want to express a simpler summary, something likecannot overflow on argument X.

The answer is yes. And yep we could have such a checker. But please read on.

Do we really ever need to specify this in a summary?

It would be possible to have a different DSL for describing the summaries. Now, the `RangeConstraint` requires a list of ranges, but that's just some technical detail. So, instead of

.ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, Max)))

we could have

.ArgConstraint(ArgumentCondition(0, WithinRange, GreaterThanOrEqTo(0)))

. In this case, however, `GreaterThanOrEqTo` would return a range(0, Max). And `Max` still would be something that we can evaluate only lazily (once we have the FunctionDecl).

I prefer the explicit Range(0, Max) notion, because then the range is seen immediately.

Since D80016 we are able to look up types in the TU, so we can get the maximum value from the found type.