[cfe-dev] ASTMatcher for assert()

Manuel Klimek klimek at google.com
Fri Jun 6 07:13:28 PDT 2014


On Fri, Jun 6, 2014 at 4:10 PM, Alex Horn <alex.horn at cs.ox.ac.uk> wrote:

> 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?
>

I wouldn't combine them. Why not write all tools to work on the
non-macro-rewritten code? (you can get macros yourself via the PPCallbacks
interface).


>
> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140606/77b90899/attachment.html>


More information about the cfe-dev mailing list