Hi,
I am quite new to clang AST matchers and wondering if you could help me with a match. I am writing a matcher to generate replacements.
Consider this,
SomeClientBuilder SCB(Foo& f) {
return SomeClientBuilder.setFoo(f);
}
class SomeClientBuilder {
Fruit apple(…);
Fruit pear(…);
};
I would like to change
“return SCB(foo).apple(req).get(…)”
to
“return SCB().pear(req).via(foo).get(…)”
I would like to create a matcher that:
matches SCB so it has 1 argument of type Foo
matches method named apple() and is a method in SomeClientBuilder
After many attempts, I came up with two matchers.
cxxMemberCallExpr(callee(cxxMethodDecl(hasName(“apple”), ofClass(cxxRecordDecl(hasName("SomeClientBuilder "))))))
this matcher does not restrict SCB to have 1 argument of type Foo
callExpr(callee(functionDecl(hasName(“SCB”))), argumentCountIs(1), hasArgument(0, hasType(cxxRecordDecl(hasName(“Foo”)))))
this matcher does not match the “apple()” methods
I have tried combining the matchers together with no success. What do you think would be the best way to accomplish what I want to do?
Thanks,
David Lai
r4nt
March 28, 2018, 8:55am
2
Hi,
I am quite new to clang AST matchers and wondering if you could help me with a match. I am writing a matcher to generate replacements.
Consider this,
SomeClientBuilder SCB(Foo& f) {
return SomeClientBuilder.setFoo(f);
}
class SomeClientBuilder {
Fruit apple(…);
Fruit pear(…);
};
I would like to change
“return SCB(foo).apple(req).get(…)”
to
“return SCB().pear(req).via(foo).get(…)”
I would like to create a matcher that:
matches SCB so it has 1 argument of type Foo
matches method named apple() and is a method in SomeClientBuilder
After many attempts, I came up with two matchers.
cxxMemberCallExpr(callee(cxxMethodDecl(hasName(“apple”), ofClass(cxxRecordDecl(hasName("SomeClientBuilder "))))))
this matcher does not restrict SCB to have 1 argument of type Foo
You should be able to compine this with the “on” matcher for cxxMemberCallExpr.
See http://clang.llvm.org/docs/LibASTMatchersReference.html
on() takes an expr matcher as argument, with which you can match the nested call expr.
Hi,
Thanks for your help! I was able to write the matcher with nested “on” statements.
However, I am having trouble correctly retrieving the argument “foo” in SCB. Right now, I am retrieving it like:
std::string Buffer;
llvm::raw_string_ostream Stream(Buffer);
callArg->getArg(0)->prettyPrint(Stream, nullptr, result.Context->getPrintingPolicy())
and printing Stream.str() gives me “this->foo”, whereas I want to retrieve “foo” by itself. I have tried using the different Ignore functions (IgnoreCasts, IgnoreImplicit, etc), but none of them have worked.
Ultimately, I want to write a replacement like:
Replacements.emplace(source_manager,
CharSourceRange::getCharRange(call->getExprLoc(),
Lexer::getLocForEndOfToken(call->getExprLoc(), 0, source_manager, context.getLangOpts()),
“via(“ + argument + “).get”);
where argument is “foo”. Furthermore, using prettyPrint function for this seems kind of hacky as well, what is the proper way to retrieve the argument name?
Thanks,
David Lai