[Development] How to port from Q_FOREACH to range-based for

Konstantin Tokarev annulen at yandex.ru
Tue Jun 11 09:38:03 CEST 2019



10.06.2019, 14:48, "Giuseppe D'Angelo" <giuseppe.dangelo at kdab.com>:
> (Changing the subject to be on topic)
>
> On 10/06/2019 13:27, Konstantin Tokarev wrote:
>>>  At the cost of saying for the 100th time, before this stuff ends up
>>>  indexed by Google: you can port away from Q_FOREACH in an automated way
>>>  only in trivial cases.*NOT* in the general case.
>>  How is one supposed to port uses of Q_FOREACH in 1559 places then?
>
> I've wrote it below ↓
>
>>>  For the general case you've only got the 5 minutes solution (c&p&rename
>>>  Q_FOREACH into your codebase; assuming the worst case, of lack of
>>>  "Qt5Support" or so) or the long walk of checking all usages.
>
>>  What things should be checked during that "long walk", except aforemention measures
>>  to avoid detaching? If we cannot have porting tool, we need at least comprehensive
>>  porting guide (and if such guide is formalized, I'm pretty sure it will be possible to
>>  automate it, at least partially)
>
> For instance:
>
> * that in the body of the loop you're not mutating the container through
> the loop variable itself (before: it would affect a copy; now: it
> affects the original; solution: take a copy explicitly);
>
> * that in the body of the loop you're not mutating the container in a
> way that invalidates iterators (and/or possibly references into it).
>
> Here's the catch: from the body you may be calling a function which DOES
> the above mutations. For instance, you're in a member function,
> iterating over some container held as member variable, and from within
> the loop call another member function which mutates that container.
>
> Again, before someone says "who in their minds does this?", _Qt itself_
> did it.
>
> The conclusion is that either such a porting tool will be incomplete
> and/or incorrect:
>
> * it may give up as soon as it sees a non-local call (= 99.9% of the
> loops), making the tool incomplete (and probably useless);

I guess this can be mitigated by using whitelists, e.g. it's safe to assume that
standard C library functions, standard C++ classes, and data classes from
Qt which are not supposed to be inherited by user cannot modify that member
container behind the scenes. This should improve percentage and allow to do
at least some porting automatically.

>
> * or can do some escape/shape analysis to make it more useful, but still
> incomplete (who's going to implement this?);
>
> * or it can ignore the problem and refactor away, at the risk of
> introducing bugs (= incorrect).
>
> Complete and correct requires solving the halting problem.

Sounds like a task for run-time instrumentation. While it cannot be treated as
"correct" without 100% coverage, it's still a big improvement over static reasoning
and allows to prove that change is safe in the most common usage scenarios.
It should be safer than doing check only with naked eye. However, I have no idea
how complex can be such tool to develop (sounds very similar to coverage tools
though).

-- 
Regards,
Konstantin



More information about the Development mailing list