<div class="gmail_quote">On Tue, Aug 16, 2011 at 5:31 PM, Argyrios Kyrtzidis <span dir="ltr"><<a href="mailto:akyrtzi@gmail.com">akyrtzi@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Author: akirtzidis<br>
Date: Tue Aug 16 19:31:20 2011<br>
New Revision: 137794<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=137794&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=137794&view=rev</a><br>
Log:<br>
Introduce SourceManager::getMacroArgExpandedLocation function.<br></blockquote><div><br></div><div>Really cool!</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

+/// \brief If \arg Loc points inside a function macro argument, the returned<br>
+/// location will be the macro location in which the argument was expanded.<br>
+/// If a macro argument is used multiple times, the expanded location will<br>
+/// be at the first expansion of the argument.<br>
+/// e.g.<br>
+///   MY_MACRO(foo);<br>
+///             ^<br>
+/// Passing a file location pointing at 'foo', will yield a macro location<br>
+/// where 'foo' was expanded into.<br>
+SourceLocation SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) {<br>
+  if (Loc.isInvalid())<br>
+    return Loc;<br>
+<br>
+  FileID FID = getFileID(Loc);<br>
+  if (FID.isInvalid())<br>
+    return Loc;<br>
+<br>
+  int ID = <a href="http://FID.ID" target="_blank">FID.ID</a>;<br></blockquote><div><br></div><div>Personally, I'd find it very helpful to have a description of the algorithm here. This seems like fairly tricky code.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
+  while (1) {<br>
+    ++ID;<br>
+    // Stop if there are no more FileIDs to check.<br>
+    if (ID > 0) {<br>
+      if (unsigned(ID) >= local_sloc_entry_size())<br>
+        return Loc;<br>
+    } else if (ID == -1) {<br>
+      return Loc;<br>
+    }<br>
+<br>
+    const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID);<br>
+    if (Entry.isFile()) {<br>
+      if (Entry.getFile().getIncludeLoc().isValid() &&<br>
+          !isBeforeInTranslationUnit(Entry.getFile().getIncludeLoc(), Loc))<br>
+        return Loc;<br>
+      continue;<br>
+    }<br>
+<br>
+    if (isBeforeInTranslationUnit(Loc,<br>
+                                  Entry.getExpansion().getExpansionLocStart()))<br>
+      return Loc;<br>
+    if (!Entry.getExpansion().isMacroArgExpansion())<br>
+      continue;<br>
+<br>
+    // This is a macro argument expansion. See if Loc points in the argument<br>
+    // that was lexed.<br>
+<br>
+    SourceLocation SpellLoc = Entry.getExpansion().getSpellingLoc();<br>
+    unsigned NextOffset;<br>
+    if (ID > 0) {<br>
+      if (unsigned(ID+1) == local_sloc_entry_size())<br>
+        NextOffset = getNextLocalOffset();<br>
+      else<br>
+        NextOffset = getLocalSLocEntry(ID+1).getOffset();<br>
+    } else {<br>
+      if (ID+1 == -1)<br>
+        NextOffset = MaxLoadedOffset;<br>
+      else<br>
+        NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();<br>
+    }<br></blockquote><div><br></div><div>And all of this makes me wish we had unit tests for the SourceManager that could exercise this algorithm in a contained fashion... oh well. =]</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

+    unsigned EntrySize = NextOffset - Entry.getOffset() - 1;<br>
+    unsigned BeginOffs = SpellLoc.getOffset();<br>
+    unsigned EndOffs = BeginOffs + EntrySize;<br>
+    if (BeginOffs <= Loc.getOffset() && Loc.getOffset() < EndOffs) {<br>
+      SourceLocation ExpandLoc = SourceLocation::getMacroLoc(Entry.getOffset());<br>
+      // Replace current Loc with the expanded location and continue.<br>
+      // The expanded argument may end up being passed to another function macro<br>
+      // and relexed again.<br>
+      Loc = ExpandLoc.getFileLocWithOffset(Loc.getOffset()-BeginOffs);<br>
+    }<br>
+  }<br>
+}<br>
+<br>
 /// Given a decomposed source location, move it up the include/expansion stack<br>
 /// to the parent source location.  If this is possible, return the decomposed<br>
 /// version of the parent in Loc and return false.  If Loc is the top-level<br>
@@ -1557,7 +1626,7 @@<br>
                << NextLocalOffset << "B of Sloc address space used.\n";<br>
   llvm::errs() << LoadedSLocEntryTable.size()<br>
                << " loaded SLocEntries allocated, "<br>
-               << (1U << 31U) - CurrentLoadedOffset<br>
+               << MaxLoadedOffset - CurrentLoadedOffset<br>
                << "B of Sloc address space used.\n";<br>
<br>
   unsigned NumLineNumsComputed = 0;<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br>