C++ Clang AST Matchers:如何找到对使用右值调用的完美转发函数的调用?

C++ Clang AST Matchers:如何找到对使用右值调用的完美转发函数的调用?,c++,clang,abstract-syntax-tree,perfect-forwarding,clang-ast-matchers,C++,Clang,Abstract Syntax Tree,Perfect Forwarding,Clang Ast Matchers,给定一个函数模板,例如: template <typename T> void function(T &&t) { /*...*/ } 你明白了 我在想这样的事情: callExpr(callee(functionDecl( hasName("function"), unless(hasTemplateArgument(0, refersT

给定一个函数模板,例如:

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

我在想这样的事情:

callExpr(callee(functionDecl(
                    hasName("function"),
                    unless(hasTemplateArgument(0,
                        refersToType(references(anything()))))))
要过滤掉将
T
推断为引用类型(表示传递了左值)的情况,但我不知道如何将
functionDecl
期望的
匹配器连接到从
hasTemplateArgument
返回的
匹配器

我使用的是Clang 3.8,以防万一(似乎是5.0.0,并给出了404)。

这似乎有效:

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

尽管我确信它遗漏了一些场景。

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

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);
}
template void g(T&&T){
模板空g(T&T){}
void g(){
int i=2;
g(i);
g(2);
}
clang查询显示匹配器匹配第一个(rval)调用,而不是第二个(lval):

匹配#1:
test\u input\u rval\u call.cc:1:23:注意:“fdecl”在这里绑定
模板void g(T&&T){}
^~~~~~~~~~~~~~~
test\u input\u rval\u call.cc:1:30:注意:“pdecl”在这里绑定
模板void g(T&&T){}
^~~~~
test\u input\u rval\u call.cc:8:3:注意:“root”绑定在这里
g(2);
^~~~~~~~~
1场比赛。

谢谢。即使在没有第二个
g
过载的情况下,这种方法也能工作。
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);
}
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.