[cfe-commits] r137794 - in /cfe/trunk: include/clang/Basic/SourceManager.h lib/Basic/SourceManager.cpp

Argyrios Kyrtzidis akyrtzi at gmail.com
Tue Aug 16 17:31:21 PDT 2011


Author: akirtzidis
Date: Tue Aug 16 19:31:20 2011
New Revision: 137794

URL: http://llvm.org/viewvc/llvm-project?rev=137794&view=rev
Log:
Introduce SourceManager::getMacroArgExpandedLocation function.

If we pass it a source location that points inside a function macro argument,
the returned location will be the macro location in which the argument was expanded.
If a macro argument is used multiple times, the expanded location will
be at the first expansion of the argument.
 e.g.
   MY_MACRO(foo);
             ^
Passing a file location pointing at 'foo', will yield a macro location
where 'foo' was expanded into.

Make SourceManager::getLocation call getMacroArgExpandedLocation as well.

Modified:
    cfe/trunk/include/clang/Basic/SourceManager.h
    cfe/trunk/lib/Basic/SourceManager.cpp

Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=137794&r1=137793&r2=137794&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Tue Aug 16 19:31:20 2011
@@ -489,6 +489,10 @@
   /// not have been loaded, so that value would be unknown.
   unsigned CurrentLoadedOffset;
 
+  /// \brief The highest possible offset is 2^31-1, so CurrentLoadedOffset
+  /// starts at 2^31.
+  static const unsigned MaxLoadedOffset = 1U << 31U;
+
   /// \brief A bitmap that indicates whether the entries of LoadedSLocEntryTable
   /// have already been loaded from the external source.
   ///
@@ -1001,8 +1005,33 @@
   ///
   /// If the source file is included multiple times, the source location will
   /// be based upon the first inclusion.
+  ///
+  /// If the location points inside a function macro argument, the returned
+  /// location will be the macro location in which the argument was expanded.
+  /// \sa getMacroArgExpandedLocation
   SourceLocation getLocation(const FileEntry *SourceFile,
-                             unsigned Line, unsigned Col);
+                             unsigned Line, unsigned Col) {
+    SourceLocation Loc = translateFileLineCol(SourceFile, Line, Col);
+    return getMacroArgExpandedLocation(Loc);
+  }
+  
+  /// \brief Get the source location for the given file:line:col triplet.
+  ///
+  /// If the source file is included multiple times, the source location will
+  /// be based upon the first inclusion.
+  SourceLocation translateFileLineCol(const FileEntry *SourceFile,
+                                      unsigned Line, unsigned Col);
+
+  /// \brief If \arg Loc points inside a function macro argument, the returned
+  /// location will be the macro location in which the argument was expanded.
+  /// If a macro argument is used multiple times, the expanded location will
+  /// be at the first expansion of the argument.
+  /// e.g.
+  ///   MY_MACRO(foo);
+  ///             ^
+  /// Passing a file location pointing at 'foo', will yield a macro location
+  /// where 'foo' was expanded into.
+  SourceLocation getMacroArgExpandedLocation(SourceLocation Loc);
 
   /// \brief Determines the order of 2 source locations in the translation unit.
   ///

Modified: cfe/trunk/lib/Basic/SourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/SourceManager.cpp?rev=137794&r1=137793&r2=137794&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/SourceManager.cpp (original)
+++ cfe/trunk/lib/Basic/SourceManager.cpp Tue Aug 16 19:31:20 2011
@@ -403,9 +403,7 @@
 
   // Use up FileID #0 as an invalid expansion.
   NextLocalOffset = 0;
-  // The highest possible offset is 2^31-1, so CurrentLoadedOffset starts at
-  // 2^31.
-  CurrentLoadedOffset = 1U << 31U;
+  CurrentLoadedOffset = MaxLoadedOffset;
   createExpansionLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1);
 }
 
@@ -1303,8 +1301,8 @@
 ///
 /// If the source file is included multiple times, the source location will
 /// be based upon an arbitrary inclusion.
-SourceLocation SourceManager::getLocation(const FileEntry *SourceFile,
-                                          unsigned Line, unsigned Col) {
+SourceLocation SourceManager::translateFileLineCol(const FileEntry *SourceFile,
+                                                  unsigned Line, unsigned Col) {
   assert(SourceFile && "Null source file!");
   assert(Line && Col && "Line and column should start from 1!");
 
@@ -1454,6 +1452,77 @@
   return getLocForStartOfFile(FirstFID).getFileLocWithOffset(FilePos + Col - 1);
 }
 
+/// \brief If \arg Loc points inside a function macro argument, the returned
+/// location will be the macro location in which the argument was expanded.
+/// If a macro argument is used multiple times, the expanded location will
+/// be at the first expansion of the argument.
+/// e.g.
+///   MY_MACRO(foo);
+///             ^
+/// Passing a file location pointing at 'foo', will yield a macro location
+/// where 'foo' was expanded into.
+SourceLocation SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) {
+  if (Loc.isInvalid())
+    return Loc;
+  
+  FileID FID = getFileID(Loc);
+  if (FID.isInvalid())
+    return Loc;
+
+  int ID = FID.ID;
+  while (1) {
+    ++ID;
+    // Stop if there are no more FileIDs to check.
+    if (ID > 0) {
+      if (unsigned(ID) >= local_sloc_entry_size())
+        return Loc;
+    } else if (ID == -1) {
+      return Loc;
+    }
+
+    const SrcMgr::SLocEntry &Entry = getSLocEntryByID(ID);
+    if (Entry.isFile()) {
+      if (Entry.getFile().getIncludeLoc().isValid() &&
+          !isBeforeInTranslationUnit(Entry.getFile().getIncludeLoc(), Loc))
+        return Loc;
+      continue;
+    }
+  
+    if (isBeforeInTranslationUnit(Loc,
+                                  Entry.getExpansion().getExpansionLocStart()))
+      return Loc;
+    if (!Entry.getExpansion().isMacroArgExpansion())
+      continue;
+
+    // This is a macro argument expansion. See if Loc points in the argument
+    // that was lexed.
+
+    SourceLocation SpellLoc = Entry.getExpansion().getSpellingLoc();
+    unsigned NextOffset;
+    if (ID > 0) {
+      if (unsigned(ID+1) == local_sloc_entry_size())
+        NextOffset = getNextLocalOffset();
+      else
+        NextOffset = getLocalSLocEntry(ID+1).getOffset();
+    } else {
+      if (ID+1 == -1)
+        NextOffset = MaxLoadedOffset;
+      else
+        NextOffset = getSLocEntry(FileID::get(ID+1)).getOffset();
+    }
+    unsigned EntrySize = NextOffset - Entry.getOffset() - 1;
+    unsigned BeginOffs = SpellLoc.getOffset();
+    unsigned EndOffs = BeginOffs + EntrySize;
+    if (BeginOffs <= Loc.getOffset() && Loc.getOffset() < EndOffs) {
+      SourceLocation ExpandLoc = SourceLocation::getMacroLoc(Entry.getOffset());
+      // Replace current Loc with the expanded location and continue.
+      // The expanded argument may end up being passed to another function macro
+      // and relexed again.
+      Loc = ExpandLoc.getFileLocWithOffset(Loc.getOffset()-BeginOffs);
+    }
+  }
+}
+
 /// Given a decomposed source location, move it up the include/expansion stack
 /// to the parent source location.  If this is possible, return the decomposed
 /// version of the parent in Loc and return false.  If Loc is the top-level
@@ -1557,7 +1626,7 @@
                << NextLocalOffset << "B of Sloc address space used.\n";
   llvm::errs() << LoadedSLocEntryTable.size()
                << " loaded SLocEntries allocated, "
-               << (1U << 31U) - CurrentLoadedOffset
+               << MaxLoadedOffset - CurrentLoadedOffset
                << "B of Sloc address space used.\n";
   
   unsigned NumLineNumsComputed = 0;





More information about the cfe-commits mailing list