<div class="gmail_quote">On Thu, Jul 5, 2012 at 10:19 PM, Sean Silva <span dir="ltr"><<a href="mailto:silvas@purdue.edu" target="_blank">silvas@purdue.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
If you haven't already, take a look at clang's PPCallbacks class<br>
<<a href="http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html" target="_blank">http://clang.llvm.org/doxygen/classclang_1_1PPCallbacks.html</a>>.<br>
<br>
You could maybe try the following:<br>
At every #if* (PPCallbacks::If, PPCallbacks::Ifdef,<br>
PPCallbacks::Ifndef), you basically "checkpoint" the Preprocessor.<br>
Then, if a corresponding PPCallbacks::SourceRangeSkipped occurs, you<br>
can arrange to go back and lex it as though it were there<br>
<br>
Also, this could get really hairy. The dependency graph of macros that<br>
you are thinking of is not necessarily going to be acyclic; it could<br>
be quite bad (think of recursive includes; also check out Boost<br>
Preprocessor for more nastiness<br>
<<a href="http://www.boost.org/doc/libs/1_50_0/libs/preprocessor/doc/index.html" target="_blank">http://www.boost.org/doc/libs/1_50_0/libs/preprocessor/doc/index.html</a>>).<br>
However, for "most code", I'm guessing that the graph will probably<br>
not be too bad, but I might be wrong.<br>
<br>
> and then *create all permutations of their conditions* and rerun the preprocessor<br>
(emphasis mine). All permutations is n!. If you can't come up with<br>
some really clever way to prune this, it won't be tractable.<br></blockquote><div><br></div><div>I don't understand how permutations play into this:</div><div>For each #ifdef that triggers a decision you can either go into that branch or not. If every decision is based on a single define, it seems like this is an exponential problem (2 states for each define).</div>
<div><br></div><div>It gets much worse if ifdefs start to have data dependencies like:</div><div><div>#if a < b and a * 42 < b * 5</div></div><div>Now the problem is not only the number of combinations, but also solving for the right values to use to trigger each switch ...</div>
<div><br></div><div>Cheers,</div><div>/Manuel</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class="HOEnZb"><font color="#888888"><br>
--Sean Silva<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
On Thu, Jul 5, 2012 at 3:33 AM, gorny <<a href="mailto:gorny@santarago.org">gorny@santarago.org</a>> wrote:<br>
> Hi all,<br>
><br>
> I've been messing around with the LLVM/Clang internals, for fun and giggles.<br>
> However I quickly ran into problems with the preprocessor. In my opinion the<br>
> worst thing about C/C++ is the fact that the preprocessor is completely<br>
> decoupled from the rest of the language making it really hard to do proper code<br>
> analysis. If you also want to build a code analyzer you also want to properly<br>
> track conditional macro's and their dependencies. What I would like to do is<br>
> create a dependency graph for the preprocessor macro's in a single .c file.<br>
><br>
> Example:<br>
><br>
> #ifdef A<br>
>   #ifdef B<br>
>   #endif<br>
> #endif<br>
> #ifdef C<br>
>   #ifndef B<br>
>    #define D<br>
>   #endif<br>
> #endif<br>
><br>
> This should yield, with dependencies between parentheses: A(), B(C), C(), D(!B)<br>
><br>
> Using Clang's preprocessor it's impossible to go beyond the first level of<br>
> a conditional macro if it is undefined. The preprocessor will simply eat<br>
> everything within A and thus never deduce that B is conditional on A. I've<br>
> also looked at gcc (cpp -E -dU  - < hello.c | egrep "(#undef|#define)")<br>
> but that also only tracks first level macro's.<br>
><br>
> I'm was thinking about a solution where I simply get the first level macro's<br>
> and then create all permutations of their conditions and rerun the preprocessor<br>
> to find additional levels of used conditional macro's. Rinse and repeat.  I<br>
> think that should work relatively well although it might blow up quite quickly<br>
> with code bases which are really large. I haven't even thought about<br>
> conditional macro's yet. This all could probably be made to work with an<br>
> unpatched Clang instance.<br>
><br>
> For my preferred solution I was thinking about is to create a patch for the<br>
> Clang Preprocessor and turn all the relevant functions into virtual ones so I<br>
> can override the Preprocessor.  Either that or I create a patch which gives me<br>
> the option to record all this information when doing the Preprocessing. I'm not<br>
> looking directly to get this into Clang, if at all, since I very well<br>
> understand it's quite a limited use-case, but if someone could maybe offer some<br>
> guidance here on how to approach this (or share some pitfalls I need to watch<br>
> out for) it would be greatly appreciated.<br>
><br>
> cheers,<br>
> Vincent<br>
> _______________________________________________<br>
> cfe-dev mailing list<br>
> <a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
</div></div></blockquote></div><br>