如何使用Clang AST匹配器将通用引用参数匹配到成员函数



我正在尝试匹配传递给模板化成员函数调用的参数,使用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节点。

相关内容

  • 没有找到相关文章

最新更新