Hi all,
A while ago I attempted to make a modification to gcc 4.0 before it
was released. I attempted to create a modification that would allow me
to document all exceptions that are eithre thrown directly by a
function/method or that could propagate through a function/method. I ran
into a few problems along the way and this email is to ask a few
questions about gcc internals and better ways of coding in gcc so that I
can re-write this module to work correctly. (Sorry it is so long)
The modification I made to the C++ front end would parse the
global_namespace tree in the function cp_parser_translation_unit (found
in cp/parser.c) and create a database that maps a function/method to all
calls it made to other functions/methods and also a list of all
exceptions thrown directly by it. This database file was appended to for
each run of g++ and so after compiling a whole project the database
would(Should) contain the details for all methods in that project. I
then wrote a post-processing tool that went through the database and
generated a list of all exceptions that could propagate through a
particular function/method and also a seperate list of all exceptions
that would be thrown directly by the method.
In concept it worked, but my implementation of the tree parser did not
always work... A simple problem was that if I was to compile a small
file like:
---main.cpp---
void Function1();
void Function2();
int main()
{
Function1();
return 0;
}
void Function1()
{
throw 1;
}
void Function2()
{
throw 2;
}
------------
Then the database would contain the information as expected for
Function1() but not for Function2(). The parser would come across a
definition for funciton 2 but there was no function body segment in the
tree for me to process and find out if it threw exceptions or called
other functions. This problem also seemed to occurr for all library
files I compiled. Is this some optimisation done by gcc and is there
another place where I can get access to a global tree that represents
ALL source code that has been parsed?
Also I was wondering if I was parsing the best tree for this problem.
The tree I was parsing was the tree found in the variable:
global_namespace
in the file:
cp/parser.c
in the function:
static bool cp_parser_translation_unit(cp_parser* parser)
just after the call to:
finish_translation_unit();
Another problem with the method I was using is that some of the tree
nodes that I expected to find in the tree were not avaliable, it was as
if they had already been translated to more primitive node types. For
example I did not see any tree nodes of type:
EH_SPEC_BLOCK
TRY_BLOCK
THROW_EXPR
EH_FILTER_EXPR
CATCH_EXPR
(Note I could be wrong about some of those expressions. I do however
remember that instead of getting a THROW_EXPR I had to search for calls
to the __cxa_throw() function to know when an exception was thrown. I
cant remember how I handled the try/catch blocks though I did).
I would like to re-write this code at some point and I am looking for
some pointers on ways of doing things better/differently. In particular
I would like to know if the method I was using as described above is
fine, or if there is a better tree to parse to get the information I
need or a better place to process the tree from.
If anyone is able to help me or even point me to the place where I can
get more help on this then I would greatly appreciate it.
I feel that a tool which enables me to see what exceptions can possibly
propagate through what methods could be very useful. It could also warn
of exceptions that could possibly propagate through methods whose
exception specification block do not support it. I was also looking at
modifying doxygen to automatically import this data into its
documentation, but that is another topic.
Thanks,
Brendon.