[cfe-dev] ASTMatcher for assert()

Alex Horn alex.horn at cs.ox.ac.uk
Fri Jun 6 07:10:54 PDT 2014


Thanks for the effective response. This helped on the right track and
I've successfully used SourceManager::getImmediateExpansionRange() to
insert BAR and its surrounding parenthesis correctly.

As a directly related issue: The proposed technique of using the
expansion range does the trick but of course requires that "-cc1
-rewrite-macros" is _not_ invoked prior to rewriting "assert()"
macros. However, this is problematic when other rewrites in the same
RefactoringTool _do_ rely on macros having been rewritten. This poses
the question whether these things can coexist in the same
RefactoringTool. In particular, is it possible to call the
RewriteMacros functionality only after certain matches have completed?

To ask the same thing differently, what is the preferred way to
compose ASTMatchers and cc1 drivers such as RewriteMacros?

On 6 June 2014 13:56, Manuel Klimek <klimek at google.com> wrote:
> On Tue, Jun 3, 2014 at 5:36 PM, Alex Horn <alex.horn at cs.ox.ac.uk> wrote:
>>
>> 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()"?
>
>
> You need to get the expansion location:
> SourceLocation ExpLocBegin = SM.getExpansionLoc(LocBegin);
> Replace->insert(tooling::Replacement(SM, ExpLocBegin, 6, "BAR"));
>
> Something like this should do the trick...
> Cheers,
> /Manuel



More information about the cfe-dev mailing list