0

I'm planning a bunch of refactorings on a large code base that I'd like to automate using Clang tooling. For this, I'm trying to write a Clang AST Matcher expression.

Specifically, I'm trying to match pairs of statements that I'd like to replace with something else, like

 a();      =>     a_and_b(x);
 b(x);

So I'm trying to match an a callExpr() followed by a b callExpr() (but could be any statement, really). I have constructed matchers for the first and the second statements, independently, let's call them aMatcher() and bMatcher() but haven't found how to combine them so that they match only if they're back-to-back, something like bMatcher(follows(aMatcher()). None of the existing matchers seems to be pertinent (looked for "next", "prev", "position", ...).

How do I go about this the correct way, please?

Marc Mutz - mmutz
  • 24,485
  • 12
  • 80
  • 90

1 Answers1

0

The implementation of UseAnyOfAllOfCheck contains a private nextStmt matcher:

/// Matches a Stmt whose parent is a CompoundStmt, and which is directly
/// followed by a Stmt matching the inner matcher.
AST_MATCHER_P(Stmt, nextStmt, ast_matchers::internal::Matcher<Stmt>,
              InnerMatcher) {
  DynTypedNodeList Parents = Finder->getASTContext().getParents(Node);
  if (Parents.size() != 1)
    return false;

  auto *C = Parents[0].get<CompoundStmt>();
  if (!C)
    return false;

  const auto *I = llvm::find(C->body(), &Node);
  assert(I != C->body_end() && "C is parent of Node");
  if (++I == C->body_end())
    return false; // Node is last statement.

  return InnerMatcher.matches(**I, Finder, Builder);
}

I don't know how robust that is, but I'll try to use it and report back.

Marc Mutz - mmutz
  • 24,485
  • 12
  • 80
  • 90