member function of the same class or when
accessing member variables. The pointer can be
implied, meaning that this is not specifically written
but will still be invoked. Because the this pointer
information is explicit in the AST, PAIGE catches
both member functions called inside other member
functions as well as functions of another class called
inside member functions where the object of the
other class is a member variable of the first class.
Doxygen catches neither as it does not parse the this
pointer. An example of how the implied this pointer
looks in the C++ AST is presented in Figure 12.
In Figure 12, m_drawingAPI is a
DrawingAPI-type member variable of class
CircleShape. In the AST, not only is the class of
m_drawingAPI given, but the class of the this
pointer (CircleShape) is also given. Therefore,
PAIGE is able to connect the function
drawCircle to the function definition in the
DrawingAPI class definition.
There are two principal reasons for lapses in
PAIGE’s ability to catch functions that Doxygen
catches. The first principal reason is the state of
development of the Clang AST: it does not currently
accept template classes, for example, and does not
include this code in its AST, so any member
functions of a template class will not be displayed in
a PAIGE call graph. Also, the Clang AST views
static functions as regular functions instead of
member functions and therefore does not include the
function’s class. PAIGE does catch this function, but
displays it as a regular function (and therefore
cannot include any more function calls inside that
function’s definition).
The second principal reason that PAIGE may
catch fewer function calls than Doxygen relates only
to the current PAIGE IG: information is available in
the Clang AST, but has not yet been addressed in the
PAIGE IG. For example, using namespaces in class
definitions: The namespace and class are included in
the function call, but only the class name is included
in the class definition right now, causing some
functions not to show up in the final call graph. But
with some addition to the IG code, this problem
could be easily addressed. Another issue is the use
of function pointers: Doxygen catches the name of
the function, while PAIGE only catches the function
and displays a warning that the name of the function
cannot be caught. The function pointer is displayed
differently in the C++ AST than a regular function
call, so additional work needs to be done to catch the
name of the function. Handling polymorphism also
falls into this class.
One difference between PAIGE and Doxygen is
that PAIGE displays library function calls. This is
necessary because MLSA is meant to process
programs written in multiple computer languages
and display how they interact. Many of these
languages interact through library functions; for
example, Python.h allows python code to be
called in a C/C++ program, so library functions are
key for catching interoperability.
PAIGE also catches all the arguments in call
functions – recall that the PAIGE call graph is a tree
and not a graph – for the same purpose that it
catches library calls. These library functions that
allow interoperability take in arguments that indicate
what cross-language code is being called, giving for
example the name of a program or the actual code
itself.
Figure 13: PAIGE Recursive Function.
Lastly, call graphs were compared to determine
whether recursion is displayed correctly. PAIGE
distinguishes a recursive function call by drawing it
as a leaf node and bordering the node in a dotted
line, as seen in Figure 13. Doxygen only caught
recursive functions in two of the 22 programs that
contained recursive functions. Catching recursion is
clearly important for analyzing a program.
5.2 Clang AST for Objective-C
Clang can process Objective-C source code as well
as C/C++ code. In theory, PAIGE should be able to
generate call graphs for Objective-C from the Clang
AST. PAIGE was tested on five Objective-C
programs. In fact, MLSA did catch all function calls
written in the C/C++-format that used the keyword
CallEpr, which some programs included.
However, it could not catch the majority of
Objective-C function definitions and function calls,
as they were displayed in the AST with Objective-C-
specific keywords – ObjCMethodDecl and
ObjCMessageExpr respectively; nonetheless, the
IG parsing did not crash either. Objective-C call
syntax can be easily included into the IG by just
adding a few keywords.
5.3 Time Comparison and Robustness
To evaluate the time performance of the IG
approach, PAIGE was tested against the original call
graph approach used in MLSA – ad-hoc string