clang插件独立运行快速开发模板(llvm15)

clang-plugin-testAlone github

clang-plugin-testAlone gitee

以下以获取每个语句(Stmt)末尾分号位置为例

//file : TestAloneMain.cpp
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclVisitor.h"
#include "llvm/Support/raw_ostream.h"
#include "clang/Basic/TargetInfo.h"
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include <clang/Rewrite/Core/Rewriter.h>
#include <iostream>using namespace clang;class Util {
public:static std::string _getSourceText(const clang::SourceManager& SM,const LangOptions &LO, SourceRange sourceRange){CharSourceRange charSourceRange=CharSourceRange::getCharRange(sourceRange);std::string strSourceText=Lexer::getSourceText(charSourceRange, SM, LO).str();return strSourceText;}static std::string _getSpelling(const clang::SourceManager& SM,const LangOptions &LO, Token token,bool *Invalid = nullptr){const std::string strTok = Lexer::getSpelling(token, SM, LO, Invalid);return strTok;}static std::tuple<int,int> extractLineAndColumn(const clang::SourceManager& SM, const clang::SourceLocation& sourceLocation ) {clang::PresumedLoc presumedLoc = SM.getPresumedLoc(sourceLocation);int line = presumedLoc.getLine();int column = presumedLoc.getColumn();return std::tuple<int,int>(line,column);}static SourceLocation getStmtEndSemicolonLocation(const Stmt *S, const SourceManager &SM,bool& endIsSemicolon) {const LangOptions &LO = LangOptions();std::string stmtText=Util::_getSourceText(SM, LO, S->getSourceRange());Token JTok;// 获取Stmt的结束位置SourceLocation JLoc = S->getEndLoc();if(JLoc.isInvalid()){//如果语句末尾位置 就不合法,则标记没找到分号,再直接返回。endIsSemicolon= false;return JLoc;}do{Lexer::getRawToken(JLoc, JTok, SM, LO,/*IgnoreWhiteSpace:*/true);//忽略空白字符,IgnoreWhiteSpace:true,很关键,否则可能某个位置导致循环后还是该位置,从而死循环。JLoc = Lexer::getLocForEndOfToken(JTok.getEndLoc(), /*Offset*/1, SM, LO);//偏移量给1,Offset:1,很关键,如果不向前移动 可能循环一次还是在该位置,造成死循环。//取第J次循环的Token的结尾位置,JTok.getEndLoc(),很关键,否则可能下次循环还在该token上,导致死循环。}while (JTok.isNot(tok::semi)&& JTok.isNot(tok::eof)
&& JTok.getLocation().isValid());// 获取分号的结束位置endIsSemicolon=JTok.is(tok::semi);return JTok.getLocation();}
};class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor> {
public:CompilerInstance& CI;explicit MyASTVisitor(CompilerInstance &_CI, const std::shared_ptr<Rewriter> _rewriter_ptr ) : CI(_CI)  {}bool VisitStmt(clang::Stmt *stmt) {bool endIsSemicolon=false;SourceManager &SM = CI.getSourceManager();LangOptions &LO = CI.getLangOpts();std::string strSourceText=Util::_getSourceText(SM,LO,stmt->getSourceRange());const SourceLocation &semicolonLoc = Util::getStmtEndSemicolonLocation(stmt, SM,endIsSemicolon);//条件断点 eq为真const std::string &semicolonLocStr = semicolonLoc.printToString(SM);llvm::outs() << "访问到语句: " << stmt->getStmtClassName()  << ": 【" << strSourceText  << "】,结尾是否分号:"<<std::to_string(endIsSemicolon)+""+(endIsSemicolon?(",结尾分号位置: " + semicolonLocStr):"" )<< "\n";return true;}
/*输出:
TraverseStmt: ImplicitCastExpr
TraverseStmt: FloatingLiteral
TraverseStmt: CompoundStmt
TraverseStmt: ReturnStmt
TraverseStmt: BinaryOperator
TraverseStmt: ImplicitCastExpr
TraverseStmt: DeclRefExpr
TraverseStmt: ImplicitCastExpr
TraverseStmt: DeclRefExpr*/
};class MyASTConsumer : public clang::ASTConsumer {
public:CompilerInstance &CI;MyASTVisitor visitor;explicit MyASTConsumer(CompilerInstance &_CI, const std::shared_ptr<Rewriter> _rewriter_ptr)  : CI(_CI) ,visitor(_CI,_rewriter_ptr)  {}void HandleTranslationUnit(clang::ASTContext &Context) override {for (Decl *D : Context.getTranslationUnitDecl()->decls()) {visitor.TraverseDecl(D);}//      TranslationUnitDecl *translationUnitDecl = Context.getTranslationUnitDecl();}
};class MyASTFrontendAction : public clang::ASTFrontendAction {
public:const std::shared_ptr<Rewriter> mRewriter_ptr=std::make_shared<Rewriter>();//这里是插件Act中的Rewriter,是源头,理应构造Rewriter.std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &CI, llvm::StringRef InFile) override {SourceManager &SM = CI.getSourceManager();LangOptions &langOptions = CI.getLangOpts();ASTContext &astContext = CI.getASTContext();CI.getDiagnostics().setSourceManager(&SM);mRewriter_ptr->setSourceMgr(SM, langOptions);return std::make_unique<MyASTConsumer>(CI,mRewriter_ptr);}
};int main() {// 创建 Clang 编译实例clang::CompilerInstance CI;CI.createDiagnostics();CI.createFileManager();CI.createSourceManager(CI.getFileManager());CI.getLangOpts().CPlusPlus = true;CI.getTargetOpts().Triple= "x86_64-pc-linux-gnu";llvm::Triple triple("x86_64-pc-linux-gnu");std::shared_ptr<clang::TargetOptions> targetOpts=std::make_shared<clang::TargetOptions>();targetOpts->Triple=triple.str();TargetInfo* targetInfo=  TargetInfo::CreateTargetInfo(CI.getDiagnostics(), targetOpts) ;CI.setTarget(targetInfo);CI.createPreprocessor(clang::TU_Complete);CI.getPreprocessor().Initialize(*targetInfo);SourceManager& SM=CI.getSourceManager();LangOptions &LO = CI.getLangOpts();Preprocessor &PP = CI.getPreprocessor();//添加诊断llvm::raw_ostream &OS = llvm::outs();DiagnosticOptions *diagnosticOptions = new clang::DiagnosticOptions();clang::TextDiagnosticPrinter *TextDiag = new TextDiagnosticPrinter(OS, diagnosticOptions);TextDiag->BeginSourceFile(LO,&PP);
//  TextDiag->EndSourceFile();CI.getDiagnostics().setClient(TextDiag);// 创建 ASTFrontendAction 实例clang::FrontendAction* Action = new MyASTFrontendAction();// 设置输入文件CI.getFrontendOpts().Inputs.push_back(clang::FrontendInputFile("/pubx/clang-brc/test_in/test_main.cpp", clang::InputKind(clang::Language::CXX)));// 运行 Clang 编译if (!CI.ExecuteAction(*Action)) {llvm::errs() << "Clang compilation failed\n";return 1;}return 0;
}

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

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

相关文章

Unity进阶--使用PhotonServer实现服务端和客户端通信--PhotonServer(一)

文章目录 Unity进阶--使用PhotonServer实现服务端和客户端通信服务器的安装和配置添加日志客户端的配置客户端和服务器的通信Dlc 出现vscode引用不好使的时候 Unity进阶–使用PhotonServer实现服务端和客户端通信 服务器的安装和配置 Photon的地址&#xff1a;https://www.ph…

高速公路巡检无人机,为何成为公路巡检的主流工具

随着无人机技术的不断发展&#xff0c;无人机越来越多地应用于各个领域。其中&#xff0c;在高速公路领域&#xff0c;高速公路巡检无人机已成为公路巡检的得力助手。高速公路巡检无人机之所以能够成为公路巡检中的主流工具&#xff0c;主要是因为其具备以下三大特性。 一、高速…

Leetcode | 有效的括号、最长有效括号

一、有效的括号 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应…

webpack复习

webpack webpack复习 webpack基本配置 拆分配置 - 公共配置 生产环境配置 开发环境配置 使用merge webpack-dev-server 启动本地服务 在公共中引入babel-loader处理es6 webpack高级配置 多入口文件 enty 入口为一个对象 里面的key为入口名 value为入口文件路径 例如 pa…

SSL 证书过期巡检脚本 (Python 版)

哈喽大家好&#xff0c;我是咸鱼 之前写了个 shell 版本的 SSL 证书过期巡检脚本 &#xff08;文章&#xff1a;《SSL 证书过期巡检脚本》&#xff09;&#xff0c;后台反响还是很不错的 那么今天咸鱼给大家介绍一下 python 版本的 SSL 证书过期巡检脚本 &#xff08;完整代码…

React入门学习笔记2

jsx语法规则 定义虚拟DOM时&#xff0c;不要写引号。标签中混入JS表达式时要用{ }。样式的类名指定不要用class&#xff0c;要用className。内联样式&#xff0c;要用style{{key&#xff1a;value}}的形式去写。只有一个根标签标签必须闭合标签首字母 )若小写字母开头&#xf…

echarts绘制甘特图

说在前面 项目上有需求&#xff0c;需要在大屏上展示进度甘特图&#xff0c;调研了DHTMLX和普加甘特图&#xff0c;效果都不是特别符合需求现状&#xff0c;查询了一些博客&#xff0c;决定使用echarts来绘制甘特图。 实现效果展示 实现思路分析 1、应该采用柱状图&#xff…

ORACLE常用基础

. 1.oracle开机启动流程 su - oracle lsnrctl start lsnrctl status sqlplus / as sysdba startup 2、如何查看数据库版本 select * from v$version; 3.如何查看用户从那个设备连接的数据库 SELECT DISTINCT machine , terminal FROM V$SESSION; 4.如何查看表结构 selec…

Android 14重要更新预览

Android 14重要更新预览 国际化 Android 14 在 Android 13 的基础上进一步扩展了按应用设定语言功能&#xff0c;提供了一些额外的功能&#xff1a; 自动生成应用的 localeConfig&#xff1a;从 Android Studio Giraffe Canary 7 和 AGP 8.1.0-alpha07 开始&#xff0c;您可以…

【设计模式——学习笔记】23种设计模式——观察者模式Observer(原理讲解+应用场景介绍+案例介绍+Java代码实现)

文章目录 案例引入原始方案实现实现问题分析 介绍基础介绍登场角色 案例实现案例一类图实现分析 案例二类图实现 观察者模式在JDK源码的应用总结文章说明 案例引入 有一个天气预报项目&#xff0c;需求如下&#xff1a; 气象站可以将每天测量到的温度、湿度、气压等等以公告的…

Java爬虫

什么是爬虫&#xff1f; 通过请求&#xff0c;从而去获取互联网上的各种数据与资源&#xff0c;如文字&#xff0c;图片&#xff0c;视频。 本质上原理都一样&#xff0c;都是通过api请求&#xff0c;然后服务器就会发给你信息&#xff0c;然后你再根据这些信息去提取你想要的…

Apache Kafka Learning

目录 一、Kafka 1、Message Queue是什么&#xff1f; 2、Kafka 基础架构 3、Kafka安装 二、Maven项目测试 1、Topic API 2、生产者&消费者 一、Kafka Kafka是由Apache软件基金会开发的一个开源流处理平台&#xff0c;由Scala和Java编写。Kafka是一种高吞吐量的分布式…

Flutter 实现按位置大小比例布局的控件

文章目录 前言一、如何实现&#xff1f;1、数值转成分数2、RowFlexible布局横向3、ColumnFlexible布局纵向 二、完整代码三、使用示例1、基本用法2、四分屏3、六分屏4、八分屏5、九分屏6、414分屏 总结 前言 做视频监控项目时需要需要展示多分屏&#xff0c;比如2x2、3x3、414…

使用 LangChain 搭建基于 Amazon DynamoDB 的大语言模型应用

LangChain 是一个旨在简化使用大型语言模型创建应用程序的框架。作为语言模型集成框架&#xff0c;在这个应用场景中&#xff0c;LangChain 将与 Amazon DynamoDB 紧密结合&#xff0c;构建一个完整的基于大语言模型的聊天应用。 本次活动&#xff0c;我们特意邀请了亚马逊云科…

pyspark 判断 Hive 表是否存在

Catalog.tableExists(tableName: str, dbName: Optional[str] None) → booltableName:表名 dbName&#xff1a;库名(可选) return&#xff1a;bool 值 from pyspark.sql import SparkSession spark SparkSession \.builder \.appName(tableExists) \.config(spark.num.execu…

C#类型转换

&#x1f35f;数据类型 大体分为三个大类型&#xff1a;整型&#xff08;其中又分为有符号整型、无符号整型&#xff09;、浮点型、特殊类型 注意&#xff1a;浮点数在初始化时要在值后加上后缀&#xff0c;双精度浮点数decimal的后缀为“M”、单精度浮点数double和float的后…

AI相机“妙鸭相机”原理分析和手动实现方案

妙鸭相机 一个通过上传大约20张照片&#xff0c;生成专属自拍。在2023年7月末爆火&#xff0c;根据36Kr报道&#xff0c;妙鸭相机系阿里系产品&#xff0c;挂靠在阿里大文娱体系下&#xff0c;并非独立公司。 使用方法是上传20张自拍照片&#xff0c;之后可以选择模板生成自己…

算法通过村——Hash和队列问题解析

算法的备胎Hash和找靠山的队列 备胎Hash Hash&#xff0c;不管是算法&#xff0c;还是在工程中都会大量使用。很多复杂的算法问题都用Hash能够轻松解决&#xff0c;也正是如此&#xff0c;在算法例就显得没什么思维含量&#xff0c;所以Hash是应用里的扛把子&#xff0c;但在算…

C#实现端口扫描和执行cmd命令、调用摄像头

C#端口扫描 using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Threading;namespace PortScanner {class Program{static void Main(string[] args){// 设置扫描参数string host "localho…

【安全测试】安全测试威胁建模设计方法STRIDE

目录 背景 TM(ThreatModeling) 实践 具体流程 资料获取方法 背景 目前安全测试一般都存在如下问题&#xff1a; 安全测试人员不懂业务&#xff0c;业务测试人员不懂安全&#xff0c;安全测试设计出现遗漏是无法避免的安全测试点繁多复杂&#xff0c;单点分析会导致风险暴…