http://gitlab.fjfi.cvut.cz/culikzde/prekl-2022/-/tree/main/clang-tree ===== cindex ===== from clang.cindex import Index, Cursor def print_branch (cursor, level = 0) : txt = level * " " + cursor.kind.name + ": " + cursor.spelling print (txt) for item in cursor.get_children () : print_branch (item, level + 1) index = Index.create () tu = index.parse ("example.cc") for item in tu.diagnostics : print ("MESSAGE:", str (item)) cursor = tu.cursor print_branch (cursor) dnf install python3-clang struct Point { int x, y, z; }; Point g; int main (int argc, char * * argv) { g.x = 1; g.y = g.x + 2; } ===== gcc_options.py ===== import sys, re, subprocess if sys.version_info >= (3,) : def conv (s) : return str (s, "utf-8") else : def conv (s) : return str (s) def gcc_options (gcc = "gcc", complete = False, selected_variables = False) : cmd = "echo 'int main () { }' | " + gcc + " -v -x c++ -dD -E - 2>&1" variables = [ "__GNUC__", "__GNUG__", "__GNUC_MINOR__", "__GNUC_PATCHLEVEL__", "_GNU_SOURCE", "__VERSION__" ] result = [ ] if complete : result.append ("-nostdinc") f = subprocess.Popen (cmd, shell=True, stdout=subprocess.PIPE).stdout incl = False for s in f : s = s.strip () s = conv (s) if re.match ("End of search list.", s) : incl = False if incl and s != "" : # s = os.path.normpath (s) # result.append ("-I " + s) result.append ("-I") result.append (s) # two items "-I", "directory", # one item "-Idirectory" # NOT one item "-I directory" # if re.match ("#include \"...\" search starts here:", s) : # incl = True if re.match ("#include <...> search starts here:", s) : incl = True m = re.match ("#define (\\w+) (.*)", s) if m : name = m.group (1) value = m.group (2) # if name == "__VERSION__" : # value = value.replace (" ", "_") if name in variables or not selected_variables: if complete : result.append ("-U " + name) result.append ("-D " + name + "=" + value) f.close () return result def pkg_options (pkg, libs = False) : cmd = "pkg-config " + pkg + " --cflags" if libs : cmd = cmd + " --libs" f = subprocess.Popen (cmd, shell=True, stdout=subprocess.PIPE).stdout result = [ ] for s in f : s = s.strip () s = conv (s) for t in s.split () : result.append (t) return result if __name__ == "__main__" : gcc = "gcc" if len (sys.argv) == 2 : gcc = sys.argv [1] result = gcc_options (gcc, complete = True, selected_variables = True) for s in result : print (s) ===== cindex 2 ===== from gcc_options import gcc_options from clang.cindex import Index, Cursor, CursorKind def print_object (obj) : for name in dir (obj) : try : print (name, "=", getattr (obj, name)) except : pass def print_branch (cursor, level = 0, enabled = False) : txt = level * " " + cursor.kind.name + ": " + cursor.spelling if txt.find ("printf") >= 0: enabled = True if enabled : # print (txt) pass if cursor.kind == CursorKind.DECL_REF_EXPR and cursor.spelling == "printf": print ("CALL", cursor.spelling) print_object (cursor) for item in cursor.get_children () : print_branch (item, level + 1, enabled) opts = gcc_options (gcc = "clang", complete=True) # print ("OPTIONS:", opts) index = Index.create () tu = index.parse ("example.cc", opts) for item in tu.diagnostics : print ("MESSAGE:", str (item)) cursor = tu.cursor print_branch (cursor) #include struct Point { int x, y, z; }; Point g; int main (int argc, char * * argv) { g.x = 1; g.y = g.x + 2; printf ("Hello g.y = %d \n", g.y); } clang -Xclang -ast-dump example.cc clang -Xclang -ast-dump example.cc | less -R clang -S -emit-llvm example.cc -o example.ll http://kmlinux.fjfi.cvut.cz/~culikzde/prekl/llvm-plugin-07-fedora27.tgz