【发布时间】:2019-05-06 21:59:50
【问题描述】:
我希望在 clang ast 匹配器的帮助下更改以下代码。
foo(NUM << DEV_SHIFT | DEVICE);
到
foo(ADDR(NUM, DEVICE));
与
#define ADDR(a, b) (((a) << NUM_SHIFT) | (b))
我有以下 AST 匹配器,似乎可以很好地识别代码。
Finder->addMatcher(
callExpr(hasArgument(
0, binaryOperator(hasOperatorName("|"),
hasLHS(ignoringParenImpCasts(
binaryOperator(hasOperatorName("<<")))))
.bind("replaceWithMacro"))),
this);
但是我在理解如何写支票和翻译时遇到了问题。我目前坚持使用此代码:
void FirstCheckCheck::check(const MatchFinder::MatchResult &Result) {
// FIXME: Add callback implementation.
if (const auto MatchedDecl =
Result.Nodes.getNodeAs<CallExpr>("replaceWithMacro")) {
diag(MatchedDecl->getExprLoc(), "CallExp");
} else if (const auto MatchedDecl =
Result.Nodes.getNodeAs<Expr>("replaceWithMacro")) {
diag(MatchedDecl->getExprLoc(), "Expr");
diag(MatchedDecl->getBeginLoc(), "BeginLOC");
diag(MatchedDecl->getEndLoc(), "EndLOC");
}
我不知道如何将这两个变量提取为字符串。 我正在查看 Expr 类 (http://clang.llvm.org/doxygen/classclang_1_1Expr.html) 的文档,但找不到有用的东西。
如果有人能指出我正确的方向,将不胜感激。
添加编辑。
【问题讨论】:
-
始终在扩展中的宏参数名称周围加上括号(在处理算术或逻辑表达式时)。因此:
#define ADDR(a, b) (((a) << NUM_SHIFT) | (b))。它可能不是您的问题的一个因素,但它是基本的 C 代码卫生。 (规则有例外,例如在处理字符串时,但在明智的情况下遵守准则 - 这是一个明智的地方。) -
在我看来,您正在尝试从 Expr 中提取两个变量。为什么不添加两个额外的绑定?您已经制定了匹配器,只需修改一下以绑定“
标签: c abstract-syntax-tree clang-ast-matchers