S
SIGSEGV DREC
@segfault_drec747 подп.
880просмотров
15 марта 2025 г.
Score: 968
Его темнейшество На лекции по Clang internals было задание проверки принадлежности идентификаторов к словарю (под это ещё была забавная легенда). Первым этапом была реализация с помощью Visitor и LibTooling. А я решил сделать более простую (и гачимучную) задачу. Простенькая обработка опций и запуск действия на фронтенде: int main(int argc, const char **argv) { auto expectedParser = clang::tooling::CommonOptionsParser::create( argc, argv, ....); if (!expectedParser) { llvm::errs() << expectedParser.takeError(); return EXIT_FAILURE; } clang::tooling::CommonOptionsParser &optParser = expectedParser.get(); std::string error; clang::tooling::ClangTool tool(optParser.getCompilations(), optParser.getSourcePathList()); return tool.run( clang::tooling::newFrontendActionFactory<FistingAction>().get()) ? EXIT_FAILURE : EXIT_SUCCESS; } И дальше создадим это действие, единственным отличием которого от базового будет перегруженный метод, создающий кастомный обработчик AST. class FistingAction final : public clang::ASTFrontendAction { public: std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &compiler, llvm::StringRef inFile) override { return std::make_unique<FistingConsumer>(&compiler.getASTContext()); } }; В свою очередь этот обработчик умеет только запускать visitor'а в единицу трансляции class FistingConsumer final : public clang::ASTConsumer { public: explicit FistingConsumer(clang::ASTContext context) : visitor_(context) {} virtual void HandleTranslationUnit(clang::ASTContext &context) override { visitor_.TraverseDecl(context.getTranslationUnitDecl()); } private: FistingVisitor visitor_; }; А уже visitor, методы которого вызывают на нодах определенного рода, находя fisting, выводит пользователю подсказку, что у него есть 300&#036; и где они class FistingVisitor final : public clang::RecursiveASTVisitor<FistingVisitor> { public: explicit FistingVisitor(clang::ASTContext context) : context_(context) {} bool VisitNamedDecl(clang::NamedDecl d) { if (d->getDeclName().isIdentifier() && (d->getDeclName().getAsString() == "fisting")) { llvm::outs() << "hint: fisting detected on " << context_->getFullLoc((d->getBeginLoc())).getLineNumber() << ":" << context_->getFullLoc((d->getBeginLoc())).getColumnNumber() << "&#092;n"; } return true; } private: clang::ASTContext context_; }; Класс в clang/include/clang/AST/RecursiveASTVisitor.h должен сделать немного: обойти все ноды, каждую из них перебрать до самого базового класса AST, вызвать на каждой итерации этого перебора метод Visit*. И если этот метод "затенил" оригинал, то вызовется именно пользовательский. Вроде бы я разобрался... А это только первая итерация задачи. Дальше как-то сами. Да пребудет с вами fisting! #compiler #llvm
880
просмотров
3010
символов
Нет
эмодзи
Нет
медиа

Другие посты @segfault_drec

Все посты канала →
Его темнейшество На лекции по Clang internals было задание п — @segfault_drec | PostSniper