Clang AST Matcher - Matching nested function and method calls

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.

  1. cxxMemberCallExpr(callee(cxxMethodDecl(hasName(“apple”), ofClass(cxxRecordDecl(hasName("SomeClientBuilder "))))))
  • this matcher does not restrict SCB to have 1 argument of type Foo
  1. 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

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.

  1. 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