[cfe-dev] ASTMatcher for assert()

Alex Horn alex.horn at cs.ox.ac.uk
Tue Jun 3 08:36:09 PDT 2014


Hello,

I am struggling to replace "assert(c)" macro calls by "BAR(c)" where c
is some integer expression and BAR is a function.

The problem manifests itself in RefactoringTool::applyAllReplacements
which returns false, thereby causing the tool to skip replacements.

I am using the following ASTMatcher:

StatementMatcher makeAssertMatcher() {
  return callExpr(callee(functionDecl(hasName("__builtin_expect")))).bind("AssertBindId");
}

Note: callExpr(callee(functionDecl(hasName("assert"))) won't work here
because assert() is a macro according to the assert.h and cassert
headers.

Here's an example match using clang-query:

example.cpp:

  #include <assert.h>
  int main() {
    assert(false);
    return 0;
  }

$ clang-query> match callExpr(callee(functionDecl(hasName("__builtin_expect"))))

  Match #1:

  example.cpp:4:3: note: "AssertBindId" binds here
    assert(false);
    ^~~~~~~~~~~~~
  /usr/include/assert.h:93:6: note: expanded from macro 'assert'
      (__builtin_expect(!(e), 0) ? __assert_rtn(__func__, __FILE__,
__LINE__, #e) : (void)0)
       ^~~~~~~~~~~~~~~~~~~~~~~~~
  1 match.

But I cannot find the correct way to rewrite the match; the following
replacement is skipped (i.e. see line 295 in Refactoring.cpp):

  const CallExpr *E = Result.Nodes.getNodeAs<CallExpr>("AssertBindId");
  SourceManager &SM = *Result.SourceManager;
  SourceLocation LocBegin = E->getLocStart();
  Replace->insert(tooling::Replacement(SM, LocBegin,
    /* number of letters in assert */ 6, "BAR"));

What is the correct way (if any) to rewrite call expressions of macros
such as "assert()"?

Best,
Alex



More information about the cfe-dev mailing list