Add script to verify proper Memset template use

Since there does not seem to be any elegant way of
checking whether a class is the first base class in
c++ (given that the 2009 c++ proposal n2965 was
rejected), this python script does it by scanning
all source files for illegal patterns.

The python file was implemented in a way to enable
easy addition of further checks, should need arise.

Bug: b/152253831
Change-Id: I25701a3302579700ccb6222141843d27f38d9069
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/49788
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Jari Komppa <jari@siru.fi>
diff --git a/tests/presubmit.sh b/tests/presubmit.sh
index 20b0b61..10ccf53 100755
--- a/tests/presubmit.sh
+++ b/tests/presubmit.sh
@@ -84,6 +84,10 @@
   go run ${TESTS_DIR}/check_build_files/main.go --root="${ROOT_DIR}"
 }
 
+function run_scan_sources() {
+  python3 ${TESTS_DIR}/scan_sources/main.py ${SRC_DIR}
+}
+
 # Ensure we are clean to start out with.
 check "git workspace must be clean" true
 
@@ -102,5 +106,8 @@
 # Check build files.
 check "build files don't reference non-existent files" run_check_build_files
 
+# Check source files.
+check scan_sources run_scan_sources
+
 echo
 echo "${green}All check completed successfully.${normal}"
diff --git a/tests/scan_sources/main.py b/tests/scan_sources/main.py
new file mode 100644
index 0000000..d9bab46
--- /dev/null
+++ b/tests/scan_sources/main.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python3
+
+# Copyright 2020 The SwiftShader Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Scan all source files for problems that are inconvenient or impossible
+# to guard against using static assertions in c++
+
+import glob
+import sys
+import re
+
+def main(rootdir):
+	filelist = []
+	for x in [rootdir +"/**/*.cpp", rootdir + "/**/*.hpp"]:
+		filelist += glob.glob(x, recursive=True)
+
+	# Regex for Memset< template use as base class (must be the first,
+	# thus, there must not be a ',' before it)
+	memset_template_check = re.compile(",\s*Memset\s*<")
+	
+	# Regex for Memset( template use as initializer (must be the first,
+	# thus, there must not be a ',' before it)
+	memset_call_check = re.compile(",\s*Memset\s*\(")
+
+	retval = 0
+
+	tb = 0
+	for fn in filelist:
+		with open(fn, encoding="utf-8") as f:
+			contents = f.read();
+			if memset_template_check.search(contents) != None:
+				print("ERROR: " + fn + " has illegal memset<> template use: must always be the first base class.")
+				retval = 1
+			if memset_call_check.search(contents) != None:
+				print("ERROR: " + fn + " has illegal memset<> template use: not called as the first initializer.")
+				retval = 1
+
+	sys.exit(retval)
+
+if len(sys.argv) < 2:
+	print("Give source directory as parameter.")
+	sys.exit(1)
+main(sys.argv[1])
\ No newline at end of file