查询Clang文档,发现是调用C++的clang_getDiagnostic
函数接口获取的。同理查询cindex.py发现如下信息:
("clang_getDiagnostic",
[c_object_p, c_uint],
c_object_p),
其中如下代码引用了:
class TranslationUnit(ClangObject):
# ... (很多代码) ...
@property
def diagnostics(self):
"""
Return an iterable (and indexable) object containing the diagnostics.
"""
class DiagIterator(object):
def __init__(self, tu):
self.tu = tu
def __len__(self):
return int(conf.lib.clang_getNumDiagnostics(self.tu))
def __getitem__(self, key):
diag = conf.lib.clang_getDiagnostic(self.tu, key)
if not diag:
raise IndexError
return Diagnostic(diag)
return DiagIterator(self)
使用举例:
code_str = """
#include "tmp.h"
#include "a/b/c.h"
#define int3 int
class ABC{
public:
SS s;
void run() {
int c = 0;
auto b = EXIT_CODE_ERR;
}
};
class APPLE{
public:
ABCD abc();
void run() {
int a = 0;
if (a > 1) {
abc.run();
} else {
;
}
}
};
static int fac(int n) {
int32 a();
for (a =0; a< 20; a++){
n += a;
}
APPLE apple;
return (n>1) ? n*fac(n-1) : 1;
}
"""
idx = Index.create()
translation_unit = idx.parse('tmp.cpp', args=['-I./', # tmp.h放在当前python同目录
'-std=c++11',
],
unsaved_files=[('tmp.cpp', code_str)],
options=0x1)
for diagnostic in translation_unit.diagnostics:
print(diagnostic)
可打印如下信息:
tmp.cpp:3:10: fatal error: 'a/b/c.h' file not found
注释掉#include "a/b/c.h"
后,再次运行打印如下信息:
tmp.cpp:8:9: error: unknown type name 'SS'
tmp.cpp:11:22: error: use of undeclared identifier 'EXIT_CODE_ERR'
tmp.cpp:17:9: error: unknown type name 'ABCD'
tmp.cpp:29:5: error: unknown type name 'int32'
tmp.cpp:29:12: warning: empty parentheses interpreted as a function declaration [-Wvexing-parse]
可以发觉,报错并不是一次性全部暴露出来的,随着一步一步错误处理,深层次的错误才会暴露。只有所有错误都解决了,libclang才能完整解析出正确的C++ AST