2312clang,基于访问者的前端动作

原文

基于RecursiveASTVisitorASTFrontendActions.

创建用RecursiveASTVisitor查找特定名字的CXXRecordDeclAST节点的FrontendAction.

创建FrontendAction

编写基于clang的工具(如Clang插件或基于LibTooling的独立工具)时,常见入口是允许在编译过程中执行用户特定操作的FrontendAction接口.

为了在ASTclang上运行工具,提供了方便的负责执行操作的ASTFrontendAction接口.你只需要实现对每个转换单元返回一个ASTConsumerCreateASTConsumer方法.

class FindNamedClassAction : public clang::ASTFrontendAction {
public:virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &Compiler, llvm::StringRef InFile) {return std::make_unique<FindNamedClassConsumer>();}//FindNamedClassAction
};

创建ASTConsumer

ASTConsumer是一个,不管如何生成的AST,在AST编写的通用操作接口.ASTConsumer提供了许多不同的入口,但在此,只需要用ASTContext调用翻译单元HandleTranslationUnit.

class FindNamedClassConsumer : public clang::ASTConsumer {
public:virtual void HandleTranslationUnit(clang::ASTContext &Context) {//通过`RecursiveASTVisitor`遍历翻译单元声明,会访问`AST`中的所有节点.Visitor.TraverseDecl(Context.getTranslationUnitDecl());}
private://`RecursiveASTVisitor`实现.FindNamedClassVisitor Visitor;
};

使用RecursiveASTVisitor

现在已连接了,下一步是实现RecursiveASTVisitor以从AST中提取相关信息.

除了按值传递的TypeLoc节点,RecursiveASTVisitor为大多数AST节点提供bool VisitNodeType(NodeType*)形式的勾挂.只需要为相关节点类型实现方法,就可以了.
首先编写一个访问所有CXXRecordDeclRecursiveASTVisitor.

class FindNamedClassVisitor: public RecursiveASTVisitor<FindNamedClassVisitor> {
public:bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {//为了调试,转储`AST`节点,会显示已访问的节点.Declaration->dump();//返回值指示是否想继续访问.返回`假`以停止`AST`的遍历.return true;}
};

RecursiveASTVisitor的方法中,现在可用ClangAST全部功能来深入感兴趣部分.如,要查找带特定名字的所有类声明,可检查全名:

bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {if (Declaration->getQualifiedNameAsString() == "n::m::C")Declaration->dump();return true;
}

访问SourceManagerASTContext

有关AST的某些信息(如源位置和全局标识信息)不在AST节点自身中,而是在ASTContext及其关联的源管理器中存储.

要提取它们,需要传递ASTContextRecursiveASTVisitor实现中.

调用CreateASTConsumer时,CompilerInstance可访问ASTContext.因此,可从那里提取,并把它交给新创建的FindNamedClassConsumer:

virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &Compiler, llvm::StringRef InFile) {return std::make_unique<FindNamedClassConsumer>(&Compiler.getASTContext());
}

现在在RecursiveASTVisitor中,可访问ASTContext,可利用AST节点,查找源位置等:

bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {if (Declaration->getQualifiedNameAsString() == "n::m::C") {//`getFullLoc`使用`ASTContext`的`SourceManager`来解析源位置,并分解为`行和列`部分.FullSourceLoc FullLocation = Context->getFullLoc(Declaration->getBeginLoc());if (FullLocation.isValid())llvm::outs() << "Found declaration at "<< FullLocation.getSpellingLineNumber() << ":"<< FullLocation.getSpellingColumnNumber() << "\n";}return true;
}

组合在一起

如下:

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Tooling.h"
using namespace clang;
class FindNamedClassVisitor: public RecursiveASTVisitor<FindNamedClassVisitor> {
public:explicit FindNamedClassVisitor(ASTContext *Context): Context(Context) {}bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {if (Declaration->getQualifiedNameAsString() == "n::m::C") {FullSourceLoc FullLocation = Context->getFullLoc(Declaration->getBeginLoc());if (FullLocation.isValid())llvm::outs() << "Found declaration at "<< FullLocation.getSpellingLineNumber() << ":"<< FullLocation.getSpellingColumnNumber() << "\n";}return true;}
private:ASTContext *Context;
};
class FindNamedClassConsumer : public clang::ASTConsumer {
public:explicit FindNamedClassConsumer(ASTContext *Context): Visitor(Context) {}virtual void HandleTranslationUnit(clang::ASTContext &Context) {Visitor.TraverseDecl(Context.getTranslationUnitDecl());}
private:FindNamedClassVisitor Visitor;
};
class FindNamedClassAction : public clang::ASTFrontendAction {
public:virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &Compiler, llvm::StringRef InFile) {return std::make_unique<FindNamedClassConsumer>(&Compiler.getASTContext());}
};
int main(int argc, char **argv) {if (argc > 1) {clang::tooling::runToolOnCode(std::make_unique<FindNamedClassAction>(), argv[1]);}
}

FindClassDecls.cpp文件中存储它,并创建以下CMakeLists.txt来链接它:

set(LLVM_LINK_COMPONENTSSupport)
add_clang_executable(find-class-decls FindClassDecls.cpp)
target_link_libraries(find-class-declsPRIVATEclangASTclangBasicclangFrontendclangSerializationclangTooling)

对代码片运行此工具时,输出找到的n::m::C类的所有声明:

$ ./bin/find-class-decls "namespace n { namespace m { class C {}; } }"

1:29找到声明

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/578251.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在生产环境正确使用Redis

一、在生产环境使用Redis 如果在生产环境使用Redis&#xff0c;需要遵守一定的使用规范&#xff0c;以保障服务稳定、高效。。 1.1、明确Redis集群的服务定位 1、仅适用于缓存场景&#xff1a;Redis定位于高性能缓存服务&#xff0c;强调快速读写和低延迟的特性&#xff0c;…

Adobe Application Manager丢失或损坏 - 解决方案

前言 Adobe Application Manager&#xff08;简称AAM&#xff09;&#xff0c;是用来管理旧版Adobe软件的管理器&#xff0c;后来已经升级为Adobe Creative Cloud&#xff08;简称ACC&#xff09;。 使用Adobe系列软件时可能会报错提示需要使用Adobe Application Manager解决…

【Windows编程】期末复习题3

系列文章目录 期末复习题1 期末复习题2 文章目录 系列文章目录什么是事件驱动的程序执行过程&#xff1f;简要描述Windows的事件驱动程序模型。什么是动态链接库&#xff1f;其作用是什么&#xff1f;在Windows API程序设计中&#xff0c;资源的主要作用有哪些&#xff1f;Vis…

wifi驱动打开双模式

双模式 3.1 开启双模式 在Makefile添加EXTRA_CFLAGS -DCONFIG_CONCURRENT_MODE 重新编译&#xff08;make之后发现不正常工作&#xff0c;需要make clean清理一下&#xff09;。 再用sudo rmmod 8821cu.ko&#xff0c;重新启动。出现wlan1&#xff1a; 出现问题&#xff1…

助力打造清洁环境,基于轻量级DETR(DEtectionTRansformer)开发构建公共场景下垃圾堆放垃圾桶溢出检测识别系统

公共社区环境生活垃圾基本上是我们每个人每天几乎都无法避免的一个问题&#xff0c;公共环境下垃圾投放点都会有固定的值班时间&#xff0c;但是考虑到实际扔垃圾的无规律性&#xff0c;往往会出现在无人值守的时段内垃圾堆放垃圾桶溢出等问题&#xff0c;有些容易扩散的垃圾比…

2024年PMP考试新考纲-PMBOK第七版-项目绩效域真题解析

如何一次性通过PMP考试&#xff0c;取得3A等级的PMP证书&#xff1f;华研荟根据十多年的培训和辅导&#xff0c;以及数千名学员的建议是&#xff1a; 先把PMBOK第六版、第七版和敏捷实践指南的三本官方教材研读一遍&#xff08;如果觉得自己看书慢&#xff0c;可以看讲解视频&…

基于多反应堆的高并发服务器【C/C++/Reactor】(中)Dispatcher模块的实现思路和定义

&#xff08;四&#xff09;Dispatcher模块的实现思路 关于dispatcher&#xff0c;它应该是反应堆模型里边的核心组成部分&#xff0c;因为如果说这个反应堆模型里边有事件需要处理&#xff0c;或者说有事件需要检测&#xff0c;那么是需要通过这个poll、epoll 或者 select来完…

Spring Boot3 Web开发技术

前期回顾 springboot项目常见的配置文件类型有哪些&#xff1f;哪种类型的优先级最高 yml properties yaml 读取配置文件里的数据用什么注解&#xff1f; value restful风格 RESTful 风格与传统的 HTTP 请求方式相比&#xff0c;更加简洁&#xff0c;安全&#xff0c;能隐…

有赞微商城集成CRM:无代码电商平台优化用户运营

有赞微商城与无代码开发的完美结合 在数字化转型的浪潮中&#xff0c;无代码开发是商家极力追求的目标&#xff0c;它能够让非技术人员也能轻松地实现软件集成和数据流转。有赞微商城的出现&#xff0c;就是为了响应这一需求。通过无需复杂编程即可实现的API集成&#xff0c;商…

Kind创建k8s - JAVA操作控制

kind 简介kind 架构安装 Kind (必备工具)docker官网kubectl官网kind官网校验安装结果 关于kind 命令 安装一个集群查看当前 Kubernetes 集群中的节点信息。查看当前命名空间下中的Pod&#xff08;容器实例&#xff09;的信息。使用 kind create cluster 安装&#xff0c;关于安…

MYSQL一一函数一一流程函数

咱今天讲的是MySQL函数中的流程函数&#xff0c;会有3小题和一个综合案例帮助大家理解 流程函数是很常用的一类函数&#xff0c;可以在SQL语句中实现条件筛选&#xff0c;从而提高语句的效率 小题&#xff1a; ①if语句&#xff1a; select if(flash,ok,error); //如果…

Java之Atomic 原子类总结

Java之Atomic 原子类总结 Atomic 原子类介绍 Atomic 翻译成中文是原子的意思。在化学上&#xff0c;我们知道原子是构成一般物质的最小单位&#xff0c;在化学反应中是不可分割的。在我们这里 Atomic 是指一个操作是不可中断的。即使是在多个线程一起执行的时候&#xff0c;一…

【Java】你掌握了多线程吗?

【文末送书】今天推荐一本Java多线程编程领域新书《一本书讲透Java线程》 摘要 互联网的每一个角落&#xff0c;无论是大型电商平台的秒杀活动&#xff0c;社交平台的实时消息推送&#xff0c;还是在线视频平台的流量洪峰&#xff0c;背后都离不开多线程技术的支持。在数字化转…

FPGA-ZYNQ-7000 SoC在嵌入式系统中的优势

FPGA-ZYNQ-7000 SoC在嵌入式系统中的优势 本章节主要参考书籍《Xilinx Zynq-7000 嵌入式系统设计与实现 基于ARM Cortex-A9双核处理器和Vivado的设计方法 (何宾&#xff0c;张艳辉编著&#xff09;》 本章节主要讲述FPGA-ZYNQ-7000 SoC在嵌入式系统中的优势&#xff0c;学习笔…

LeetCode刷题--- 优美的排列

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 http://t.csdnimg.cn/6AbpV 数据结构与算法 ​​​​​​http://t.cs…

java web中 EL表达式的相关案例:

java web中 EL表达式的相关案例&#xff1a; <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%><%String abc"ABC";String xyz"XYZ";//原因是没有把abc放到作用域里pageContext.…

UGUI Panel的显示和隐藏优化

unity UI如何开启&#xff08;显示&#xff09;或者关闭&#xff08;隐藏&#xff09;Panel界面&#xff0c;相信大家都是知道的&#xff0c;但是如何做最好呢&#xff1f; 可能大家一般开启/关闭界面的方法就是直接SetActive吧。这样做通常是可以的&#xff0c;简答快速地解决…

开发环境和生产环境的区别

软件开发环境(Software Development Environment&#xff0c;SDE)是指在基本硬件和宿主软件的基础上&#xff0c;为支持系统软件和应用软件的工程化开发和维护而使用的一组软件&#xff0c;简称SDE。它由软件工具和环境集成机制构成&#xff0c;前者用以支持软件开发的相关过程…

【MATLAB】 RGB和YCbCr互转

前言 在视频、图像处理领域经常会遇到不同色域图像的转换&#xff0c;比如RGB、YUV、YCbCr色域间的转换&#xff0c;这里提供一组转换公式&#xff0c;供大家参考。 色彩模型 RGB RGB色彩模型是一种用于表示数字图像的颜色空间&#xff0c;其中"RGB"代表红色&…

排序算法--------计数排序

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…