[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