使用 Clang AST 访问者匹配传递给 ForStmt 的 Cond 中的函数的参数 [英] Matching the argument passed to a function in a ForStmt's Cond using Clang AST Visitors

查看:23
本文介绍了使用 Clang AST 访问者匹配传递给 ForStmt 的 Cond 中的函数的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图匹配传递给 ForStmt 条件的整数值.但是,loopbound 是对 FunctionDecl 的调用,而我似乎没有通过 ParamVarDecl 得到这个.

I am trying to match the value of an integer passed to a ForStmt's condition. However, the loopbound is a call to a FunctionDecl and I don't seem to get this with ParamVarDecl.

MWE:我的测试示例:

MWE: My Test Example:

void testASTVistor (int N) {
  N = 123;
  for (int i = 0; i <= GetBoundFunc(N), i++ ){
    //do Sth;
  }  
}

这是 AST 转储:

FunctionDecl 0x5602066f0db8 <FOO.cpp:XXX:XXX> col:X implicit used GetBoundFunc 'unsigned short (unsigned short) noexcept' extern
|-ParmVarDecl 0x5602066f0e50 <<invalid sloc>> <invalid sloc> 'unsigned short'
|-NoThrowAttr 0x5602066f0eb8 <col:X> Implicit
|-ConstAttr 0x5602066f0ef8 <col:X> Implicit
`-Attr 0x5602066f0f08 <col:X> Implicit

ASTRecursiveVisitor:

ASTRecursiveVisitor:

class BinaryVisitor : public clang::RecursiveASTVisitor<BinaryVisitor> {
public:
  bool VisitBinaryOperator(clang::BinaryOperator *BO) {
  
      if (const CallExpr *RHS = dyn_cast<CallExpr>(BO->getRHS()->IgnoreParenImpCasts())) {
        if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(RHS->getDirectCallee())) {
          if (FD->getNameAsString().std::string::find("GetBoundFunc") != std::string::npos) {       
            if (const ParmVarDecl *Bound = dyn_cast<ParmVarDecl>(FD->getParamDecl(0))) {

    return true;
            }
          }
        }
};

/// ...
BinaryVisitor visitor;
visitor.TraverseDecl(someDecl);

我不确定为什么 Bound 在此处作为 Null 指针返回.我已经调试了代码直到之前的 IfStmt 并且它们似乎工作.任何帮助将不胜感激.

I am not sure why Bound is returned as a Null pointer here. I have debugged the code up until the previous IfStmt and they seems to work. Any help would be appreciated.

推荐答案

首先,示例代码中似乎有几个错别字 (n = 123, i <= myBoundFunc(N), i++).

First of all, there seems to be a couple of typos in the sample code (n = 123, i <= myBoundFunc(N), i++).

无论如何,了解 AST 发生了什么的最简单方法是转储 AST.假设这是测试程序:

Anyhow, the easiest way to understand what is going on with the AST is to dump AST. Assuming this is the test program:

int myBoundFunc(int);

void testASTVistor (int N) {
  N = 123;
  for (int i = 0; i <= myBoundFunc(N); i++ ){
    //do Sth;
  }
}

您可以要求 Clang 转储 AST:

You can ask Clang to dump the AST:

clang -cc1 -ast-dump test.c

您将获得以下输出:

TranslationUnitDecl 0x7fd77b024408 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x7fd77b024ca0 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x7fd77b0249a0 '__int128'
|-TypedefDecl 0x7fd77b024d10 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x7fd77b0249c0 'unsigned __int128'
|-TypedefDecl 0x7fd77b024ff8 <<invalid sloc>> <invalid sloc> implicit __NSConstantString 'struct __NSConstantString_tag'
| `-RecordType 0x7fd77b024df0 'struct __NSConstantString_tag'
|   `-Record 0x7fd77b024d68 '__NSConstantString_tag'
|-TypedefDecl 0x7fd77b025090 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x7fd77b025050 'char *'
|   `-BuiltinType 0x7fd77b0244a0 'char'
|-TypedefDecl 0x7fd77b025368 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]'
| `-ConstantArrayType 0x7fd77b025310 'struct __va_list_tag [1]' 1
|   `-RecordType 0x7fd77b025170 'struct __va_list_tag'
|     `-Record 0x7fd77b0250e8 '__va_list_tag'
|-FunctionDecl 0x7fd77b0158d0 <test.c:1:1, col:20> col:5 used myBoundFunc 'int (int)'
| `-ParmVarDecl 0x7fd77b015800 <col:17> col:20 'int'
`-FunctionDecl 0x7fd77b015a98 <line:3:1, line:8:1> line:3:6 testASTVistor 'void (int)'
  |-ParmVarDecl 0x7fd77b0159d8 <col:21, col:25> col:25 used N 'int'
  `-CompoundStmt 0x7fd77b015df8 <col:28, line:8:1>
    |-BinaryOperator 0x7fd77b015b80 <line:4:3, col:7> 'int' '='
    | |-DeclRefExpr 0x7fd77b015b40 <col:3> 'int' lvalue ParmVar 0x7fd77b0159d8 'N' 'int'
    | `-IntegerLiteral 0x7fd77b015b60 <col:7> 'int' 123
    `-ForStmt 0x7fd77b015dc0 <line:5:3, line:7:3>
      |-DeclStmt 0x7fd77b015c40 <line:5:8, col:17>
      | `-VarDecl 0x7fd77b015bb8 <col:8, col:16> col:12 used i 'int' cinit
      |   `-IntegerLiteral 0x7fd77b015c20 <col:16> 'int' 0
      |-<<<NULL>>>
      |-BinaryOperator 0x7fd77b015d58 <col:19, col:37> 'int' '<='
      | |-ImplicitCastExpr 0x7fd77b015d40 <col:19> 'int' <LValueToRValue>
      | | `-DeclRefExpr 0x7fd77b015c58 <col:19> 'int' lvalue Var 0x7fd77b015bb8 'i' 'int'
      | `-CallExpr 0x7fd77b015d00 <col:24, col:37> 'int'
      |   |-ImplicitCastExpr 0x7fd77b015ce8 <col:24> 'int (*)(int)' <FunctionToPointerDecay>
      |   | `-DeclRefExpr 0x7fd77b015c78 <col:24> 'int (int)' Function 0x7fd77b0158d0 'myBoundFunc' 'int (int)'
      |   `-ImplicitCastExpr 0x7fd77b015d28 <col:36> 'int' <LValueToRValue>
      |     `-DeclRefExpr 0x7fd77b015c98 <col:36> 'int' lvalue ParmVar 0x7fd77b0159d8 'N' 'int'
      |-UnaryOperator 0x7fd77b015d98 <col:40, col:41> 'int' postfix '++'
      | `-DeclRefExpr 0x7fd77b015d78 <col:40> 'int' lvalue Var 0x7fd77b015bb8 'i' 'int'
      `-CompoundStmt 0x7fd77b015db0 <col:45, line:7:3>

如果我回答对了你的问题,那么你正在寻找以下片段:

And if I get your question right, then you are looking for the following snippet:

  | `-CallExpr 0x7fd77b015d00 <col:24, col:37> 'int'
  |   |-ImplicitCastExpr 0x7fd77b015ce8 <col:24> 'int (*)(int)' <FunctionToPointerDecay>
  |   | `-DeclRefExpr 0x7fd77b015c78 <col:24> 'int (int)' Function 0x7fd77b0158d0 'myBoundFunc' 'int (int)'
  |   `-ImplicitCastExpr 0x7fd77b015d28 <col:36> 'int' <LValueToRValue>
  |     `-DeclRefExpr 0x7fd77b015c98 <col:36> 'int' lvalue ParmVar 0x7fd77b0159d8 'N'

在这种情况下,您不需要 FunctionDecl,而是可以通过 RHS->getArg(0) 获取 CallExpr 的第一个参数) 并将其转换为 DeclRefExpr 并进行进一步检查以获得所需的值.

In which case you don't need the FunctionDecl, but instead you can get the first arg of the CallExpr via RHS->getArg(0) and cast it to the DeclRefExpr and do the further checks to get to the value you need.

FunctionDecl::getParamDecl 返回 NULL 开始,很难说没有看到 myBoundFunc 声明.

As of the FunctionDecl::getParamDecl returning NULL it is hard to say without seeing the myBoundFunc declaration.

这篇关于使用 Clang AST 访问者匹配传递给 ForStmt 的 Cond 中的函数的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆