summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2017-04-04 16:35:25 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2017-04-05 06:49:56 +0000
commite3eadc96cc05135880b72c42358eb3fe51ea94c4 (patch)
tree6478330637b3d6b12882fcb4ca60790b5800a87c /compilerplugins
parentff339c89b51ed571d55c762e43aa1a6ee9ada1cb (diff)
teach constantparam plugin to find always on and always off bitmask values
Change-Id: If56a483494bd3d7feb3fa67c01000dddd0d34421 Reviewed-on: https://gerrit.libreoffice.org/36085 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'compilerplugins')
-rwxr-xr-xcompilerplugins/clang/constantparam.py67
1 files changed, 65 insertions, 2 deletions
diff --git a/compilerplugins/clang/constantparam.py b/compilerplugins/clang/constantparam.py
index 2f930187666f..5550c51c34f3 100755
--- a/compilerplugins/clang/constantparam.py
+++ b/compilerplugins/clang/constantparam.py
@@ -4,7 +4,7 @@ import sys
import re
import io
-callDict = dict()
+callDict = dict() # callInfo tuple -> callValue
# 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.
@@ -38,7 +38,7 @@ for callInfo, callValues in callDict.iteritems():
sourceLoc = callInfo[4]
functionSig = callInfo[0] + " " + callInfo[1]
- # try and ignore setter methods
+ # try to ignore setter methods
if ("," not in nameAndParams) and (("::set" in nameAndParams) or ("::Set" in nameAndParams)):
continue
# ignore code that follows a common pattern
@@ -67,4 +67,67 @@ with open("loplugin.constantparam.report", "wt") as f:
f.write(" " + v[1] + "\n")
f.write(" " + v[2] + "\n")
+# -------------------------------------------------------------
+# Now a fun set of heuristics to look for methods that
+# take bitmask parameters where one or more of the bits in the
+# bitmask is always one or always zero
+# integer to hext str
+def hex(i):
+ return "0x%x" % i
+# I can't use python's ~ operator, because that produces negative numbers
+def negate(i):
+ return (1 << 32) - 1 - i
+
+tmp2list = list()
+for callInfo, callValues in callDict.iteritems():
+ nameAndParams = callInfo[1]
+ if len(callValues) < 2:
+ continue
+ # we are only interested in enum parameters
+ if not "enum" in callInfo[3]: continue
+ if not "Flag" in callInfo[3] and not "flag" in callInfo[3] and not "Bit" in callInfo[3] and not "State" in callInfo[3]: continue
+ # try to ignore setter methods
+ if ("," not in nameAndParams) and (("::set" in nameAndParams) or ("::Set" in nameAndParams)):
+ continue
+
+ setBits = 0
+ clearBits = 0
+ continue_flag = False
+ first = True
+ for callValue in callValues:
+ if "unknown" == callValue or not callValue.isdigit():
+ continue_flag = True
+ break
+ if first:
+ setBits = int(callValue)
+ clearBits = negate(int(callValue))
+ first = False
+ else:
+ setBits = setBits & int(callValue)
+ clearBits = clearBits & negate(int(callValue))
+
+ # estimate allBits by using the highest bit we have seen
+ # TODO dump more precise information about the allBits values of enums
+ allBits = (1 << setBits.bit_length()) - 1
+ clearBits = clearBits & allBits
+ if continue_flag or (setBits == 0 and clearBits == 0): continue
+
+ sourceLoc = callInfo[4]
+ functionSig = callInfo[0] + " " + callInfo[1]
+
+ v2 = callInfo[3] + " " + callInfo[2]
+ if setBits != 0: v2 += " setBits=" + hex(setBits)
+ if clearBits != 0: v2 += " clearBits=" + hex(clearBits)
+ tmp2list.append((sourceLoc, functionSig, v2))
+
+
+# sort results by filename:lineno
+tmp2list.sort(key=lambda v: natural_sort_key(v[0]))
+
+# print out the results
+with open("loplugin.constantparam.report-bitmask-params", "wt") as f:
+ for v in tmp2list:
+ f.write(v[0] + "\n")
+ f.write(" " + v[1] + "\n")
+ f.write(" " + v[2] + "\n")