-
Notifications
You must be signed in to change notification settings - Fork 77
[Clang源码解读] SourceLocation
我们做Clang开发,特别是要对代码进行增删改,都不可避免地会跟SourceLocation
打交代。每一个token或者AST的节点像Decl
, Expression
, 都有类似getLocation
, getLocStart
, getLocEnd
的函数,用于获取该AST节点在代码中的位置。如果想获取对应AST节点的代码,配合着使用SourceManager
和Lexer
就能容易的获取到。
SourceLocation提供了dump函数,输出类似source.cc:<line_number>:<column_number>
易于阅读的信息。
SourceLocation内部是一个32bitinteger
的offset,非常轻量级,拷贝的代价很少,在Clang代码中按值传递。所以SourceLocation可以简单理解成指字符串(这个字符串就是代码)中的offset,指向某个字符。
SourceLocation有一个getLocWithOffset
函数,这个函数用于移动当前的offset,并返回对应的SourceLocation。用来获取相对于SourceLocation的前面或者后面的SourceLocation。
Clang里有SourceRange
, CharSourceRange
的数据结构表示代码里的一个范围(Begin, End)。 CharSourceRange分为两个类型:
- TokenRange,是基于Token的范围。这种类型下的End是指向最后一个token的开始位置,实际范围会包括最后一个token的长度(
lexer::MeasureTokenLength
)。 - CharRange, 是基于Char的范围。这种类型下的End指向最后一个char的位置,实际范围是Begin和End所代表的范围
我们使用Lexer::getSourceText
接口获取某个CharSourceRange的代码块。不过值得注意的是如果是CharRange,最后的End的是不包括,即获取的范围是[begin, end):
vector<Token> toks = ParseSource("int a;");
// tok[0]: int
// tok[1]: a
// tok[2]: ;
SourceRange Range(toks[0].getLocation(), toks[2].getLocEnd());
bool Invalid = false;
// Get "int a"
Lexer::getSourceText(CharSourceRange::getCharRange(Range), SourceMgr, &Invalid);
// Get "int a;"
Lexer::getSourceText(CharSourceRange::getCharRange(SourceRange(toks[0].getLocation(), toks[2].getLocation()().getLocWithOffset(1))),
SourceMgr, &Invalid);
// Get "int a;"
Lexer::getSourceText(CharSourceRange::getTokenRange(Range), SourceMgr, &Invalid);
如果是宏定义怎么处理?SourceManager
提供了相应的接口:
vector<Token> toks = ParseSource(
"#define X(x) x\n"
"X(int a;)");
// Line 2, column 1, 宏展开的位置
toks[0].getLocation();
// Begin: line 2, column 1
// End:Line 2, column 9
// 获取宏展开的位置
SourceRange MacroRange = SourceMgr.getExpansionRange(toks[0].getLocation());
// 获取token[0] int在macro的位置:Line 2, column 3
SourceLocation SpellingLocBegin = SourceMgr.getSpellingLoc(toks[0].getLocation());
// Line 2, column 6
SourceLocation SpellingLocBegin = SourceMgr.getSpellingLoc(toks[0].getLocation());
LLVM/Clang
C/C++
- Get lower 32 bits from uint64
- How to unpack a std::tuple to a function with multiple arguments?
- {}-list Initialization
- Empty macro arguments
- 为什么能在函数中以by value方式返回unique_ptr?
- c++unsigned类型提升
- extern "C"
Linux
- ubuntu获取源码方法
- gcc/g++常用命令
- 浏览器导入安全证书
- ubuntu下宏包latex安装
- Bash Shell常用快捷键
- ubuntu把/tmp目录挂载到内存
- tar命令
- voyager12.04 apt-get install无法安装解决方法
- terminal shows git branch
- 编译GTK API源程序(附带pkg-config用法)
- ldconfig检查库是否存在
- Googletest Setup&Install
- Centos设置service开机自动启动
- CentOS create admin user
- 设置时区
- MySQL修改root密码
- MySQL常用命令
- Screen使用
- 环境变量
- Unity桌面环境的desktop文件
- zip和gzip文件区别
- Linux安全设置
Vim
- vim列编辑
- vim编辑二进制文件
- vim quickfix窗口
- Vim 批量操作
- Vim对多行重复操作
- mac下vim编译安装
- mac下vim taglist无效解决方法
- Vim 配置vim-airline
Tools
- gdb cgdb命令
- Source Insight添加.cc文件
- Source Insight快捷键
- GPT分区转MBR分区
- IRC工具Pidgin使用
- iTerm2 shortcuts
- MacOS shortcuts
- Compile/Run JUnitTest in Command Line
- Install Python2.7 on CentOS 6.4
- Install vmware tool on ubuntu server 12.04
- node-gyp Usage
- zsh中文乱码解决方法
- tmux快捷键
- 使用aria2突破百度云盘限速
- 配置 scheme编写环境
- How to list all available targets in ninja
Others
- CRLF换行符
- Git autocrlf设置
- Git reflog数据恢复命令
- how to migrate from SVN repo to Git repo
- Git submodule使用
- Git Pull强制更新
Chromium-Dev tips