添加检查¶
在使用 clang-query 完成匹配器后,是时候将其提升到下一步,将其转换为 C++ 并将其运行在整个 m-c 代码库上,看看会发生什么。
Clang 插件位于 build/clang-plugin,在这里我们将介绍添加插件所需的步骤。要了解最近一次检查是如何添加的,您可以查看 Checks.inc 的日志,这是需要编辑的文件之一。这也是我们接下来要介绍的内容。
添加新检查的样板步骤¶
首先选择一个名称。选择一个有意义的名称,不使用标点符号,最多 8 个单词左右。在本例中,我们将它命名为“枚举比较缺少 Else”。
在 build/clang-plugin/Checks.inc、ChecksIncludes.inc 和 moz.build 中按字母顺序添加它。
cd build/clang-plugin && touch MissingElseInEnumComparisons.h MissingElseInEnumComparisons.cpp
复制现有简单 .h 文件(例如 build/clang-plugin/ScopeChecker.h)的内容,并编辑类名和头文件保护。
为您的实现创建以下样板代码
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MissingElseInEnumComparisons.h"
#include "CustomMatchers.h"
void MissingElseInEnumComparisons::registerMatchers(MatchFinder *AstMatcher) {
}
void MissingElseInEnumComparisons::check(const MatchFinder::MatchResult &Result) {
}
将您的匹配器转换为 C++¶
在完成样板代码后,现在我们可以专注于将匹配器转换为 C++。一旦它在 C++ 中,您还可以利用一些技巧,使您的匹配器更容易阅读和理解。
转换匹配器的要点是采用以下伪代码,并将您的整个匹配器粘贴到“foo”所在的位置;保留 .bind(“node”)。
AstMatcher->addMatcher(
traverse(TK_IgnoreUnlessSpelledInSource,
foo
.bind("node")),
this);
老实说,通常就这么简单。这是一个有效的示例,我直接从 Compiler Explorer 粘贴过来的
AstMatcher->addMatcher(
traverse(TK_IgnoreUnlessSpelledInSource,
ifStmt(allOf(
has(
binaryOperator(
has(
declRefExpr(hasType(enumDecl().bind("enum")))
)
)
),
hasElse(
ifStmt(allOf(
unless(hasElse(anything())),
has(
binaryOperator(
has(
declRefExpr(hasType(enumDecl()))
)
)
)
))
)
))
.bind("node")),
this);
如果由于某种原因您没有使用 IgnoreUnlessSpelledInSource
遍历模式,请删除对 traverse 的调用以及相应的右括号。(此外,如果您将此代码与现有源代码进行比较,请注意,由于此遍历模式是 clang 的新功能,大多数历史 clang 检查都没有使用它。)
连接警告和错误¶
要开始使用一些简单的输出,只需获取此处的样板警告并将其粘贴进去即可
const auto *MatchedDecl = Result.Nodes.getNodeAs<IfStmt>("node");
diag(MatchedDecl->getIfLoc(),
"Enum comparisons in an if/else if block without a trailing else.",
DiagnosticIDs::Warning);
您需要修改两件事
确保“node”与您在上面 .bind() 中输入的内容匹配。
getNodeAs<IfStmt>
需要更改为“node”的元素类型。在上面,我们将“node”绑定到一个 IfStmt,所以我们需要将其转换为该类型。如果错误地执行此步骤,会导致 clang 在编译期间崩溃,就像出现了一些内部编译器错误一样。
在 Central 上运行¶
接下来,需要在您的 .mozconfig 中添加 ac_add_options --enable-clang-plugin
并进行构建。您的插件将自动编译并在整个代码库中使用。我建议使用 ./mach build | tee output.txt
,然后 grep "Enum comparisons" output.txt | cut -d " " -f 3- | sort | uniq
。(cut
用于去除行中的时间戳。)