【问题标题】:Clang AST Matchers: How to find calls to a perfectly forwarding function called with rvalues?Clang AST Matchers:如何找到对使用右值调用的完美转发函数的调用?
【发布时间】:2017-07-11 06:46:44
【问题描述】:

给定一个函数模板如:

template <typename T> void function(T &&t) { /*...*/ }

如何找到对传递右值的函数的调用:

function(1); // MATCH
int i;
function(i); // SKIP
int foo();
function(foo()); // MATCH
...

你明白了。

我在想这样的事情:

callExpr(callee(functionDecl(
                    hasName("function"),
                    unless(hasTemplateArgument(0,
                        refersToType(references(anything()))))))

过滤出T 被推断为引用类型的情况(表示传递了一个左值),但我不知道如何将functionDecl 预期的Matcher&lt;FunctionDecl&gt; 连接到Matcher&lt;TemplateSpecializationType&gt;hasTemplateArgument返回。

我正在使用 Clang 3.8,以防万一(online docs 似乎是 5.0.0,http://releases.llvm.org/3.8.0/tools/clang/docs/LibASTMatchersReference.html 给出 404)。

【问题讨论】:

    标签: c++ clang abstract-syntax-tree perfect-forwarding clang-ast-matchers


    【解决方案1】:

    这里有一个稍微不同的方法来询问参数的类型:

    callExpr(
      callee(
        functionDecl(           // could also narrow on name, param count etc
          hasAnyParameter(      // could also use hasParameter(n,...)
            parmVarDecl(
              hasType(
                rValueReferenceType()
              )
            ).bind("pdecl")
          ) 
        ).bind("fdecl")
      )
    )
    

    关于这个测试代码:

    template <typename T> void g(T &&t){}
    
    template <typename T> void g(T &t){}
    
    void g(){
      int i = 2;
      g<int>(i);
      g<int>(2);
    }
    

    clang-query 显示匹配器匹配第一个 (rval) 调用,而不是第二个 (lval):

    Match #1:
    
    test_input_rval_call.cc:1:23: note: "fdecl" binds here
    template <typename T> void g(T &&t){}
                          ^~~~~~~~~~~~~~~
    test_input_rval_call.cc:1:30: note: "pdecl" binds here
    template <typename T> void g(T &&t){}
                                 ^~~~~
    test_input_rval_call.cc:8:3: note: "root" binds here
      g<int>(2);
      ^~~~~~~~~
    1 match.
    

    【讨论】:

    • 谢谢。即使没有第二个 g 过载,这也有效。
    【解决方案2】:

    这似乎有效:

    callExpr(hasDeclaration(functionDecl(hasName("function"))),
             hasArgument(0, cxxBindTemporaryExpr()))
    

    虽然我确信它错过了一些场景。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-05
      • 2016-01-01
      • 2016-08-23
      相关资源
      最近更新 更多