[cfe-dev] Help with replacements on macros
Vedant Kumar via cfe-dev
cfe-dev at lists.llvm.org
Tue Jul 12 17:32:19 PDT 2016
Hi Scott,
> On Jun 29, 2016, at 10:02 PM, scott constable via cfe-dev <cfe-dev at lists.llvm.org> wrote:
>
> Hi All,
>
> I have an AST matcher which has successfully matched all "if" statements in a large program:
>
> StatementMatcher CondMatcher = ifStmt(hasCondition(expr().bind("condition")));
>
> My goal is to use libtooling replacements to refactor all "if" conditions <cond> into my_func(<cond>). For instance,
>
> if (true) { ... }
>
> should refactor to
>
> if (my_func(true)) { ... }
>
> The only time I run into trouble is when I try to refactor complex macros. For instance, take the following code:
>
> #define GUARD2 GUARD1(999)
> #define GUARD1(X) if (1 | X) { return 11; }
>
> int main() {
> GUARD2
> return 0;
> }
>
> My AST matcher successfully grabs the expanded if statement's condition. To perform my replacement, I would like to obtain the following source locations:
>
> #define GUARD2 GUARD1(999)
> #define GUARD1(X) if (<LBegin>1 | X<LEnd>) { return 11; }
>
> int main() {
> GUARD2
> return 0;
> }
>
> but if I do something like
>
> SourceLocation LBegin = MySourceManager.getSpellingLoc(Condition->getBeginLoc());
> SourceLocation LEnd = MySourceManager.getSpellingLoc(Condition->getEndLoc());
> LEnd = Lexer::getLocForEndOfToken(LEnd, 0, MySourceManager, opts);
There are some routines in lib/CodeGen/CoverageMappingGen.cpp which may help
with this.
You should be able to get the spelling location of the start of the conditional
by calling SM.getImmediateExpansionRange() in a loop. That's what the
"getStart(Stmt *)" method does.
There's a matching "getEnd(Stmt *)" routine which gets the precise end
location. It works by using a similar loop to find the location corresponding
to the last token in the statement, and then adding that token length to the
end location.
best,
vedant
> then the source locations are as follows:
>
> #define GUARD2 GUARD1(999<LEnd>)
> #define GUARD1(X) if (<LBegin>1 | X) { return 11; }
>
> int main() {
> GUARD2
> return 0;
> }
>
> And thus the replacements turn out as
>
> 1 #define GUARD2 GUARD1(999))
> 2 #define GUARD1(X) if (my_func(1 | X) { return 11; }
> 3
> 4 int main() {
> 5 GUARD2
> 6 return 0;
> 7 }
>
> which is incorrect. Note the extra parenthesis in line 1, and missing parenthesis in line 2. Any help at all would be very much appreciated.
>
> Thanks in advance,
>
> Scott Constable
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
More information about the cfe-dev
mailing list