Я пишу свой первый AST Matcher для обнаружения преобразования указателя в целое, но размер BoundedNodes
в MatchResult
равен 0. Как это возможно? Почему AST Matcher вызывает мой обратный вызов даже с пустым MatchResult? Возможно ли, чтобы фрагмент кода соответствовал определенному Matcher, не отображаясь как узел в AST?
Это весь мой код:
class PtoICallback : public clang::ast_matchers::MatchFinder::MatchCallback {
clang::Rewriter rewriter;
public:
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult& result) override final {
llvm::outs() << result.Nodes.getMap().size() << " nodes matched\n";
}
};
int main(int argc, const char** argv) {
llvm::cl::OptionCategory findPtoICategory("find-ptoi options");
clang::tooling::CommonOptionsParser options(argc, argv, findPtoICategory);
clang::tooling::ClangTool tool(options.getCompilations(), options.getSourcePathList());
auto matcher = clang::ast_matchers::castExpr(clang::ast_matchers::hasCastKind(clang::CastKind::CK_PointerToIntegral));
PtoICallback callback;
clang::ast_matchers::MatchFinder finder;
finder.addMatcher(matcher, &callback);
return tool.run(clang::tooling::newFrontendActionFactory(&finder).get());
}
Это выводит
0 nodes matched
при вызове файла, который содержит 1 указатель на интегральное преобразование:
#include <stdint.h>
int main() {
int i = 0;
intptr_t a = reinterpret_cast<intptr_t>(&i);
return 0;
}
Опять же, я не понимаю, почему совпадение будет обнаружено, но узел не будет найден? Если я дамп AST для приведенного выше кода, он дает:
`-FunctionDecl 0x55765ad54520 <example.cpp:5:1, line:9:1> line:5:5 main 'int ()'
`-CompoundStmt 0x55765ad62010 <col:12, line:9:1>
|-DeclStmt 0x55765ad61e40 <line:6:5, col:14>
| `-VarDecl 0x55765ad54648 <col:5, col:13> col:9 used i 'int' cinit
| `-IntegerLiteral 0x55765ad61e20 <col:13> 'int' 0
|-DeclStmt 0x55765ad61fc8 <line:7:5, col:48>
| `-VarDecl 0x55765ad61e90 <col:5, col:47> col:14 a 'intptr_t':'long' cinit
| `-CXXReinterpretCastExpr 0x55765ad61f98 <col:18, col:47> 'intptr_t':'long' reinterpret_cast<intptr_t> <PointerToIntegral>
| `-UnaryOperator 0x55765ad61f48 <col:45, col:46> 'int *' prefix '&' cannot overflow
| `-DeclRefExpr 0x55765ad61ef8 <col:46> 'int' lvalue Var 0x55765ad54648 'i' 'int'
`-ReturnStmt 0x55765ad62000 <line:8:5, col:12>
`-IntegerLiteral 0x55765ad61fe0 <col:12> 'int' 0
Итак, я полагаю, что result.Nodes.getMap()
даст мне хотя бы CXXReinterpretCastExpr
, показанное в дампе AST? И все же он пуст.
Нашел. По-видимому, вам нужно bind
сопоставить какую-то строку, иначе узлы, которым он соответствует, не будут присутствовать в связанных узлах. Это имеет смысл, если вы так говорите, но мне пришлось слишком долго искать это.
Для тех, кто читает это, если вы вызовете метод bind
в конце вашего сопоставления, вы можете в основном указать определенную вами строку, которая будет идентифицировать найденные вами узлы, которые были сопоставлены в результате этого конкретного сопоставления. Кажется, что нет такой вещи, как строка с подстановочными знаками или что-то в этом роде, поэтому он не привязывает узлы AST к вашим результатам, если вы не привязываете сопоставление к чему-либо.
Я думаю, что это предназначено для того, чтобы различать сопоставители, если несколько из них должны были найти результаты, и они используют один и тот же обратный вызов, и каким-то образом MatchResults содержит несколько узлов, которые сопоставляются одновременно? Мне пока не совсем понятно, как работает сопоставление. Объединяет ли он несколько «совпадений», чтобы избежать слишком частого вызова run()
? Я не знаю. Для меня всегда есть только одна запись в узлах за раз.
Да,
run()
вызывается один раз за матч. Когда вы ничего не делаетеbind()
, у вас нет возможности указать, на какую часть совпадения вы хотите сослаться, поэтомуNodes
пусто. Обратите внимание, что вы можете вызывать.bind()
в различных частях сопоставителя, чтобы иметь возможность получить дескриптор этих частей в обратном вызове (например,bind()
дляcallExpr
и другую привязку для второго аргументаcallExpr
, вместо того, чтобы вручную спускаться от совпадающегоcallExpr
до второго аргумента).