我正在尝试匹配传递给模板化成员函数调用的参数,使用clang查询作为编写clang整洁检查的前兆。虽然我可以让非模板成员函数匹配,但我无法让模板成员函数与匹配。我使用的是clang-14.0。
考虑:
#include <string>
class BaseTrace {
public:
template <typename... Args>
void Templated(const char *fmt, Args &&...args) {
}
void NotTemplated(const char *fmt, const char *s1, const char *s2) {
}
};
BaseTrace TRACE;
void trace1(const std::string &s1, const std::string &s2)
{
TRACE.Templated("One:{} Two:{}n", s1.c_str(), s2.c_str());
}
void trace2(const std::string &s1, const std::string &s2)
{
TRACE.NotTemplated("One:{} Two:{}n", s1.c_str(), s2.c_str());
}
查询正常成员调用函数是否与预期匹配:
clang-query> match match cxxMemberCallExpr(callee(functionDecl(hasName("NotTemplated"))), on(expr(hasType(cxxRecordDecl(hasName("::BaseTrace"))))), hasAnyArgument(cxxMemberCallExpr()))
Match #1:
/home/mac/git/llvm-project/build/../clang-tools-extra/test/clang-tidy/checkers/minimal-cstr.cpp:23:3: note: "root" binds here
TRACE.NotTemplated("One:{} Two:{}n", s1.c_str(), s2.c_str());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 match.
但是查询模板化的成员函数调用并不能:
clang-query> match match cxxMemberCallExpr(callee(functionDecl(hasName("Templated"), isTemplateInstantiation())), on(expr(hasType(cxxRecordDecl(hasName("::BaseTrace"))))), hasAnyArgument(cxxMemberCallExpr()))
0 matches.
这个问题的答案意味着这应该奏效。如果我不尝试匹配这些论点,那么我就可以得到匹配:
clang-query> match cxxMemberCallExpr(callee(functionDecl(hasName("Templated"), isTemplateInstantiation())), on(anyOf(expr(hasType(cxxRecordDecl(hasName("::BaseTrace")))), expr(hasType(cxxRecordDecl(isDerivedFrom("::BaseTrace")))))))
Match #1:
/home/mac/git/llvm-project/build/../clang-tools-extra/test/clang-tidy/checkers/minimal-cstr.cpp:16:3: note: "root" binds here
TRACE.Templated("One:{} Two:{}n", s1.c_str(), s2.c_str());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 match.
在匹配非成员函数时,我似乎没有同样的问题。
我是错过了什么,还是这可能是一个叮当作响的限制。
我不相信我已经彻底了解了这一点,但似乎我可以通过使用以下任意一种方法来匹配Templated
方法:
clang-query> set traversal IgnoreUnlessSpelledInSource
而不是问题中匹配表达式的AsIs
默认值,或者通过将匹配表达式修改为:
clang-query> match cxxMemberCallExpr(callee(functionDecl(hasName("Templated"), isTemplateInstantiation())), on(expr(hasType(cxxRecordDecl(hasName("::BaseTrace"))))), hasAnyArgument(materializeTemporaryExpr(has(cxxMemberCallExpr()))))
以匹配语法树中的额外CCD_ 3节点。