clangclang-tidylibtooling

clang libtooling: how to get expansion EndLoc of function-like macros?


I am writing a module of clang-tidy, which finds declarations of variables with the necessary condition and perform FixItHint:CreateReplacement() for them.

I found VarDecl, which defined via a strange function macro that ignores its arguments. Need to delete the entire macro text to perform the substitution of new text. The problem is that I can not get the source location, which would point outside the parentheses of this macro. Example is below.

#define VAR_DECL(type, name) float other_name;

    VAR_DECL(int, test)
//  |      |           \__ How can i get this SourceLocation?
//  |      \__ VarDecl->getEndLoc()
//  \__ VarDecl->getBeginLoc()

int main(void) { return 0; }

The output of clang-query looks like:

Match #1:

Binding for "root":
VarDecl 0x59d487e8f330 <stck.c:1:30, col:36> col:36 other_name 'float'

1 match.

I tried to find the necessary functions in SourceManager, Lexer and Preprocessor classes but couldn't find anything suitable.


Solution

  • The thing i was looking for is getExpansionRange(), whose description states: Given a SourceLocation object, return the range of tokens covered by the expansion in the ultimate file.

    My resulting code looks like:

    begin_loc = var_decl->getBeginLoc().isMacroID() ?
        sm.getExpansionRange(var_decl->getBeginLoc()).getBegin() :
        sm.getExpansionLoc(var_decl->getBeginLoc());
    
    end_loc = var_decl->getEndLoc().isMacroID() ?
        sm.getExpansionRange(var_decl->getEndLoc()).getEnd() :
        sm.getExpansionLoc(var_decl->getEndLoc());