Reputation: 25293
Given a function template such as:
template <typename T> void function(T &&t) { /*...*/ }
how do I find calls to the function that pass rvalues:
function(1); // MATCH
int i;
function(i); // SKIP
int foo();
function(foo()); // MATCH
...
You get the idea.
I was thinking about something like:
callExpr(callee(functionDecl(
hasName("function"),
unless(hasTemplateArgument(0,
refersToType(references(anything()))))))
to filter out the case where T
is deduced as a reference type (indicating an lvalue was passed), but I don't see how I can connect the Matcher<FunctionDecl>
expected by functionDecl
to the Matcher<TemplateSpecializationType>
returned from hasTemplateArgument
.
I'm using Clang 3.8, in case it matters (the online docs seem to be at 5.0.0, and http://releases.llvm.org/3.8.0/tools/clang/docs/LibASTMatchersReference.html gives a 404).
Upvotes: 1
Views: 2262
Reputation: 1111
Here's a slightly different approach that interrogates the type of the parameter:
callExpr(
callee(
functionDecl( // could also narrow on name, param count etc
hasAnyParameter( // could also use hasParameter(n,...)
parmVarDecl(
hasType(
rValueReferenceType()
)
).bind("pdecl")
)
).bind("fdecl")
)
)
On this test code:
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 shows that the matcher matches the first (rval) call, and not the second (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.
Upvotes: 1
Reputation: 25293
This appears to work:
callExpr(hasDeclaration(functionDecl(hasName("function"))),
hasArgument(0, cxxBindTemporaryExpr()))
though I'm sure it misses some scenarios.
Upvotes: 0