1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
#!/usr/bin/env python3
import os
import sys
import json
import clang.cindex
def find_child_of_kind(node, kind):
if node.kind == kind:
return node
for child in node.get_children():
found_type = find_child_of_kind(child, kind)
if found_type:
return found_type
def get_types_from_annotation(annotation):
return [t.replace(" ", "") for t in annotation.split(",")]
def parse_call_expr(call_expr):
if call_expr.spelling == "hash_map_get" or call_expr.spelling == "hash_map_insert":
args = list(call_expr.get_arguments())
# First arg
self_obj = next(args[0].get_children(), None)
self_obj_def = self_obj.get_definition()
annotation = next(self_obj_def.get_children(), None)
if not annotation or annotation.kind != clang.cindex.CursorKind.ANNOTATE_ATTR:
print("WARNING: Hash map at %s is not annotated" % args[0].location)
return
(hash_map_key_type, hash_map_value_type) = get_types_from_annotation(annotation.spelling)
hash_map_value_type = hash_map_value_type + "*"
# Second arg
#key_arg_type = args[1].type.spelling.replace(" ", "")
#if key_arg_type != hash_map_key_type:
# print("Error: Incorrect usage of %s key argument found at %s." % (call_expr.spelling, args[1].location))
# print(" Argument variable is of type %s, but the HashMap expects a value of type %s" % (key_arg_type, hash_map_key_type))
# Third arg
value_obj = next(args[2].get_children(), None)
value_arg_type = value_obj.type.spelling.replace(" ", "")
if value_arg_type != hash_map_value_type:
print("ERROR: Incorrect usage of %s value argument found at %s." % (call_expr.spelling, args[2].location))
print(" Argument variable is of type %s, but the HashMap expects a value of type %s" % (value_arg_type, hash_map_value_type))
#print("def: %s, loc: %s" % (self_obj.get_definition(), self_obj.get_definition().location))
def parse(node):
if node.kind == clang.cindex.CursorKind.CALL_EXPR:
parse_call_expr(node)
for child in node.get_children():
parse(child)
def compile_commands_get_files(compile_commands_filepath):
files = []
with open(compile_commands_filepath) as json_file:
data = json.load(json_file)
for obj in data:
filepath = os.path.join(obj["directory"], obj["file"])
files.append(filepath)
return files
def main():
script_path = os.path.realpath(sys.argv[0])
script_dir = os.path.dirname(script_path)
compile_commands_file = os.path.join(script_dir, "..", "compile_commands.json")
if not os.path.isfile(compile_commands_file):
print("compile_commands.json file is missing! You need to compile amalgam before running this script")
exit(1)
idx = clang.cindex.Index.create()
for filepath in compile_commands_get_files(compile_commands_file):
#print("Parsing file: %s" % filepath)
tu = idx.parse(filepath, args=['-std=c89'], options=0)
parse(tu.cursor)
if __name__ == "__main__":
main()
|