1#!/usr/local/bin/python3.8 2 3import sys 4import re 5import io 6 7callDict = dict() # callInfo tuple -> callValue 8definitionToSourceLocationMap = dict() 9paramSet = set() # paraminfo tuple 10 11# clang does not always use exactly the same numbers in the type-parameter vars it generates 12# so I need to substitute them to ensure we can match correctly. 13normalizeTypeParamsRegex = re.compile(r"type-parameter-\d+-\d+") 14def normalizeTypeParams( line ): 15 return normalizeTypeParamsRegex.sub("type-parameter-?-?", line) 16 17# reading as binary (since we known it is pure ascii) is much faster than reading as unicode 18with io.open("workdir/loplugin.virtualdead.log", "r", encoding="ascii", errors="ignore", buffering=1024*1024) as txt: 19 for line in txt: 20 try: 21 tokens = line.strip().split("\t") 22 if tokens[0] == "virtual:": 23 nameAndParams = normalizeTypeParams(tokens[1]) 24 sourceLocation = tokens[2] 25 returnValue = tokens[3] 26 callInfo = (nameAndParams, sourceLocation) 27 if not callInfo in callDict: 28 callDict[callInfo] = set() 29 callDict[callInfo].add(returnValue) 30 definitionToSourceLocationMap[nameAndParams] = sourceLocation 31 elif tokens[0] == "param:": 32 name = normalizeTypeParams(tokens[1]) 33 if len(tokens)>2: 34 bitfield = tokens[2] 35 paramSet.add((name,bitfield)) 36 else: 37 print( "unknown line: " + line) 38 except IndexError: 39 print("problem with line " + line.strip()) 40 raise 41 42tmp1list = list() 43for callInfo, callValues in iter(callDict.items()): 44 nameAndParams = callInfo[1] 45 if len(callValues) != 1: 46 continue 47 callValue = next(iter(callValues)) 48 if "unknown-stmt" in callValue: 49 continue 50 if "unknown2" in callValue: 51 continue 52 if "unknown3" in callValue: 53 continue 54 if "unknown4" in callValue: 55 continue 56 if "pure" in callValue: 57 continue 58 srcloc = callInfo[1] 59 if srcloc.startswith("workdir/"): continue 60 # ignore Qt stuff 61 if srcloc.startswith("Gui/"): continue 62 if srcloc.startswith("Widgets/"): continue 63 if srcloc.startswith("Core/"): continue 64 if srcloc.startswith("/Qt"): continue 65 if srcloc.startswith("Qt"): continue 66 if srcloc.startswith("64-"): continue 67 functionSig = callInfo[0] 68 tmp1list.append((srcloc, functionSig, callValue)) 69 70def merge_bitfield(a, b): 71 if len(a) == 0: return b 72 ret = "" 73 for i, c in enumerate(b): 74 if c == "1" or a[i] == "1": 75 ret += "1" 76 else: 77 ret += "0" 78 return ret; 79tmp2dict = dict() 80tmp2list = list() 81for paramInfo in paramSet: 82 name = paramInfo[0] 83 bitfield = paramInfo[1] 84 if re.match( r"\w+ com::", name): continue 85 if re.match( r"\w+ ooo::vba::", name): continue 86 if re.match( r"\w+ orcus::", name): continue 87 if re.match( r"\w+ std::", name): continue 88 if not name in tmp2dict: 89 tmp2dict[name] = bitfield 90 else: 91 tmp2dict[name] = merge_bitfield(tmp2dict[name], bitfield) 92for name, bitfield in iter(tmp2dict.items()): 93 srcloc = definitionToSourceLocationMap[name] 94 # ignore Qt stuff 95 if srcloc.startswith("Gui/"): continue 96 if srcloc.startswith("Widgets/"): continue 97 if srcloc.startswith("Core/"): continue 98 if srcloc.startswith("/Qt"): continue 99 if srcloc.startswith("Qt"): continue 100 if srcloc.startswith("64-"): continue 101 # ignore external stuff 102 if srcloc.startswith("workdir/"): continue 103 # referenced by generated code in workdir/ 104 if srcloc.startswith("writerfilter/source/ooxml/OOXMLFactory.hxx"): continue 105 if "0" in bitfield: 106 tmp2list.append((srcloc, name, bitfield)) 107 108# sort results by filename:lineno 109def natural_sort_key(s, _nsre=re.compile('([0-9]+)')): 110 return [int(text) if text.isdigit() else text.lower() 111 for text in re.split(_nsre, s)] 112# sort by both the source-line and the datatype, so the output file ordering is stable 113# when we have multiple items on the same source line 114def v_sort_key(v): 115 return natural_sort_key(v[0]) + [v[1]] 116tmp1list.sort(key=lambda v: v_sort_key(v)) 117tmp2list.sort(key=lambda v: v_sort_key(v)) 118 119# print out the results 120with open("compilerplugins/clang/virtualdead.results", "wt") as f: 121 for v in tmp1list: 122 f.write(v[0] + "\n") 123 f.write(" " + v[1] + "\n") 124 f.write(" " + v[2] + "\n") 125with open("compilerplugins/clang/virtualdead.unusedparams.results", "wt") as f: 126 for v in tmp2list: 127 f.write(v[0] + "\n") 128 f.write(" " + v[1] + "\n") 129 f.write(" " + v[2] + "\n") 130