First please replace the word "enum" with "typedef" in my previous post - the typedefs and classes are those problematic things...
(But I'm still wondering why the enums are there in RecalcData() [and typedefs as well] - it's a bit array so [without looking at the parser itself] I guess that for "typedef struct" you set both tkClass and tkTypedef so you can test for tkClass only here...)
Well, the project I'm working on isn't free so you cannot try it. However, the good news is that the problematic part of the project is the boost library it uses (the source tree contains a partial copy of boost). Download the full sources from here:
http://www.boost.org/ and add all the source files recursively to a project. With full copy of boost I wasn't even patient enough to wait until the tree is generated and killed codeblocks... (let me know if you are able to reproduce it)
I've also analysed this behaviour a bit: the part marked as
// first loop to convert ancestors string to token indices for each token
takes about 7 seconds - even though this not so much compared to the total time, I think that this can be done completely during the parsing stage and not being reparsed every time (anyway, this would have to be done in a thread not to block the GUI).
But the most problematic part is
// second loop to calculate full inheritance for each token
I think that the recursive algorithm you use is suboptimal - for every class you compute its ancestors again and again, but you could reuse the work you have already done for the subclasses. With the copy of boost my project uses, the maximal depth of the inheritance hierarchy was 74. After thinking about it a bit (and getting some graph algorithms from the back of my brain), this should be much more optimal algorithm:
1. Set X equal to the set of all classes and Y equal to empty set
2. Set Z equal to the set of all classes that do not inherit anything
3. Set the set of all ancestors and descendants of all members of Z equal to empty set
do while X is getting smaller:
4. Set X = X - Z, Y = Y union Z, and Z = emptyset
5. Set Z equal to the set of all classes that inherit from some class from Y (in the case of multiple inheritance all the ancestors have to be from Y - otherwise don't put the class to Z)
6. For every member M of Z set the set of all ancestors equal to the set of ancestors of the classes it inherits from (those from Y) plus the classes themselves. At the same time, for each of the ancestors of M add M as its descendant.
(In correctly written C++ program X should be empty set but before compiling the user can make an error so there is a loop in the inheritance. This is the reason why there is the condition "do while X is getting smaller")
The advantage is clear - you go up from the classes that don't inherit anything and reuse what you did in the previous step (and in addition, you avoid recursion which can speed up things a bit as well)
So a good start would be to implement this algorithm and see how much it helps (right now I don't have time to do this myself, sorry). If it's not enough (even if the time reduces to 1s, the freeze is still quite unpleasant), then the function should be put into the parser thread.