1

給出一個函數模板,如: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>預計由functionDeclMatcher<TemplateSpecializationType>hasTemplateArgument返回。

我使用的是Clang 3.8,萬一它很重要(online docs似乎在5.0.0,http://releases.llvm.org/3.8.0/tools/clang/docs/LibASTMatchersReference.html給出了404)。

回答

0

這似乎工作:

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

但我敢肯定它錯過了一些場景。

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); 
} 

鐺查詢顯示,匹配第一(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. 
+0

謝謝。即使在沒有第二個「g」超載的情況下,這也是有效的。 –