How to find macro arguments?

Hi all,

I'm trying to familiarize myself with clang and in particular its AST matchers.
Therefore, I tried to write some piece of code to determine if an expression
has been passed as an argument to a macro:

    auto& context = /* ASTContext */
    auto& SM = context.getSourceManager();
    auto loc = expr.getLocStart();

    if (SM.isMacroArgExpansion(loc)) {
        const auto expLoc = SM.getImmediateExpansionRange(loc).first;
        const auto name = Lexer::getImmediateMacroName(expLoc, SM, context.getLangOpts());
        if (name == "MACRO")
            return true;
    }

Given the following code:

#define MACRO(v) (v + 1) - 2

int test(int x)
{
    return MACRO(x);
}

it also returns true for the expression `x + 1' (BinaryOperator) within
the macro expansion, not just the DeclRefExpr `x' itself. Looks like both
expressions have the same location (I dumped its internal representation).
But why? And how can the 2 cases be distinguished? Or what am I missing here?
Thanks in advance for any pointers.

ciao,
Mario

Hi all,

I’m trying to familiarize myself with clang and in particular its AST matchers.
Therefore, I tried to write some piece of code to determine if an expression
has been passed as an argument to a macro:

auto& context = /* ASTContext */
auto& SM = context.getSourceManager();
auto loc = expr.getLocStart();

if (SM.isMacroArgExpansion(loc)) {
const auto expLoc = SM.getImmediateExpansionRange(loc).first;
const auto name = Lexer::getImmediateMacroName(expLoc, SM, context.getLangOpts());
if (name == “MACRO”)
return true;
}

Given the following code:

#define MACRO(v) (v + 1) - 2

int test(int x)
{
return MACRO(x);
}

it also returns true for the expression x + 1' (BinaryOperator) within the macro expansion, not just the DeclRefExpr x’ itself. Looks like both
expressions have the same location (I dumped its internal representation).
But why? And how can the 2 cases be distinguished? Or what am I missing here?
Thanks in advance for any pointers.

I’d expect that for the second case you’d have start and end location of the range in different expansions (which is generally where we’ll have to through our hands in the air and go home).
You can look at what getFileCharRange / getSourceText in Lexer:: does to make sure a range in a macro is fully on the same expansion level.

Hi Manuel,

thanks for the pointer. Meanwhile, I managed to complete the implementation.
You were right. I had to consider the entire range to distinguish the two cases:
The expression `x + 1' (BinaryOperator) has a starting location which is a
macro argument, but its end lies within the macro. For the DeclRefExpr `x' both
locations are considered a macro argument.

ciao,
Mario