Thanks for the input!
Tooling/Refactoring is definitely the right way to go - dumping to stdout was just a holdover from the example on LibTooling. I’ll change it once I figure out how it works - and a clean way to arrange the tests.
As for the use of matchers vs. visitors, I decided to use a visitor because this is a relatively complex transformation. I would happily use matchers if I thought I could - and I think that some other c++11 migrations can easily be written with matchers - but I think the for loop checks need some features that matchers don’t have (correct me if I’m wrong!). For example, the check for statically allocated array-based loops does this:
Given a for loop, determine if:
- The increment statement increments (via ++) exactly one integral index variable, such that the variable is declared and initialized to zero in the init portion of the loop, and that this variable’s value is a compared (via <, > or !=) to a nonnegative compile-time constant N in the compare portion.
- The index variable is only ever used in an ArrayIndexExpession indexing a single, statically allocated array A.
- The array A has exactly N elements.
- Additionally, if the ArrayIndexExpression A[index] is ever assigned, passed to a function or copied as a non-const reference, or its address taken with & (I still need to add a check for calls to non-const member functions), the loop variable in the converted version needs to be a non-const reference so that the value will be correctly updated (this step adds the most complexity).
The other types of loop (iterator-based, and array-like container) are more complicated to detect, since there are more permitted ways to define and use the index/iterators. What makes this difficult to do entirely with matchers is the number of back- and cross-references, as well as the different local behaviors based on semantic properties. On the other hand, if there were some kind of backreference-enabled matcher that allowed me to locate all matches in a given Stmt, it could be much easier to express some parts of the logic, such as the first step in the above list. I also suspect that a single-Stmt matcher would better way to handle the last step; currently I track whether the visitor is looking at a statement or expression which fits any of the const-disqualifying conditions, and a note is made if I run into A[index].
Does this make the use case clearer? I don’t really see a better way to approach this problem, but you guys know the available toolkit far better than I do.