14

使用 libclang,我在 AST 中有一个游标,它对应于宏扩展产生的语句。我想检索原始的、未扩展的宏文本。

我一直在寻找一个 libclang API 来执行此操作,但找不到。我错过了什么吗?

假设不存在这样的 API,我看到了几种方法可以做到这一点,它们都基于使用 clang_getCursorExtent() 来获取光标的源范围——大概是原始文本的范围。

第一个想法是使用 clang_getFileLocation() 获取文件名和位置以及范围开始和结束,并直接从文件中读取文本。如果我是从未保存的文件编译的,那么我需要处理这个问题,但我对这种方法的主要担忧是,当我确定 clang 在内部保存所有这些信息时,似乎不适合到文件系统之外. 如果 AST 已经加载而不是生成,或者源文件在解析后被修改,也会产生影响。

第二种方法是在游标范围上调用 clang_tokenize()。我尝试这样做,发现它无法为 AST 中的大多数游标生成令牌列表。跟踪代码,发现内部 clang_tokenize() 操作了提供的范围并最终得出结论它跨越多个文件(可能是由于宏扩展的某些影响),然后中止。这对我来说似乎不正确,但我确实觉得无论如何我都在滥用 clang_tokenize() 试图做到这一点。

那么,最好的方法是什么?

4

1 回答 1

12

这是我找到的唯一方法。

因此,您可以使用clang_getTranslationUnitCursor(). 然后,您clang_visitChildren()将访问者函数传递给此返回CXChildVisit_Continue,以便仅返回直接子级。在孩子中,您会看到顶级声明的常用游标类型(如CXCursor_TypedefDecl, CXCursor_EnumDecl),但其中也有CXCursor_MacroExpansion. 每个宏扩展似乎都显示在具有这种类型的光标中。然后,您可以调用clang_tokenize()这些游标中的任何一个,它会为您提供未扩展的宏文本。

我不知道为什么宏扩展卡在 AST 的顶部附近,而不是在使用它们的元素中,这让事情变得很尴尬。例子:

enum someEnum{
    one = SOMEMACRO,
    two,
    three
}

如果 SOMEMACRO 的宏扩展光标在枚举声明中而不是它的兄弟,那就太好了。

(我意识到这已经很晚了,但我希望这能让 libclang 获得更多曝光,也许对它更有经验的人可以提供更多见解)。

于 2013-09-29T05:44:36.503 回答