This is resolvable using callgraph data generated by Clang.
Step 1. Generate call schedule information with clang:
clang -S -emit-llvm SourceFile.c -o - | opt -analyze -print-callgraph
(From Create a call graph for C ++ code , replacing -dot-callgraphwith -print-callgraph.)
To enter a type:
void a(){}
void b(){a();}
void c(){a(); b();}
void d(){a(); c();}
void e(){e();}
this will produce:
CallGraph Root is: <<null function: 0x0x7fdef25036c0>>
Call graph node <<null function>><<0x7fdef25036c0>>
CS<0x0> calls function 'a'
CS<0x0> calls function 'b'
CS<0x0> calls function 'c'
CS<0x0> calls function 'd'
Call graph node for function: 'a'<<0x7fdef2503750>>
Call graph node for function: 'b'<<0x7fdef25037d0>>
CS<0x7fdef2500a38> calls function 'a'
Call graph node for function: 'c'<<0x7fdef2503870>>
CS<0x7fdef2500cb8> calls function 'a'
CS<0x7fdef2500d28> calls function 'b'
Call graph node for function: 'd'<<0x7fdef2503970>>
CS<0x7fdef2500fe8> calls function 'a'
CS<0x7fdef2501058> calls function 'c'
Call graph node for function: 'e'<<0x7f8912d03c10>>
CS<0x7f8912d01318> calls function 'e'
( ++ c++filt; , .) , :
2. callgraph , callgraph.
class Graph(object):
_callees = []
def add_callee(self, f):
self._callees.append(f)
3. walk . - :
def walkGraph(node,f,stack):
for callee in node._callees:
if f == callee:
print('Recursion!')
dumpStack(stack,f)
else:
walkGraph(callee,f,stack.append(node))