VarDecl 的源范围

问题描述 投票:0回答:1

我正在访问以下代码的 AST:

int x = 123;

VisitVarDecl( VarDecl *d )
中,我想要整个表达式的源范围。我期待一些直观的东西,如
d->print()
打印:
int x = 123

d->getSourceRange()
以“1”结尾。也就是说,它仅由类型组成(请参阅 clang 源代码)。

如果我想要整个事情,我需要做类似的事情:

auto end_loc = Lexer::getLocForEndOfToken( d->getTypeSourceInfo()->getTypeLoc().getEndLoc(), 0, sm, LangOptions() );
auto src_range = SourceRange( d->getSourceRange().getBegin(), end_loc );

有人可以详细说明一下吗?我希望有一个简单的声明方法能够给我一个“直观”的源范围。

这是一个简单的示例,适用于其他声明,例如 TypeAliasDecl。

libtooling
1个回答
0
投票

通常,Clang AST 节点将“结束”位置记录为被视为该节点子树一部分的最后一个标记的起始字符。 Clang 编译器前端 (CFE) 内部手册有一个关于此主题的简短部分

SourceRange 和 CharSourceRange

Clang 用 [first, last] 表示大多数源范围,其中“first”和“last”分别指向各自标记的开头。例如,考虑以下语句的

SourceRange

x = foo + bar;
^first    ^last

要从此表示映射到基于字符的表示,需要调整“最后”位置以指向(或过去)带有

Lexer::MeasureTokenLength()
Lexer::getLocForEndOfToken()
的标记的末尾。对于需要字符级源范围信息的极少数情况,我们使用
CharSourceRange
类。

因此,您问题中概述的方法确实是找到 AST 节点的范围必须采取的方法。

Clang 源代码中这种用法的一个随机示例位于

DurationDivisionCheck.cpp
:

      << FixItHint::CreateInsertion(
             Lexer::getLocForEndOfToken(
                 Result.SourceManager->getSpellingLoc(OpCall->getEndLoc()), 0,
                 *Result.SourceManager, Result.Context->getLangOpts()),
             ")");

上面是针对运算符表达式而不是声明,但对于两个构造的结束位置使用相同的方法。

最后一点,语句 AST 节点的“结束”通常包括终止分号;相反,它以分号之前的标记结尾(当有分号时)。 请参阅 Q+A 为什么对于以分号结尾的语句,源位置会以两个字符结尾? 了解更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.