Clang AST parsing for automated code generation

2024-01-16 12:08

本文主要是介绍Clang AST parsing for automated code generation,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文地址:http://www.seethroughskin.com/blog/?p=2172

Syntax traversal is a powerful tool. With it you can automate repetitive tasks, search for semantic errors, generate wrappers, and so much more.  A few months ago I hit a hump (read: a f***ing mountain) of an issue with some legacy code that has been on my plate for awhile now.

Having killed a small forest’s worth of paper I decided that manually tracing paths through code was an inefficient use of my time.  Instead I went in search an automatic method for generating an abstract syntax tree(AST) for C++ code.  My idea was that I could use the AST to generate something like a direct graph to better visualize code flow.

There are a few flavors of readable syntax generation out there (and likely more):

  • pycparser (Supports on C, I believe)
  • gccxml
  • Clang (via AST dump)

I’ve been a fan of Clang for awhile now and they have a very robust and active community making it a natural choice for my AST generation needs.  Clang also has decent articles on getting started in both Windows and Linux.  If you don’t have Clang installed, I suggest reading that linked article.  You’ll need compiled versions of clang.exe and libclang.dll to follow along with the Python binding below.

[Caveat]

Clang at revision 183352 (2013-06-05)  has a slight issue in that it won’t identify Linkage specifications (e.g. extern “C” void foo()).  To fix this issue, follow these steps from my SO answer:

//Bit of a necroanswer but if you go in to \llvm\tools\clang\lib\Sema\SemaCodeComplete.cpp and add the following line:case Decl::LinkageSpec:  return CXCursor_LinkageSpec;//To the switch in:
CXCursorKind clang::getCursorKindForDecl(const Decl *D)//It should resolve the issue of clang's Python binder 
//returning UNEXPOSED_DECL instead of the correct LINKAGE_SPEC.
//This change was made at revision 183352(2013-06-05).//Example from my version:
CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
if (!D)return CXCursor_UnexposedDecl;switch (D->getKind()) {case Decl::Enum:               return CXCursor_EnumDecl; case Decl::LinkageSpec:  return CXCursor_LinkageSpec;// ......

 

[Libclang]

Libclang is Clang’s dynamic binding that is used in conjunction w/ Python to allow for interpreted code evaluation.  Eli Bendersky has a great post on using libclang that I referenced frequently while writing code.  Clang documentation can be very lacking in some areas and Eli’s post does a good job of explaining the steps to getting libclang working with Python.  If you follow his steps the basic pipeline is:

  • Compile libclang
  • Add libclang to your PATH environment variable
    • On *Nix it’s LD_LIBRARY_PATH
    • On Windows it’s the standard PATH
    • Or do it in python: os.environ['PATH'] = ‘/path/to/libclang’
  • Copy the Clang/Python bindings from /llvm/tools/clang/bindings/python to your python installation or however you’d prefer to install it.
  • Verify it works by opening a python console and typing: improt clang.cindex
  • Squee when it works

[Example]

Once libclang is tied to Python it’s time to test your code.  When I got to this step I had trouble finding any good examples.  There are really only 2 and they can be found in your Clang installation folder: llvm\tools\clang\bindings\python\examples\cindex.  Others can be gleaned from blog posts and StackOverflow.  Here is a simple example I adapted that looks specifically for the LINKAGE_SPEC cursor type. LINKAGE_SPEC refers to code like `extern “C”`

#!/usr/bin/env pythonimport os
import sys
from pprint import pprint
import clang.cindex
os.environ['PATH'] = os.environ['PATH']  + os.getcwd()def get_info(node, depth=0):return { 'kind' : node.kind,'usr' : node.get_usr(),'spelling' : node.spelling,'location' : node.location,'extent.start' : node.extent.start,'extent.end' : node.extent.end,'is_definition' : node.is_definition()}def output_cursor_and_children(cursor, level=0):#LINKAGE_SPEC (http://clang.llvm.org/doxygen/classclang_1_1LinkageSpecDecl.html)#Represents code of the type:  extern "C" void foo()if cursor.kind == clang.cindex.CursorKind.LINKAGE_SPEC:pprint(('nodes', get_info(cursor)))# Recurse for children of this cursorhas_children = False;for c in cursor.get_children():if not has_children:has_children = Trueoutput_cursor_and_children(c, level+1)def main():from clang.cindex import Indexfrom pprint import pprintfrom optparse import OptionParser, OptionGroupglobal optsparser = OptionParser("usage: %prog {filename} [clang-args*]")parser.disable_interspersed_args()(opts, args) = parser.parse_args()if len(args) == 0:print 'invalid number arguments'index = Index.create()tu = index.parse(None, args)if not tu:print "unable to load input"output_cursor_and_children(tu.cursor)if __name__ == '__main__':main()
#include "test.h"int main(){Foo f;return 0;
}
#ifndef TEST_H
#define TEST_Hclass Foo 
{int data_;
public:Foo(){}void bar(int data){data_ = data;}
};extern "C" __declspec( dllexport )void test1(){}#endif

How to run:

python linkage_dump.py test.cpp

clangarang

[Conclusion]

There are so many other ways to make use of ASTs and I wish I had more time to include some of them.  Suffice it to say I’ll probably end up posting about ASTs a few more times.  At least until I work through enough examples to meet my immediate needs.

这篇关于Clang AST parsing for automated code generation的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/612555

相关文章

org.hibernate.hql.ast.QuerySyntaxException:is not mapped 异常总结

org.hibernate.hql.ast.QuerySyntaxException: User is not mapped [select u from User u where u.userName=:userName and u.password=:password] 上面的异常的抛出主要有几个方面:1、最容易想到的,就是你的from是实体类而不是表名,这个应该大家都知道,注意

Debugging Lua Project created in Cocos Code IDE creates “Waiting for debugger to connect” in Win-7

转自 I Installed Cocos Code IDE and created a new Lua Project. When Debugging the Project(F11) the game window pops up and gives me the message waiting for debugger to connect and then freezes. Also a

LLVM入门2:如何基于自己的代码生成IR-LLVM IR code generation实例介绍

概述 本节将通过一个简单的例子来介绍如何生成llvm IR,以Kaleidoscope IR中的例子为例,我们基于LLVM接口构建一个简单的编译器,实现简单的语句解析并转化为LLVM IR,生成对应的LLVM IR部分,代码如下,文件名为toy.cpp,先给出代码,后面会详细介绍每一步分代码: #include "llvm/ADT/APFloat.h"#include "llvm/ADT/S

Python安装llama库出错“metadata-generation-failed”

Python安装llama库出错“metadata-generation-failed” 1. 安装llama库时出错2. 定位问题1. 去官网下载llama包 2.修改配置文件2.1 解压文件2.2 修改配置文件 3. 本地安装文件 1. 安装llama库时出错 2. 定位问题 根据查到的资料,发现时llama包中的execfile函数已经被下线了,需要我们手动修改代码后

VS Code 调试go程序的相关配置说明

用 VS code 调试Go程序需要在.vscode/launch.json文件中增加如下配置:  // launch.json{// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// For more information,

code: 400, msg: Required request body is missing 错误解决

引起这个错误的原因是,请求参数按照get方式给。 应该给json字符串才对 补充: 1. @RequestBody String resource 加@RequestBody必须给json字符串,否则会报错400,记如标题错误。 不加这个的进行请求的话,其实post和get就没有什么区别了。 2. List<String> indexCodes=(List<String>)json.

iOS项目发布提交出现invalid code signing entitlements错误。

1、进入开发者账号,选择App IDs,找到自己项目对应的AppId,点击进去编辑, 2、看下错误提示出现  --Specifically, value "CVYZ6723728.*" for key "com.apple.developer.ubiquity-container-identifiers" in XX is not supported.-- 这样的错误提示 将ubiquity

clang: error: no such file or directory: '/Users/bigxin/Desktop/not file xxx

这样的问题,解决方法有以下几种: 第一:一般多人开发的时候会出现文件缺失的问题,遇到这个问题就根据提示找到对应的地址,然后会发现这个文件名字是红色的把红色的文件删除,然后重新addfile,然后把缺失的文件拷贝过来就可以了。。第二:如果第一种方法不行的话,可以移步到 TARGETS —-> Build Phases ——> Compile Sources(编译源) 里面来找,看有没有失效的文件

解决服务器VS Code中Jupyter突然崩溃的问题

问题 本来在服务器Anaconda的Python环境里装其他的包,装完了想在Jupyter里写代码验证一下有没有装好,一运行发现Jupyter崩溃了!?报错如下所示 Failed to start the Kernel. ImportError: /home/hujh/anaconda3/envs/mia/lib/python3.12/lib-dynload/_sqlite3.cpython-

Behind the Code:与 Rakic 和 Todorovic 对话 OriginTrail 如何实现 AI 去中心化

原文:https://www.youtube.com/watch?v=ZMuLyLCtE3s&list=PLtyd7v_I7PGnko80O0LCwQQsvhwAMu9cv&index=12 作者:The Kusamarian 编译:OneBlock+ 随着人工智能技术的飞速发展,一系列前所未有的挑战随之而来:模型的衰退与互联网的潜在威胁愈发明显。AI 的增长曲线可能因训练过程中的瓶颈而趋于平