clang-前端插件-给各种无花括号的“块”加花括号-基于llvm15--clang-plugin-add-brace

这篇具有很好参考价值的文章主要介绍了clang-前端插件-给各种无花括号的“块”加花括号-基于llvm15--clang-plugin-add-brace。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

处理的语句

case

术语约定或备忘

  1. case起止范围: 从冒号到下一个’case’开头, 简称有: case内 、case内容
  2. Ast: Abstract syntax tree: 抽象语法树

没插入花括号的case

若case内, 以下任一条成立,则 跳过该case 即 不会对该case内容用花括号包裹.

  • 有#define、
  • 有#include、
  • 有直属变量声明、
  • 空case、
  • 有宏调用

详述

预处理回调收集#include指令、宏定义

CollectIncMacro_PPCb:Collect Inlucde Macro PPCallbacks : 收集Inlucde和Macro的预处理回调

收集 #include、 #define , 以判断case起止范围内 有无 #include、 #define

遍历switch内某case起止范围内每条语句

RangeHasMacroAstVst: Range Has Macro Call Ast Vistor: 给定范围有无宏调用Ast遍历器

名义上遍历整个switch下的Stmt,实际遍历 给定范围内( 即 case起止范围 内) 的语句,进行以下计算:

1. hasMacro: case起止范围 有无宏调用,
  从而帮助过滤掉 有宏调用 的case
2. caseKSubStmtCnt:    case起止范围 语句个数(即 case子语句个数), 
  从而帮助 过滤掉 空case
3. VarDeclDirectlyInCaseKCnt:   直接写在'case'内的变量声明语句个数,
  即 直属变量声明个数 
  从而 帮助过滤掉 有直属变量声明 的case。
  直接写在'case'内的变量声明语句个数,包括以下两种情况:
  3.1. 直接写在'case'内,其父亲是case语句的
  3.2. 直接写在'case'内, 但是其父亲是switch块的.  
    即 存在 在case内的语句 但却不属于该case  而是直接属于switch, 此现象,直接导致 case的子语句 是伪命题,
      才使得 RangeHasMacroAstVst 不可能 实现无遗漏地 遍历 case下的子语句 , 
        只能扩大遍历范围到整个switch 并只关注case起止范围内的语句 才能 实现无遗漏地、精准地 遍历 case下的子语句。

实际运行花括号插件

到此 加花括号插件完工了,在llvm-project上正常运行:

sudo docker exec -it ubuntu2204_clang15Compile bash

弹出docker实例ubuntu2204_clang15Compile的bash命令行,以下命令都在此命令行下执行

cd /pubx/

git clone https://gitcode.net/pubz/llvm-project/-/commits/brc-dev-no_tick
#即 https://gitcode.net/pubz/llvm-project/-/commit/bee38a325d0957a28b4d06cb4be3c251d143cdf0
#克隆仓库llvm-project后目录结构如下: /pubx/llvm-project/.git/config
  • 步骤1: 对每个被直接编译的源文件中单语句加花括号

对llvm-project的每个源文件的编译过程应用插件libBrcPlugin.so 以 对 该源文件中单语句加花括号

source /pubx/llvm-project/doc_clang15_build/brc_build1_plugin.sh

brc_build1_plugin.sh

  • 步骤2: 对加了花括号后的llvm-project再次做正常的普通编译
source /pubx/llvm-project/doc_clang15_build/brc_build2_directly.sh

brc_build2_directly.sh

  • 步骤3: 验证
//编写c语言源文件 hello.c,内容如下:
#include <stdio.h>
int main(int argc, char** argv){
   
  int a,b;
  printf("a,b:");
  scanf("%d,%d",&a,&b);
  int sum=a+b, diff=a-b, div=a/b, mod=a%b;
  printf("sum=%d,diff=%d,div=%d,mod=%d\n",sum,diff,div,mod);
  return 0;
}
/pubx/build-llvm15/bin/clang-15  hello.c  -o hello.app
./hello.app
a,b:45,21
sum=66,diff=24,div=2,mod=3

加完花括号的llvm-project源码编译出的编译器clang-15 对 hello.c 实施编译, 编译出二进制文件 hello.app,

而该二进制文件 hello.app 正常运行

由此说明 ,花括号加的位置基本正确。

#统计

find /pubx/llvm-project/ -not -path '*/.git/*' -type f  \( -name "*.cpp" -or -name "*.c"  \)   | xargs -I% grep -Hn    BrcXxx    % > /pubx/BrcXxx.log

#把上一条bash命令抽成bash函数
findBrcCommentThenSave() {
   
  set -x #bash启用显示执行的命令
  keyword=$1
  find /pubx/llvm-project/ -not -path '*/.git/*' -type f \( -name "*.cpp" -or -name "*.c" \) | xargs -I% grep -Hn "$keyword" % |tee  /pubx/"${keyword}.log"
  set +x #bash禁止显示执行的命令
}
findBrcCommentThenSave BrcThen
findBrcCommentThenSave BrcSw
findBrcCommentThenSave BrcElse
findBrcCommentThenSave BrcFor
findBrcCommentThenSave BrcForRange
findBrcCommentThenSave BrcWhl
findBrcCommentThenSave BrcSw

各种语句分别加了多少花括号

ls -S /pubx/Brc* | xargs -I% sh -c  'wc -l %; ' 

'''
93201 /pubx/BrcThen.log
29832 /pubx/BrcSw.log
5539 /pubx/BrcElse.log
3603 /pubx/BrcFor.log
2187 /pubx/BrcForRange.log
663 /pubx/BrcWhl.log
'''

各种语句加了花括号的,有多少含有return

这些单语句return,由于没有被花括号包裹,才没有被t_clock_tick插入栈变量释放语句。
而tick插件栈变量分配、释放不平衡,具体为 栈变量共24万、最终残留2万没释放。 此不平衡是 由于 这些大约5万个单return语句没释放栈变量 导致的吗?
如下所示,被BrcPlugin插入花括号的语句中 大约5万个含有return.文章来源地址https://www.toymoban.com/news/detail-720603.html

ls -S /pubx/Brc* | xargs -I% sh -c  'echo -n "%    "; grep return % |wc -l '

'''
/pubx/BrcThen.log    50438
/pubx/BrcSw.log    2681
/pubx/BrcElse.log    815
/pubx/BrcFor.log    6
/pubx/BrcForRange.log    4
/pubx/BrcWhl.log    2
'''

实现

CMakeLists.txt

cmake_minimum_required(VERSION 3.13.4)

set(LIBFMT_DIR "/pubx/fmt/")
#set(LIBFMT_STATIC /pubx/fmt/include)
set(LIBFMT_INCLUDE "${LIBFMT_DIR}/include/")
#set(LIBFMT_STATIC /pubx/fmt/build/libfmt.a)
set(LIBFMT_STATIC "${LIBFMT_DIR}/build/libfmt.a")

include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/include")
include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/base_home/include/")

if (NOT EXISTS "${LIBFMT_STATIC}")
  MESSAGE(FATAL_ERROR "libfmt静态库${LIBFMT_STATIC} 不存在,请参照 build-libfmt.sh 构建libfmt静态库")
endif()

if (NOT EXISTS "${LIBFMT_INCLUDE}")
  MESSAGE(FATAL_ERROR "libfmt头文件目录${LIBFMT_INCLUDE} 不存在,请参照 build-libfmt.sh 构建libfmt静态库")
endif()

#===============================================================================
# 0. GET CLANG INSTALLATION DIR
#修改默认编译器
set(CT_Clang_INSTALL_DIR "/llvm_release_home/clang+llvm-15.0.0-x86_64-linux-gnu-rhel-8.4")
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CURSES_LIBRARY "/lib64/libncurses.so.6")
set(CURSES_INCLUDE_PATH "/usr/include/")
set(CMAKE_EXPORT_COMPILE_COMMANDS True)
#编译器还是使用自带的gcc, 否则 调试时 没有 libstdc++  的调试信息,导致std::string在gdb中不显示,参考:https://stackoverflow.com/questions/58356385/python-exception-class-gdb-error-there-is-no-member-named-m-dataplus-whe/58356946#58356946
#   gdb显示std::string时报错: There is no member named _M_dataplus。 因此gdb不显示std::string的值.
#set(CMAKE_C_COMPILER "/llvm_release_home/clang+llvm-15.0.0-x86_64-linux-gnu-rhel-8.4/bin/clang")
#set(CMAKE_CXX_COMPILER "/llvm_release_home/clang+llvm-15.0.0-x86_64-linux-gnu-rhel-8.4/bin/clang++")
set(LLVM_DIR "/llvm_release_home/clang+llvm-15.0.0-x86_64-linux-gnu-rhel-8.4")
#set(xxx "")

project(clang-brc)
#project放到默认编译器定义之后,否则cmake会死循环


set(CT_LLVM_INCLUDE_DIR "${CT_Clang_INSTALL_DIR}/include/llvm")

set(CT_LLVM_CMAKE_FILE "${CT_Clang_INSTALL_DIR}/lib/cmake/clang/ClangConfig.cmake")

# http://llvm.org/docs/CMake.html#embedding-llvm-in-your-project
list(APPEND CMAKE_PREFIX_PATH "${CT_Clang_INSTALL_DIR}/lib/cmake/clang/")

find_package(Clang REQUIRED CONFIG)

# Sanity check. As Clang does not expose e.g. `CLANG_VERSION_MAJOR` through
# AddClang.cmake, we have to use LLVM_VERSION_MAJOR instead.
# TODO: Revisit when next version is released.
if(NOT "15" VERSION_EQUAL "${LLVM_VERSION_MAJOR}")
  message(FATAL_ERROR "Found LLVM ${LLVM_VERSION_MAJOR}, but need LLVM 15")
endif()

message(STATUS "Found Clang ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using ClangConfig.cmake in: ${CT_Clang_INSTALL_DIR}")

message("CLANG STATUS:
  Includes (clang)    ${
   CLANG_INCLUDE_DIRS}
  Includes (llvm)     ${
   LLVM_INCLUDE_DIRS}"
)

# Set the LLVM and Clang header and library paths
include_directories(SYSTEM "${LLVM_INCLUDE_DIRS};${CLANG_INCLUDE_DIRS}")

#===============================================================================
# 3. CLANG-brc BUILD CONFIGURATION
#===============================================================================
# Use the same C++ standard as LLVM does
set(CMAKE_CXX_STANDARD 17 CACHE STRING "")

# Build type
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Debug CACHE
      STRING "Build type (default Debug):" FORCE)
endif()

# Compiler flags
set(CMAKE_CXX_FLAGS "${
   CMAKE_CXX_FLAGS} -Wall\
    -fdiagnostics-color=always")

# LLVM/Clang is normally built without RTTI. Be consistent with that.
if(NOT LLVM_ENABLE_RTTI)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
endif()

# -fvisibility-inlines-hidden is set when building LLVM and on Darwin warnings
# are triggered if llvm-tutor is built without this flag (though otherwise it
# builds fine). For consistency, add it here too.
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-fvisibility-inlines-hidden"
  SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG

到了这里,关于clang-前端插件-给各种无花括号的“块”加花括号-基于llvm15--clang-plugin-add-brace的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MinGW/MSYS/GCC/GNU/MSVC/Clang/LLVM都是什么

    MinGW(Minimalist GNU for Windows)是一个用于 Windows平台的开发工具集 ,它提供了一组用于编译和构建应用程序的工具和库。它的目标是在Windows环境下提供一个类Unix的开发体验。 MinGW的 核心是GNU编译器集合(GCC) ,它是一个开源的编译器套件,支持多种编程语言,如C、C++和For

    2024年02月20日
    浏览(34)
  • 使用 LLVM clang C/C++ 编译器编译 OpenSSL 3.X库

    1、下载 OpenSSL 3.X 库的源代码放到待编译目录 2、解压并接入 OpenSSL 3.X 库源码的根目录 3、复制 ./Configure 一个取名为 ./Configure-clang 4、修改 ./Configure-clang 找到配置段: CC= CXX= CPP= LD= 把它们改成 CC          = \\\"/usr/bin/clang-8\\\", CXX         = \\\"/usr/bin/clang++-8\\\", CPP         = \\\"/usr/bin/

    2024年02月02日
    浏览(36)
  • matlab中各种括号(),[],与{}的区别与认识

    原文 在matlab中,常常会遇到(),[],和{},这个3种符号怎么区分,怎么用,这里我来总结一下,以供参考。 [] 首先。[]叫中括号,它用来存储矩阵和向量(vector在C++中也叫容器)  举个例子,a=[1,2,3],是一个向量,这个向量有3个元素,也可以用a=[1 2 3]  eg:    对于a=[1 2 3;2 3 4 ;3

    2023年04月08日
    浏览(24)
  • vscode安装配置clang-format插件及使用

    首先安装插件。在vscode扩展里搜索 clang-format ,安装排名第一的 xaver.clang-format 。 确认clang-format可执行程序路径 windows用 eveything 查找一下 clang-format.exe , 最新的扩展 c/c++ 里集成了 clang-format。 如: C:Usersjack.vscodeextensionsms-vscode.cpptools-1.13.9-win32-x64LLVMbinclang-format.exe 。 Lin

    2024年01月20日
    浏览(26)
  • vscode 静态语法检测插件C/C++ Advanced Lint,ubuntu20.04安装clang、cppcheck

     远程环境:ubuntu20.04 本地开发环境:windows 11  开发IDE:vscode 安装llvm     2.安装clang 3.检查是否安装成功(查看clang版本,有显示即为成功) 一、简介         cppcheck 是一种 C/C++ 代码缺陷静态检查工具。cppcheck 不检查代码中的语法错误,只检查编译器检查不出来的bug,其目

    2024年02月05日
    浏览(35)
  • 前端实战:基于Verdaccio搭建私有npm仓库,轻松上传与下载自定义npm插件包

    搭建团队的私有仓库,保证团队组件的安全维护和私密性,是进阶前端开发主管路上,必不可少的一项技能。 一、原理 我们平时使用npm publish进行发布时,上传的仓库默认地址是npm,通过Verdaccio工具在本地新建一个仓库地址,再把本地的默认上传仓库地址切换到本地仓库地址

    2024年04月17日
    浏览(33)
  • Max杀毒,最强插件,解决清理各种max病毒各种弹窗提示

    遇到以下3dmax病毒,是否是非常难受,而且无解?仔细看一下下文是不是跟你提示的差不多喔。如果是,那基本是max病毒无疑了。 三维国度max杀毒软件可完全解决以下问题: 三维国度max杀毒软件下载 https://www.3wgd.com/index/index.html 3ds max病毒提示1: MAXScript Callback script Exception

    2024年02月09日
    浏览(30)
  • vue浏览器插件安装-各种问题

    https://blog.csdn.net/qq_55640378/article/details/131553642 下载地址: Tags · vuejs/devtools · GitHub npm  install  或是 cnpm  install 遇到的报错   设置淘宝镜像源(推荐使用nrm,这一步是为了保证其他依赖不报错  npm install -g nrm nrm use   taobao 文件下载到移动硬盘中cnpm  intall 报错   cnpm install

    2024年02月11日
    浏览(30)
  • 前端各种方法自我整理

    slice (-2)取出数组中倒数两个植变生成一个新数组 slice(0,3)取出数组下标0到下标3的值,生成新数组,但是不包含下标3的值 注意:slice不会改变数组的长度 查看数组或字符串 内是否有该值,有返回true,无返回false 例子:arr.includes(\\\'a\\\')  //true,false 返回小于等于x的最大整数:  注意

    2024年02月15日
    浏览(31)
  • 前端实现下载文件的各种方式

    前端涉及到的文件下载还是很多应用场景的,那么前端文件下载有多少种方式呢?每种方式有什么优缺点呢?下面就来一一介绍。 通过 a 标签的 download 属性来实现文件下载,这种方式是最简单的,也是我们比较常用的方式,先来看示例代码: 就上面的这个示例,我们点击下

    2024年02月16日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包