I am doing a clang ASTMatcher to find the locations where isnan is defined in my source code. I am trying to understand why there are three matches eventhough I have restricted to match only in the main file. Please find a sample source code below:
#include <math.h>
int main()
{
if(isnan(0.0)){
}
}
When I do clang-query match I am getting the below output:
clang-query> match declRefExpr(isExpansionInMainFile())
Match #1:
/home/clang-llvm/code/test.cpp:6:5: note: "root" binds here
if(isnan(0.0)){
^~~~~~~~~~
/usr/include/math.h:299:9: note: expanded from macro 'isnan'
? __isnanf (x) \
^~~~~~~~
Match #2:
/home/clang-llvm/code/test.cpp:6:5: note: "root" binds here
if(isnan(0.0)){
^~~~~~~~~~
/usr/include/math.h:301:9: note: expanded from macro 'isnan'
? __isnan (x) : __isnanl (x))
^~~~~~~
Match #3:
/home/clang-llvm/code/test.cpp:6:5: note: "root" binds here
if(isnan(0.0)){
^~~~~~~~~~
/usr/include/math.h:301:23: note: expanded from macro 'isnan'
? __isnan (x) : __isnanl (x))
^~~~~~~~
3 matches.
Is there anyway to restrict the match only for the source code and not the macro?
I would appreciate any help.
The macro is treated as pure text replacement during preprocessing, which happens before all your matching start. A quick grep into the math.h gives me this:
# define isnan(x) \
(sizeof (x) == sizeof (float) \
? __isnanf (x) \
: sizeof (x) == sizeof (double) \
? __isnan (x) : __isnanl (x))
This explains why you get three matching results. They are already in your main function before you run the AST Matcher.
To get a single location, depending on your source code. In this particular case, you can achieve by changing your node matcher to a conditional operator.
clang-query> match conditionalOperator(hasFalseExpression(conditionalOperator()), isExpansionInMainFile())
Match #1:
~/test.cpp:4:8: note: "root" binds here
if(isnan(0.0)){
^~~~~~~~~~
/usr/include/math.h:254:7: note: expanded from macro 'isnan'
(sizeof (x) == sizeof (float)
\
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 match.
So I am trying to match the expr that after the macro is replaced.
Hope it helps.