Clang AST Matchers:如何找到调用rvalues调用的完美转发函数的调用?
问题描述:
给出一个函数模板,如:Clang AST Matchers:如何找到调用rvalues调用的完美转发函数的调用?
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
推导为引用类型(指示左值传递)的情况下,但我不知道怎样才能连接Matcher<FunctionDecl>
预计由functionDecl
到Matcher<TemplateSpecializationType>
从hasTemplateArgument
返回。
我使用的是Clang 3.8,万一它很重要(online docs似乎在5.0.0,http://releases.llvm.org/3.8.0/tools/clang/docs/LibASTMatchersReference.html给出了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);
}
铛查询显示,匹配第一(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”超载的情况下,这也是有效的。 –