0

我正在使用 clang ASTMatcher 来查找我的源代码中定义 isnan 的位置。我试图理解为什么有三个匹配项,尽管我限制只在主文件中匹配。请在下面找到示例源代码:

#include <math.h>
int main()
{
    if(isnan(0.0)){     
    }
}

当我进行 clang-query match 时,我得到以下输出:

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.

无论如何限制匹配只针对源代码而不是宏?

我将不胜感激任何帮助。

4

1 回答 1

1

在预处理过程中,宏被视为纯文本替换,这发生在所有匹配开始之前。快速 grep 到 math.h 给了我这个:

#  define isnan(x) \                                                   
     (sizeof (x) == sizeof (float)                \              
      ? __isnanf (x)                    \
      : sizeof (x) == sizeof (double)               \
      ? __isnan (x) : __isnanl (x))  

这就解释了为什么你会得到三个匹配的结果。在您运行 AST Matcher 之前,它们已经在您的 main 函数中。

获取单个位置,具体取决于您的源代码。在这种特殊情况下,您可以通过将节点匹配器更改为条件运算符来实现。

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.    

所以我试图匹配宏被替换后的 expr。

希望能帮助到你。

于 2018-05-04T15:09:31.930 回答