【问题标题】:Retrieve information about pre-processor directives检索有关预处理器指令的信息
【发布时间】:2012-12-02 14:54:48
【问题描述】:

我最近开始使用 libclang 来解析 C 文件。我遇到的问题显然是,libclang 在生成 AST 之前启动了预处理器。我想禁止预处理器运行,而是提供预处理器指令在文件中的信息...

我使用以下 python 脚本(cindex.py 和 libclang)

import codecs
from clang.cindex import *

class SourceFile(object):
    def __init__(self, path):
        with codecs.open(path, 'r', 'utf-8') as file:
            self.file_content = file.read()

        index = Index.create()
        root_node = index.parse(path)

        for included in root_node.get_includes():
            print included.include

        self.print_declerations(root_node.cursor)

    def print_declerations(self, root, recurse=True):
        print root.kind.name, root.spelling
        if root.kind.is_declaration():
            node_def = root.get_definition()
            if node_def is not None:
                start_offset = node_def.extent.start.offset
                end_offset = node_def.extent.end.offset + 1
                print self.file_content[start_offset:end_offset], '\n'

        if recurse:
            for child in root.get_children():
                self.print_declerations(child, False)

if __name__ == '__main__':
    path = 'Sample.cpp'
    print 'Translation unit:', path
    source = SourceFile(path)

哪些输出

Translation unit: Sample.cpp
/mingw/include\stdio.h
/mingw/include\_mingw.h
/mingw/include\sys/types.h
TRANSLATION_UNIT None
TYPEDEF_DECL __builtin_va_list

STRUCT_DECL _iobuf

TYPEDEF_DECL FILE

VAR_DECL _iob
UNEXPOSED_DECL 

FUNCTION_DECL main
int main()
{
    printf(HELLO_WORLD);
    return 0;
}

对于以下 C 代码:

#include <stdio.h>
#define HELLO_WORLD "HELLO!"

int main()
{
    printf(HELLO_WORLD);
    return 0;
}

我想要的是在代码中为我的#define 获取 DEFINE_DECL HELLO_WORLD(目前我什么也得不到)。当然,我的#include 也有类似的声明。这可能吗?

编辑:基本上,我想在不扩展预处理器指令的情况下解析文件。

【问题讨论】:

  • 如果你愿意考虑 Clang 以外的其他东西,我有一个替代解决方案。

标签: c++ serialization clang libclang


【解决方案1】:

几天前,我在#llvm freenode irc 频道上问了同样的问题。答案是“macroses 不是 AST 的一部分,所以你不能”,但很可能是“-fsyntax-only”选项和 clang 插件而不是 libclang 可能会对你有所帮助。

已编辑:看起来现在实际上是可能的,请参阅 bradtgmurray 的回答

【讨论】:

  • 你的意思是写我自己的clang插件吗?还是有一个实际上称为clang插件的插件?并不是谷歌上最容易使用的短语。
  • 检查“clang”并查看“示例”文件夹。 “PrintFunctionNames”和“analyzer-plugin”可能是开始的地方。
【解决方案2】:

如果您将 PARSE_DETAILED_PROCESSING_RECORD 作为选项添加到对 index.parse() 的调用中,您将可以访问预处理器节点。

index = clang.cindex.Index.create()                                                                         
tu = index.parse(filename, options=clang.cindex.TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD)

此选项映射到以下 libclang C API 选项值。那里有一条评论,其中包含更多上下文。

/**                                                                         
 * \brief Used to indicate that the parser should construct a "detailed"    
 * preprocessing record, including all macro definitions and instantiations.
 *                                                                          
 * Constructing a detailed preprocessing record requires more memory        
 * and time to parse, since the information contained in the record         
 * is usually not retained. However, it can be useful for                   
 * applications that require more detailed information about the            
 * behavior of the preprocessor.                                            
 */                                                                         
CXTranslationUnit_DetailedPreprocessingRecord = 0x01,   

【讨论】:

  • 今天也找到了这个。回到这里添加新的答案,但在这里。没有什么可添加的。
  • 请注意,文档是错误的。它不包括所有宏实例化,而仅包括那些本身不在宏实例化中的宏实例化(因此,只跟踪一级宏扩展)。你可以注释掉PreprocessingRecord::addMacroExpansion开头的if来改变这个。
  • _DetailedPreprocessingRecord 会导致检测到所有宏(即使是那些应该被忽略的宏,因为它们是由预处理器条件“#ifdef _BLAH \n #define _FLAG \n #endif”预测的)。我怎么能只过滤掉相关的?
  • ^^^ 好吧,如果您使用 CXTranslationUnit_SingleFileParse 标志进行解析,那么对于其他想知道发生了什么的人来说,您将可以访问所有宏(不删除我之前的评论,可能对某人有帮助)。
【解决方案3】:

如果您使用命令行参数作为调用 libclang 的一种方式,这里是来自 libclang C API 实现的相关代码:

// Do we need the detailed preprocessing record?
if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
  Args->push_back("-Xclang");
  Args->push_back("-detailed-preprocessing-record");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多