2312clang,基于访问者的前端动作
原文
基于RecursiveASTVisitor的ASTFrontendActions.
创建用RecursiveASTVisitor查找特定名字的CXXRecordDeclAST节点的FrontendAction.
创建FrontendAction
编写基于clang的工具(如Clang插件或基于LibTooling的独立工具)时,常见入口是允许在编译过程中执行用户特定操作的FrontendAction接口.
为了在ASTclang上运行工具,提供了方便的负责执行操作的ASTFrontendAction接口.你只需要实现对每个转换单元返回一个ASTConsumer的CreateASTConsumer方法.
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*)形式的勾挂.只需要为相关节点类型实现方法,就可以了.
首先编写一个访问所有CXXRecordDecl的RecursiveASTVisitor.
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;
}
访问SourceManager和ASTContext
有关AST的某些信息(如源位置和全局标识信息)不在AST节点自身中,而是在ASTContext及其关联的源管理器中存储.
要提取它们,需要传递ASTContext进RecursiveASTVisitor实现中.
调用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找到声明
相关文章:
2312clang,基于访问者的前端动作
原文 基于RecursiveASTVisitor的ASTFrontendActions. 创建用RecursiveASTVisitor查找特定名字的CXXRecordDeclAST节点的FrontendAction. 创建FrontendAction 编写基于clang的工具(如Clang插件或基于LibTooling的独立工具)时,常见入口是允许在编译过程中执行用户特定操作的F…...
怎么搭建实时渲染云传输服务器
实时渲染云传输技术方案,在数字孪生、虚拟仿真领域使用越来越多,可能很多想使用该技术方案项目还不知道具体该怎么搭建云传输服务器,具体怎么使用实时云渲染平台系统。点量云小芹将对这两个问题做集中分享。 一、实时渲染服务器怎么搭建&…...
如何在生产环境正确使用Redis
一、在生产环境使用Redis 如果在生产环境使用Redis,需要遵守一定的使用规范,以保障服务稳定、高效。。 1.1、明确Redis集群的服务定位 1、仅适用于缓存场景:Redis定位于高性能缓存服务,强调快速读写和低延迟的特性,…...
LeetCode-环形链表问题
1.环形链表(141) 题目描述: 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统…...
C# 读取Word表格到DataSet
目录 功能需求 Office 数据源的一些映射关系 范例运行环境 配置Office DCOM 关键代码 组件库引入 核心代码 杀掉进程 总结 功能需求 在应用项目里,多数情况下我们会遇到导入 Excel 文件数据到数据库的功能需求,但某些情况下,也存…...
构建外卖系统:从技术到实战
在当今高度数字化的社会中,外卖系统的开发变得愈发重要。本文将从技术角度出发,带领读者一步步构建一个基础的外卖系统,并涵盖关键技术和实际代码。 1. 技术选型 1.1 后端开发 选择Node.js和Express框架进行后端开发,搭建一个灵…...
城市之眼:数据可视化在智慧城市的角色
作为智慧城市建设的核心组成部分,数据可视化扮演着至关重要的角色。在城市中,数据源源不断地产生,涵盖了从交通流量、环境质量到市民需求等各个方面。而数据可视化作为将这些数据呈现出来的手段,对智慧城市的发展起着关键性的作用…...
Nature | Baker团队用AI设计出史上最高互作强度的蛋白质
蛋白质是生命的基础,是生命功能的主要执行者,其结构与功能由氨基酸序列所决定。蛋白质设计是指对新蛋白质分子进行人为的合理设计,旨在设计新的活性,行为或目的,并增进对蛋白质功能的基本了解。可以从头开始设计蛋白质…...
C# 初识System.IO.Pipelines
写在前面 在进一步了解Socket粘包分包的过程中,了解到了.NET 中的 System.IO.Pipelines,可以更优雅高效的解决这个问题;先跟随官方的示例做个初步的认识。 System.IO.Pipelines 是一个库,旨在使在 .NET 中执行高性能 I/O 更加容…...
嵌入式——RTC内置实时时钟
学习目标 理解原理图RTC设计部分掌握初始化RTC掌握设置时间掌握读取时间学习内容 RTC原理图 RTC结构框图 RTC时钟 开发流程 加载依赖。gd32f4xx_rtc.c,gd32f4xx_pmu.c初始化RTC。时钟配置。获取时钟。RTC初始化 // 电池管理加载 rcu_periph_clock_enable(RCU_PMU); pmu_back…...
nodejs微信小程序+python+PHP的热带野生动物园景点预约订票系统的设计与实现-计算机毕业设计推荐
目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性:…...
ASP.NET MVC的5种AuthorizationFilter
一、IAuthorizationFilter 所有的AuthorizationFilter实现了接口IAuthorizationFilter。如下面的代码片断所示,IAuthorizationFilter定义了一个OnAuthorization方法用于实现授权的操作。作为该方法的参数filterContext是一个表示授权上下文的AuthorizationContext对…...
C语言初学8:函数和作用域
一、函数 函数声明告诉编译器函数的名称、返回值类型和参数。在一个源文件中定义函数且在另一个文件中调用函数时,函数声明是必需的。函数定义提供了函数的实际主体。...
2024年科技盛宴“上海智博会·上海软博会”招商工作接近尾声
2024年上海智博会和上海软博会即将于3月份在上海跨国采购会展中心盛大召开。作为全球科技和软件行业的盛会,这两大展会汇集了业界顶尖的企业、创新技术和前瞻思想,吸引了来自世界各地的专业人士和参展商。 今年的展会将一如既往地为大家呈现最前沿的科技…...
深圳锐科达SIP矿用电话模块SV-2801VP
深圳锐科达SIP矿用电话模块SV-2801VP 一、简介 SV-2800VP系列模块是我司设计研发的一款用于井下的矿用IP音频传输模块,可用此模块打造一套低延迟、高效率、高灵活和多扩展的IP矿用广播对讲系统,亦可对传统煤矿电话系统加装此模块,进行智能化…...
【Qt-数据库】
Qt编程指南 ■ SQLite■ CSV■ JSON ■ SQLite Qt 提供了很多操作数据库的类, SQLite 是非常小的,是轻量级的,完全配置时小于 400KiB,省略可选功能配置时小于 250KiB。 SQLite 是一个进程内的库,实现了自给自足的、无…...
windows文件名命名规范(文件名规范、命名规则、避免特殊字符、注意文件名长度限制260个字符)
文章目录 Windows文件名命名规范1. 基本规则1.1 避免使用特殊字符1.2 限制文件名长度1.3 避免使用预留名称 2. 最佳实践2.1 使用描述性名称2.2 使用连字符或下划线代替空格2.3 使用日期和版本号 3. 实用技巧3.1 批量重命名文件3.2 使用PowerShell进行高级文件操作 Windows文件名…...
如何修改MySQL的默认端口
MySQL是世界上最流行的开源关系型数据库管理系统之一。在某些情况下,由于安全性、网络策略或端口冲突的原因,数据库管理员可能需要更改MySQL服务的默认监听端口。本文将指导您如何在不同的操作系统上更改MySQL的默认端口。 理解MySQL配置文件 MySQL的配…...
Android笔记(二十一):Room组件实现Android应用的持久化处理
一、Room组件概述 Room是Android JetPack架构组件之一,是一个持久处理的库。Room提供了在SQLite数据库上提供抽象层,使之实现数据访问。 (1)实体类(Entity):映射并封装了数据库对应的数据表中…...
uniapp中各种状态的按钮
当涉及状态按钮时,UniApp提供了丰富的选择。UniApp中的状态按钮可以是开关按钮、单选按钮、多选按钮等。开发者可以根据具体需求选择使用合适的状态按钮组件。对于状态按钮,UniApp提供了丰富的API和事件,可以轻松实现状态切换、状态监听等功能…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
xmind转换为markdown
文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...
leetcode73-矩阵置零
leetcode 73 思路 记录 0 元素的位置:遍历整个矩阵,找出所有值为 0 的元素,并将它们的坐标记录在数组zeroPosition中置零操作:遍历记录的所有 0 元素位置,将每个位置对应的行和列的所有元素置为 0 具体步骤 初始化…...
路由基础-路由表
本篇将会向读者介绍路由的基本概念。 前言 在一个典型的数据通信网络中,往往存在多个不同的IP网段,数据在不同的IP网段之间交互是需要借助三层设备的,这些设备具备路由能力,能够实现数据的跨网段转发。 路由是数据通信网络中最基…...
