Clang MatchResult не имеет связанных узлов AST?

Я пишу свой первый 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? И все же он пуст.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
177
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Нашел. По-видимому, вам нужно bind сопоставить какую-то строку, иначе узлы, которым он соответствует, не будут присутствовать в связанных узлах. Это имеет смысл, если вы так говорите, но мне пришлось слишком долго искать это.

Для тех, кто читает это, если вы вызовете метод bind в конце вашего сопоставления, вы можете в основном указать определенную вами строку, которая будет идентифицировать найденные вами узлы, которые были сопоставлены в результате этого конкретного сопоставления. Кажется, что нет такой вещи, как строка с подстановочными знаками или что-то в этом роде, поэтому он не привязывает узлы AST к вашим результатам, если вы не привязываете сопоставление к чему-либо.

Я думаю, что это предназначено для того, чтобы различать сопоставители, если несколько из них должны были найти результаты, и они используют один и тот же обратный вызов, и каким-то образом MatchResults содержит несколько узлов, которые сопоставляются одновременно? Мне пока не совсем понятно, как работает сопоставление. Объединяет ли он несколько «совпадений», чтобы избежать слишком частого вызова run()? Я не знаю. Для меня всегда есть только одна запись в узлах за раз.

Да, run() вызывается один раз за матч. Когда вы ничего не делаете bind(), у вас нет возможности указать, на какую часть совпадения вы хотите сослаться, поэтому Nodes пусто. Обратите внимание, что вы можете вызывать .bind() в различных частях сопоставителя, чтобы иметь возможность получить дескриптор этих частей в обратном вызове (например, bind() для callExpr и другую привязку для второго аргумента callExpr, вместо того, чтобы вручную спускаться от совпадающего callExpr до второго аргумента).

adentinger 16.03.2023 22:02

Другие вопросы по теме