Clang AST Matchers:如何查找使用rvalues调用的完美转发函数的调用?

时间:2017-07-11 06:46:45

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

给出一个功能模板,例如:

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

如何找到传递rvalues的函数的调用:

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被推断为引用类型的情况(表示左值已通过),但我不知道如何连接Matcher<FunctionDecl>所期望的functionDecl 1}}到Matcher<TemplateSpecializationType>返回的hasTemplateArgument

我使用Clang 3.8,如果它很重要(online docs似乎是5.0.0,而http://releases.llvm.org/3.8.0/tools/clang/docs/LibASTMatchersReference.html给出了404)。

2 个答案:

答案 0 :(得分: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.

答案 1 :(得分:0)

这似乎有效:

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

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