Yes, the goal is that anything that may take multi ranges be rewritten to use an irange * and use the API exclusively. Then when multi ranges are passed down eventually, things will work transparently.
Aldy On Mon, Aug 10, 2020, 19:50 Andrew MacLeod <amacl...@redhat.com> wrote: > On 8/10/20 12:35 PM, Martin Sebor via Gcc-patches wrote: > > On 8/10/20 5:47 AM, Aldy Hernandez wrote: > >> > >> > >> On 8/6/20 9:30 PM, Martin Sebor wrote: > >>> On 8/6/20 8:53 AM, Aldy Hernandez via Gcc-patches wrote: > >> > >>>> + // Remove the unknown parts of a multi-range. > >>>> + // This will transform [5,10][20,MAX] into [5,10]. > >>> > >>> Is this comment correct? Wouldn't this result in returning smaller > >>> sizes than the actual value allows? If so, I'd expect that to cause > >>> false positives (and in that case, if none of our tests fail we need > >>> to add some that would). > >>> > >>> By my reading of the code below it seems to return the upper range > >>> (i.e., [20, MAX]) but I'm not fully acquainted with the new ranger > >>> APIs yet. > >> > >> I believe the comment is correct. What I'm trying to do is remove > >> [X,TYPE_MAX_VALUE] from the range > >> > >>>> + int pairs = positives.num_pairs (); > >>>> + if (pairs > 1 > >>>> + && positives.upper_bound () == wi::to_wide (TYPE_MAX_VALUE > >>>> (exptype))) > >>>> { > >>>> - if (integral) > >>>> - { > >>>> - /* Use the full range of the type of the expression when > >>>> - no value range information is available. */ > >>>> - range[0] = TYPE_MIN_VALUE (exptype); > >>>> - range[1] = TYPE_MAX_VALUE (exptype); > >>>> - return true; > >>>> - } > >>>> - > >>>> - range[0] = NULL_TREE; > >>>> - range[1] = NULL_TREE; > >>>> - return false; > >>>> + value_range last_range (exptype, > >>>> + positives.lower_bound (pairs - 1), > >>>> + positives.upper_bound (pairs - 1), VR_ANTI_RANGE); > >>>> + positives.intersect (last_range); > >>>> } > >> > >> Notice that we start with positives == vr (where vr is the range > >> returned by determine_value_range). > >> > >> Then we build last_range which is the *opposite* of > >> [X,TYPE_MAX_VALUE]. Notice the VR_ANTI_RANGE in the constructor. > >> > >> (Note that the nomenclature VR_ANTI_RANGE is being used in the > >> constructor to keep with the original API. It means "create the > >> inverse of this range". Ideally, when the m_kind field disappears > >> along with VR_ANTI_RANGEs, the enum could become RANGE_INVERSE or > >> something less confusing.) > >> > >> Finally, last_range is intersected with positives, which will become > >> whatever VR had, minus the last sub-range. > >> > >> Those that make sense, or did I miss something? > >> > >> If you have a testcase that yields a false positive in my proposed > >> patch, but not in the original code, please let me know so I can > >> adjust the patch. > > > > Sorry, I misremembered what get_size_range was used for. It's used > > to constrain the maximum size of memory accesses by functions like > > memcpy (the third argument). The use case I was thinking of was > > to determine the bounds of the size of variably modified objects > > (like VLAs). It doesn't look like it's used for that. > > > > With the current use taking the lower bound is the conservative > > thing to do and using the upper bound would cause false positives. > > With the latter it would be the other way around. So the comment > > makes sense to me now. > > > > As an aside, here's a test case I played with. I'd expect it to > > trigger a warning because the upper bound of the range of array's > > size is less than the lower bound of the range of the number of > > bytes being written to it. > > > > void f (void*); > > > > void g (unsigned n1, unsigned n2) > > { > > if (!(n1 >= 2 && n1 <= 3)) // n1 = [2, 3] > > return; > > > > char a[n1]; > > > > if (!((n2 >= 5 && n2 <= 10) > > || (n2 >= 20))) // n2 = [5, 10] U [20, UINT_MAX] > > return; > > > > __builtin_memset (a, 0, n2); > > f (a); > > } > > > > But I couldn't get it to either produce a multipart range, or > > a union of the two parts (i.e., [5, UINT_MAX]). It makes me > > wonder what I'm missing about how such ranges are supposed to > > come into existence. > > > > Martin > > > There mare a couple of things.. > > My guess is you are using a value_range? value_ranges are an > int_range<1> under the covers, so will never have more than a single > range, or anti range. > > int_range<X> is the type which allows for up to X subranges. > calculations will be merged to fit within X subranges > widest_irange is the type which allows for "unlimited" subranges... > which currently happens to be capped at 255.. . (its typedef'd as > int_range<255>). > > widest_irange is the type used within the range-ops machinery and such, > and then whatever result is calculated is "toned down" to whatever to > user provides. > > so if union results in [5,10] and [20, MAX] and you provide a > value_range for the result (, or int_range<1>), the result you get back > will be [5, MAX].. so won't look like there are any multi-ranges going on. > > and don't forget, EVRP only works with value_range, or int_range<1>. > You cant currently get these ranges without the Ranger either... which > is still on our branch. We're hoping to get moving into trunk in the > next couple of weeks. > I think Aldy is just trying to get the code functioning the same with > the new API, even if we cant get the more precise ranges yet. Then when > the ranger is added in, we switch you over and voila... multi-ranges. > > Andrew > >