Help with replacements on macros

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 into my_func(). 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 (1 | X) { 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);

then the source locations are as follows:

#define GUARD2 GUARD1(999)
#define GUARD1(X) if (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

Hi Scott,

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

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 into my_func(). 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 (1 | X) { 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);

then the source locations are as follows:

#define GUARD2 GUARD1(999)
#define GUARD1(X) if (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.

That’s what Lexer::makeFileCharRange solves - for a given range, it will give you the range on the same macro expansion level, if such a range exists.