Updated the answer with something that may have more promise.
Sorry this is not a full answer, but I wanted to get something to you...
To begin, @Pete Becker has the best answer pertaining to why C++ does not throw warnings. So, this answer will mainly attempt to give you some kind of direction to get all of the undefined functions.
Getting Def Methods
I have found the following command to produce an output of all of the functions within a given .o
file that have a definition. It does include the namespaces, but this is not designed to be the whole solution.
nm -C <object file> | grep '(.*)' | grep -oP '(?<= \w ).*'
The first grep
just returns all of the lines that contain functions, then the second actually grabs the functions.
First Attempt
Combining this with some Python I was able to produce the following:
import os
import re
def getDefMethods(object_file):
file = os.popen("nm -C %s | grep '(.*)' | grep -oP '(?<= \w ).*'"%object_file)
lines = file.readlines()
result = []
for i in lines:
# Removes the namespaces to some degree...
result.append(re.search("([^\:]*\(.*\))", i).groups[0])
return result
def getMethods(header):
file = open(header, 'r')
lines = file.readlines()
result = []
for i in lines:
match = re.search(".*\s(\w*\(.*\))", i)
if match != None:
result.append(match.groups()[0])
return result
def getUndMethods(object_file, header):
defs = getDefMethods(object_file)
fs = getMethods(header)
result = []
for i in fs:
found = False
for j in defs:
if i == j:
found = True
defs.remove(j)
break
if not found:
result.append(i)
return result
Disclaimer
Now, this is not a full solution that handles everything you can throw at it nor is this the fastest, but it does give you a good starting point. (This applies to the update as well.)
Update
Found the library CastXML that takes C++ and spits out an XML file pertaining to the code.
Using that and an XML parser in Python I came up with the following that should handle a lot more cases.
import os
import xml.etree.ElementTree as ET
def_methods = []
all_methods = []
und_methods = []
def getDefMethods(object_file):
file = os.popen("nm -C %s | grep '(.*)' | grep -oP '(?<= \w ).*'"%object_file)
result = file.readlines()
result = [line.rstrip('\n') for line in result]
def_methods.extend(result);
return result
def getID(root, id):
if id != None:
for elem in root.iter():
if elem.get('id') == id:
return elem
return None
def buildNamespace(root, elem, first):
if elem == None or elem.get('name') == "::":
return ""
id = None
if elem.get('context') != None:
id = elem.get('context')
elif elem.get('type') != None:
id = elem.get('type')
if first:
namespace = elem.get('name')
else:
namespace = elem.get('name') + "::"
namespace = buildNamespace(root,getID(root,id),false) + namespace
return namespace
def buildArgs(root, function):
result = "("
args = function.findall('Argument')
for arg in args:
name = arg.get('name')
type = buildNamespace(root, getID(root,arg.get('type')),true)
result += type + " " + name + ", "
if result.endswith(", "):
result = result[:-2]
return result + ")"
def getMethods(file_name):
xml = "%s.xml"%file_name
os.system(("gccxml %s.cpp -fxml="%file_name) + xml)
result = []
tree = ET.parse(xml)
root = tree.getroot()
functions = root.findall('Function')
for function in functions:
f = function.get('name')
f += buildArgs(root,function)
f = buildNamespace(root,getID(root,function.get('context')),false) + f
result.append(f)
methods.extend(result)
return result
def getUndMethods(object_file, file_name):
defs = getDefMethods(object_file)
fs = getMethods(file_name)
result = []
for i in fs:
found = False
for j in defs:
if i == j:
found = True
defs.remove(j)
break
if not found:
result.append(i)
und_methods.extend(result)
return result
Example
import test as methodFinder
methodFinder.getUndMethods("a.o", "a")
print "All Methods defined in object file\n"
for method in methodFinder.def_methods:
print method, "\n"
print "All Methods in file\n"
for method in methodFinder.methods:
print method, "\n"
print "Undefined Methods\n"
for method in methodFinder.und_methods:
print method, "\n"
NOTE: I have not had the time nor the environment to test the above code. So, if you find a stupid please attempt to fix it. Also, I know that is bad that the code has not been tested, but I wanted to give you something that I am pretty confident will handle a lot of methods.
Hope this helps!