summaryrefslogtreecommitdiffstats
path: root/compilerplugins/clang/fieldcast.py
diff options
context:
space:
mode:
Diffstat (limited to 'compilerplugins/clang/fieldcast.py')
-rwxr-xr-xcompilerplugins/clang/fieldcast.py71
1 files changed, 71 insertions, 0 deletions
diff --git a/compilerplugins/clang/fieldcast.py b/compilerplugins/clang/fieldcast.py
new file mode 100755
index 0000000000..fc09063571
--- /dev/null
+++ b/compilerplugins/clang/fieldcast.py
@@ -0,0 +1,71 @@
+#!/usr/bin/python3
+
+import re
+import io
+
+definitionSet = set()
+definitionToSourceLocationMap = dict()
+definitionToTypeMap = dict()
+castMap = dict()
+
+# clang does not always use exactly the same numbers in the type-parameter vars it generates
+# so I need to substitute them to ensure we can match correctly.
+normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+")
+def normalizeTypeParams( line ):
+ return normalizeTypeParamsRegex.sub("type-parameter-?-?", line)
+
+
+with io.open("workdir/loplugin.fieldcast.log", "r", buffering=1024*1024) as txt:
+ for line in txt:
+ tokens = line.strip().split("\t")
+ if tokens[0] == "cast:":
+ fieldInfo = (normalizeTypeParams(tokens[1]), tokens[2])
+ fieldType = tokens[3]
+ srcLoc = tokens[4]
+ castToType = tokens[5]
+ # ignore external source code
+ if srcLoc.startswith("external/"):
+ continue
+ # ignore build folder
+ if srcLoc.startswith("workdir/"):
+ continue
+ definitionSet.add(fieldInfo)
+ definitionToTypeMap[fieldInfo] = fieldType
+ definitionToSourceLocationMap[fieldInfo] = srcLoc
+
+ if not (fieldInfo in castMap):
+ castMap[fieldInfo] = castToType
+ elif castMap[fieldInfo] != "": # if we are not ignoring it
+ # if it is cast to more than one type, mark it as being ignored
+ if castMap[fieldInfo] != castToType:
+ castMap[fieldInfo] = ""
+ else:
+ print( "unknown line: " + line)
+
+outputSet = set()
+for k, v in castMap.items():
+ if v == "":
+ continue
+ srcLoc = definitionToSourceLocationMap[k]
+ outputSet.add((k[0] + " " + k[1] + " " + definitionToTypeMap[k], srcLoc, v))
+
+# sort the results using a "natural order" so sequences like [item1,item2,item10] sort nicely
+def natural_sort_key(s, _nsre=re.compile('([0-9]+)')):
+ return [int(text) if text.isdigit() else text.lower()
+ for text in re.split(_nsre, s)]
+# sort by both the source-line and the datatype, so the output file ordering is stable
+# when we have multiple fields declared on the same source line
+def v_sort_key(v):
+ return natural_sort_key(v[1]) + [v[0]]
+
+# sort results by name and line number
+tmp1list = sorted(outputSet, key=lambda v: v_sort_key(v))
+
+# print out the results
+with open("compilerplugins/clang/fieldcast.results", "wt") as f:
+ for t in tmp1list:
+ f.write( t[1] + "\n" )
+ f.write( " " + t[0] + "\n" )
+ f.write( " " + t[2] + "\n" )
+
+