<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">Just in case anyone ever needs to get
      the relevant macro text from either an ExpansionInfo or a
      MacroInfo to allow emitting that macro completely, I've included
      code for the way I figured out how to do it.  I didn't find an
      easier way, but maybe I missed something, but it was pretty hard. 
      For the rest of the detection I switched to using the Preprocessor
      callbacks to catch all the macros emitted in groups (using the
      range to know what goes together.)  Looks like everything is
      working.<br>
      <br>
      Thanks to everyone for all their help!<br>
        -Eric<br>
      <br>
      <br>
      <div style="font-family: "Courier New"; font-size:
        12.0pt; color: #000000;background-color: #e7e7e7; font-style:
        normal; font-weight: normal; text-decoration: none;">
        <pre><span>
</span><span style="color:#800080;">typedef</span><span> </span><span style="color:#c04000;">std</span><span>::</span><span style="color:#c04000;">pair</span><span><</span><span>clang</span><span>::</span><span>SourceRange</span><span>, </span><span>clang</span><span>::</span><span>SourceRange</span><span>></span><span> </span><span>MacroDefinitionPair</span><span>;</span>
</pre>
        <pre><span>MacroDefinitionPair</span><span> </span><span style="font-weight: bolder;">getMacroDefinitionPair</span><span>(</span><span style="color:#800080;">const</span><span> </span><span>SourceLocation</span><span> </span><span>DefBodyLoc, </span><span style="color:#800080;">const</span><span> </span><span>SourceManager</span><span> </span><span>&</span><span>SM</span><span>, </span><span><span style="color:#800080;">const</span><span> </span><span>LangOptions</span><span> </span><span>&</span><span>LangOpts</span>) </span><span style="color:#800000;">{</span><span></span>
<span>    </span><span>MacroDefinitionPair</span><span> </span><span>Ranges</span><span>;</span>
<span>    </span><span style="color:#800080;">int</span><span> </span><span>iter</span><span> </span><span style="color:#004080;">=</span><span> </span><span style="color:#000080;">0</span><span>;</span>

<span>    </span><span style="color:#008000;font-style: italic;">//SourceLocation scur = SM.getSpellingLoc(BeginLoc);</span>
<span>    </span><span style="color:#c04000;">std</span><span>::</span><span style="color:#c04000;">pair</span><span><</span><span>FileID</span><span>, </span><span style="color:#800080;">unsigned</span><span>></span><span> </span><span>cur_info</span><span> </span><span style="color:#004080;">=</span><span> </span><span>SM</span><span>.</span><span style="font-weight: bolder;">getDecomposedLoc</span><span>(</span><span>DefBodyLoc</span><span>)</span><span>;</span>
<span>    </span><span style="color:#800080;">bool</span><span> </span><span>invalid</span><span> </span><span style="color:#004080;">=</span><span> </span><span style="color:#800080;">false</span><span>;</span>
<span>    </span><span>StringRef</span><span> </span><span>buf</span><span> </span><span style="color:#004080;">=</span><span> </span><span>SM</span><span>.</span><span style="font-weight: bolder;">getBufferData</span><span>(</span><span>cur_info</span><span>.</span><span>first</span><span>, </span><span>&</span><span>invalid</span><span>)</span><span>;</span>

<span>    </span><span style="color:#800080;">if</span><span> (</span><span>invalid</span><span>) </span><span style="color:#800080;">return</span><span> </span><span>Ranges</span><span>;</span>

<span>    </span><span style="color:#008000;font-style: italic;">// Get the point in the buffer</span>
<span>    </span><span style="color:#800080;">const</span><span> </span><span style="color:#800080;">char</span><span>*</span><span> </span><span>buf_start</span><span> </span><span style="color:#004080;">=</span><span> </span><span>buf</span><span>.</span><span style="font-weight: bolder;">data</span><span>()</span><span>;</span>
<span>    </span><span style="color:#800080;">const</span><span> </span><span style="color:#800080;">char</span><span>*</span><span> </span><span>orig_point</span><span> </span><span style="color:#004080;">=</span><span> </span><span>buf_start</span><span> </span><span>+</span><span> </span><span>cur_info</span><span>.</span><span>second</span><span>;</span>
<span>    </span><span style="color:#800080;">const</span><span> </span><span style="color:#800080;">char</span><span>*</span><span> </span><span>point</span><span> </span><span style="color:#004080;">=</span><span> </span><span>orig_point</span><span>;</span>

<span>    </span><span style="color:#008000;font-style: italic;">// Find the point we begin this #define</span>
<span>    </span><span style="color:#800080;">while</span><span> (</span><span style="color:#000080;">1</span><span>) </span><span style="color:#800000;">{</span>

<span>        </span><span style="color:#008000;font-style: italic;">// Search backwards until a new-line</span>
<span>        </span><span style="color:#800080;">while</span><span> (</span><span>point</span><span> </span><span>></span><span> </span><span>buf_start</span><span>) </span><span style="color:#800000;">{</span>
<span>            </span><span style="color:#800080;">if</span><span> (</span><span>*</span><span>(</span><span>point</span><span>-</span><span style="color:#000080;">1</span><span>) </span><span>==</span><span> </span><span style="color:#006060;">'\n'</span><span>) </span><span style="color:#800080;">break</span><span>;</span>
<span>            </span><span>point</span><span style="color:#004080;">--</span><span>;</span>
<span>        </span><span style="color:#800000;">}</span>

<span>        </span><span style="color:#008000;font-style: italic;">// Make a lexer and point it at our buffer and offset and ignore</span>
<span>        </span><span style="color:#008000;font-style: italic;">// comments.</span>
<span>        </span><span>Lexer</span><span> </span><span style="font-weight: bolder;">lexer</span><span>(</span><span>SM</span><span>.</span><span style="font-weight: bolder;">getLocForStartOfFile</span><span>(</span><span>cur_info</span><span>.</span><span>first</span><span>), </span><span>LangOpts</span><span>,</span>
<span>                    </span><span>buf_start</span><span>, </span><span>point</span><span>, </span><span>buf</span><span>.</span><span style="font-weight: bolder;">end</span><span>())</span><span>;</span>
<span>        </span><span>lexer</span><span>.</span><span style="font-weight: bolder;">SetCommentRetentionState</span><span>(</span><span style="color:#800080;">false</span><span>)</span><span>;</span>

<span>        </span><span style="color:#008000;font-style: italic;">// Parse the first two tokens</span>
<span>        </span><span>Token</span><span> </span><span>tok_h</span><span>, </span><span>tok_define</span><span>;</span>
<span>        </span><span>lexer</span><span>.</span><span style="font-weight: bolder;">LexFromRawLexer</span><span>(</span><span>tok_h</span><span>)</span><span>;</span>
<span>        </span><span>lexer</span><span>.</span><span style="font-weight: bolder;">LexFromRawLexer</span><span>(</span><span>tok_define</span><span>)</span><span>;</span>

<span>        </span><span style="color:#008000;font-style: italic;">// If we match the beginning of a define, then we are done</span>
<span>        </span><span style="color:#800080;">if</span><span> (</span><span>tok_h</span><span>.</span><span style="color:#c04000;">is</span><span>(</span><span>tok</span><span>::</span><span>hash</span><span>) </span><span>&&</span><span> </span><span>tok_define</span><span>.</span><span style="color:#c04000;">is</span><span>(</span><span>tok</span><span>::</span><span>raw_identifier</span><span>) </span><span>&&</span>
<span>                </span><span>tok_define</span><span>.</span><span style="font-weight: bolder;">getRawIdentifier</span><span>() </span><span>==</span><span> </span><span style="color:#008080;">"define"</span><span>) </span><span style="color:#800000;">{</span>

<span>            </span><span style="color:#008000;font-style: italic;">// Get the name token (this skips over the leading space)</span>
<span>            </span><span>Token</span><span> </span><span>tok_name</span><span>;</span>
<span>            </span><span>lexer</span><span>.</span><span style="font-weight: bolder;">LexFromRawLexer</span><span>(</span><span>tok_name</span><span>)</span><span>;</span>

<span>            </span><span style="color:#008000;font-style: italic;">// The range starts at our token and goes through one token before</span>
<span>            </span><span style="color:#008000;font-style: italic;">// the body.</span>
<span>            </span><span>Ranges</span><span>.</span><span>first</span><span>.</span><span style="font-weight: bolder;">setBegin</span><span>(</span><span>tok_name</span><span>.</span><span style="font-weight: bolder;">getLocation</span><span>())</span><span>;</span>
<span>            </span><span>Ranges</span><span>.</span><span>first</span><span>.</span><span style="font-weight: bolder;">setEnd</span><span>(</span><span>DefBodyLoc</span><span>.</span><span style="font-weight: bolder;">getLocWithOffset</span><span>(</span><span>-</span><span style="color:#000080;">1</span><span>))</span><span>;</span>

<span>            </span><span style="color:#008000;font-style: italic;">// Done processing, move on.</span>
<span>            </span><span style="color:#800080;">break</span><span>;</span>
<span>        </span><span style="color:#800000;">}</span>

<span>        </span><span style="color:#008000;font-style: italic;">// Backup one more and keep looking</span>
<span>        </span><span>point</span><span style="color:#004080;">--</span><span>;</span>

<span>        </span><span style="color:#008000;font-style: italic;">// If we can't find the beginning, return null ranges to represent</span>
<span>        </span><span style="color:#008000;font-style: italic;">// an invalid starting point.</span>
<span>        </span><span style="color:#800080;">if</span><span>( </span><span>point</span><span> </span><span><</span><span> </span><span>buf_start</span><span> ) </span><span style="color:#800080;">return</span><span> </span><span>Ranges</span><span>;</span>
<span>    </span><span style="color:#800000;">}</span>

<span>    </span><span style="color:#008000;font-style: italic;">// Make a lexer and point it at our buffer and offset</span>
<span>    </span><span>Lexer</span><span> </span><span style="font-weight: bolder;">lexer</span><span>(</span><span>SM</span><span>.</span><span style="font-weight: bolder;">getLocForStartOfFile</span><span>(</span><span>cur_info</span><span>.</span><span>first</span><span>), </span><span>LangOpts</span><span>,</span>
<span>                </span><span>buf</span><span>.</span><span style="font-weight: bolder;">begin</span><span>(), </span><span>orig_point</span><span>, </span><span>buf</span><span>.</span><span style="font-weight: bolder;">end</span><span>())</span><span>;</span>
<span>    </span><span>lexer</span><span>.</span><span style="font-weight: bolder;">SetCommentRetentionState</span><span>(</span><span style="color:#800080;">false</span><span>)</span><span>;</span>

<span>    </span><span style="color:#008000;font-style: italic;">// Intermediate variables</span>
<span>    </span><span>Token</span><span> </span><span>tok</span><span>;</span>
<span>    </span><span>SourceLocation</span><span> </span><span>EndBodyLoc</span><span>;</span>

<span>    </span><span style="color:#008000;font-style: italic;">// Advance 1 token because when we start the tokenizer it assumes that</span>
<span>    </span><span style="color:#008000;font-style: italic;">// we're the start of line.</span>
<span>    </span><span>lexer</span><span>.</span><span style="font-weight: bolder;">LexFromRawLexer</span><span>(</span><span>tok</span><span>)</span><span>;</span>

<span>    </span><span style="color:#008000;font-style: italic;">// Read tokens until we find the next Start of Line.</span>
<span>    </span><span style="color:#800080;">while</span><span> (</span><span style="color:#000080;">1</span><span>) </span><span style="color:#800000;">{</span>
<span>        </span><span>lexer</span><span>.</span><span style="font-weight: bolder;">LexFromRawLexer</span><span>(</span><span>tok</span><span>)</span><span>;</span>

<span>        </span><span style="color:#008000;font-style: italic;">// If we're EoF or SoL, we should stop advancing</span>
<span>        </span><span style="color:#800080;">if</span><span> (</span><span>tok</span><span>.</span><span style="color:#c04000;">is</span><span>(</span><span>tok</span><span>::</span><span>eof</span><span>) </span><span>||</span>
<span>            </span><span>tok</span><span>.</span><span style="font-weight: bolder;">getFlags</span><span>() </span><span>&</span><span> </span><span>Token</span><span>::</span><span>TokenFlags</span><span>::</span><span>StartOfLine</span><span> ) </span><span style="color:#800000;">{</span>
<span>        </span><span style="color:#008000;font-style: italic;">//if (tok.is(tok::eof)) {</span>
<span>            </span><span style="color:#800080;">break</span><span>;</span>
<span>        </span><span style="color:#800000;">}</span>

<span>        </span><span style="color:#008000;font-style: italic;">// Cache the last token's final location</span>
<span>        </span><span>EndBodyLoc</span><span> </span><span style="color:#004080;">=</span><span> </span><span>tok</span><span>.</span><span style="font-weight: bolder;">getEndLoc</span><span>()</span><span>.</span><span style="font-weight: bolder;">getLocWithOffset</span><span>(</span><span>-</span><span style="color:#000080;">1</span><span>)</span><span>;</span>
<span>    </span><span style="color:#800000;">}</span>

<span>    </span><span style="color:#008000;font-style: italic;">// Mark the end of the macro body</span>
<span>    </span><span>Ranges</span><span>.</span><span>second</span><span>.</span><span style="font-weight: bolder;">setBegin</span><span>(</span><span>DefBodyLoc</span><span>)</span><span>;</span>
<span>    </span><span>Ranges</span><span>.</span><span>second</span><span>.</span><span style="font-weight: bolder;">setEnd</span><span>(</span><span>EndBodyLoc</span><span>)</span><span>;</span>

<span>    </span><span style="color:#008000;font-style: italic;">// Return the ranges</span>
<span>    </span><span style="color:#800080;">return</span><span> </span><span>Ranges</span><span>;</span>
<span style="color:#800000;">}</span>
</pre>
      </div>
      <br>
    </div>
  </body>
</html>