[cfe-commits] r40103 - in /cfe/trunk: Basic/SourceManager.cpp Driver/DiagChecker.cpp Driver/PrintPreprocessedOutput.cpp Driver/TextDiagnosticPrinter.cpp Driver/TextDiagnostics.cpp Lex/Lexer.cpp Lex/MacroExpander.cpp Lex/Pragma.cpp Lex/Preprocessor.cpp Lex/ScratchBuffer.cpp include/clang/Basic/SourceLocation.h include/clang/Basic/SourceManager.h include/clang/Lex/Lexer.h

Chris Lattner sabre at nondot.org
Fri Jul 20 09:37:11 PDT 2007


Author: lattner
Date: Fri Jul 20 11:37:10 2007
New Revision: 40103

URL: http://llvm.org/viewvc/llvm-project?rev=40103&view=rev
Log:
Reimplement SourceLocation.  Instead of having a 
fileid/offset pair, it now contains a bit discriminating between
mapped locations and file locations.  This separates the tables for
macros and files in SourceManager, and allows better separation of
concepts in the rest of the compiler.  This allows us to have *many*
macro instantiations before running out of 'addressing space'.

This is also more efficient, because testing whether something is a
macro expansion is now a bit test instead of a table lookup (which
also used to require having a srcmgr around, now it doesn't).

This is fully functional, but there are several refinements and
optimizations left.

Modified:
    cfe/trunk/Basic/SourceManager.cpp
    cfe/trunk/Driver/DiagChecker.cpp
    cfe/trunk/Driver/PrintPreprocessedOutput.cpp
    cfe/trunk/Driver/TextDiagnosticPrinter.cpp
    cfe/trunk/Driver/TextDiagnostics.cpp
    cfe/trunk/Lex/Lexer.cpp
    cfe/trunk/Lex/MacroExpander.cpp
    cfe/trunk/Lex/Pragma.cpp
    cfe/trunk/Lex/Preprocessor.cpp
    cfe/trunk/Lex/ScratchBuffer.cpp
    cfe/trunk/include/clang/Basic/SourceLocation.h
    cfe/trunk/include/clang/Basic/SourceManager.h
    cfe/trunk/include/clang/Lex/Lexer.h

Modified: cfe/trunk/Basic/SourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Basic/SourceManager.cpp?rev=40103&r1=40102&r2=40103&view=diff

==============================================================================
--- cfe/trunk/Basic/SourceManager.cpp (original)
+++ cfe/trunk/Basic/SourceManager.cpp Fri Jul 20 11:37:10 2007
@@ -18,7 +18,6 @@
 #include <algorithm>
 #include <iostream>
 #include <fcntl.h>
-
 using namespace clang;
 using namespace SrcMgr;
 using llvm::MemoryBuffer;
@@ -141,7 +140,7 @@
   // FilePos field.
   unsigned FileSize = File->second.Buffer->getBufferSize();
   if (FileSize+1 < (1 << SourceLocation::FilePosBits)) {
-    FileIDs.push_back(FileIDInfo::getNormalBuffer(IncludePos, 0, File));
+    FileIDs.push_back(FileIDInfo::get(IncludePos, 0, File));
     assert(FileIDs.size() < (1 << SourceLocation::FileIDBits) &&
            "Ran out of file ID's!");
     return FileIDs.size();
@@ -152,7 +151,7 @@
 
   unsigned ChunkNo = 0;
   while (1) {
-    FileIDs.push_back(FileIDInfo::getNormalBuffer(IncludePos, ChunkNo++, File));
+    FileIDs.push_back(FileIDInfo::get(IncludePos, ChunkNo++, File));
 
     if (FileSize+1 < (1 << SourceLocation::FilePosBits)) break;
     FileSize -= (1 << SourceLocation::FilePosBits);
@@ -176,7 +175,14 @@
   // Resolve InstantLoc down to a real logical location.
   InstantLoc = getLogicalLoc(InstantLoc);
   
+  // FIXME: intelligently cache macroid's.
+  MacroIDs.push_back(MacroIDInfo::get(InstantLoc, PhysLoc));
+  
+  return SourceLocation::getMacroLoc(MacroIDs.size()-1, 0, 0);
+  
+#if 0
   unsigned InstantiationFileID;
+  
   // If this is the same instantiation as was requested last time, return this
   // immediately.
   if (PhysLoc.getFileID() == LastInstantiationLoc_MacroFID &&
@@ -193,7 +199,9 @@
     LastInstantiationLoc_InstantLoc = InstantLoc;
     LastInstantiationLoc_Result     = InstantiationFileID;
   }
-  return SourceLocation(InstantiationFileID, PhysLoc.getRawFilePos());
+  return SourceLocation::getMacroLoc(InstantiationFileID, 
+                                     PhysLoc.getRawFilePos());
+#endif
 }
 
 
@@ -203,34 +211,21 @@
 const char *SourceManager::getCharacterData(SourceLocation SL) const {
   // Note that this is a hot function in the getSpelling() path, which is
   // heavily used by -E mode.
-  unsigned FileID = SL.getFileID();
-  assert(FileID && "Invalid source location!");
+  SL = getPhysicalLoc(SL);
   
-  return getFileInfo(FileID)->Buffer->getBufferStart() + getFilePos(SL);
+  return getFileInfo(SL.getFileID())->Buffer->getBufferStart() + 
+         getFullFilePos(SL);
 }
 
-/// getIncludeLoc - Return the location of the #include for the specified
-/// FileID.
-SourceLocation SourceManager::getIncludeLoc(unsigned FileID) const {
-  const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(FileID);
-
-  // For Macros, the physical loc is specified by the MacroTokenFileID.
-  if (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion)
-    FIDInfo = &FileIDs[FIDInfo->u.MacroTokenFileID-1];
-  
-  return FIDInfo->IncludeLoc;
-}  
-
 
-/// getColumnNumber - Return the column # for the specified include position.
+/// getColumnNumber - Return the column # for the specified file position.
 /// this is significantly cheaper to compute than the line number.  This returns
 /// zero if the column number isn't known.
 unsigned SourceManager::getColumnNumber(SourceLocation Loc) const {
-  Loc = getLogicalLoc(Loc);
   unsigned FileID = Loc.getFileID();
   if (FileID == 0) return 0;
   
-  unsigned FilePos = getFilePos(Loc);
+  unsigned FilePos = getFullFilePos(Loc);
   const MemoryBuffer *Buffer = getBuffer(FileID);
   const char *Buf = Buffer->getBufferStart();
 
@@ -244,7 +239,6 @@
 /// the SourceLocation specifies.  This can be modified with #line directives,
 /// etc.
 std::string SourceManager::getSourceName(SourceLocation Loc) {
-  Loc = getLogicalLoc(Loc);
   unsigned FileID = Loc.getFileID();
   if (FileID == 0) return "";
   return getFileInfo(FileID)->Buffer->getBufferIdentifier();
@@ -256,7 +250,6 @@
 /// line offsets for the MemoryBuffer, so this is not cheap: use only when
 /// about to emit a diagnostic.
 unsigned SourceManager::getLineNumber(SourceLocation Loc) {
-  Loc = getLogicalLoc(Loc);
   unsigned FileID = Loc.getFileID();
   if (FileID == 0) return 0;
   FileInfo *FileInfo = getFileInfo(FileID);
@@ -317,28 +310,10 @@
   // type approaches to make good (tight?) initial guesses based on the
   // assumption that all lines are the same average size.
   unsigned *Pos = std::lower_bound(SourceLineCache, SourceLineCache+NumLines,
-                                   getFilePos(Loc)+1);
+                                   getFullFilePos(Loc)+1);
   return Pos-SourceLineCache;
 }
 
-/// getSourceFilePos - This method returns the *logical* offset from the start
-/// of the file that the specified SourceLocation represents.  This returns
-/// the location of the *logical* character data, not the physical file
-/// position.  In the case of macros, for example, this returns where the
-/// macro was instantiated, not where the characters for the macro can be
-/// found.
-unsigned SourceManager::getSourceFilePos(SourceLocation Loc) const {
- 
-  // If this is a macro, we need to get the instantiation location.
-  const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(Loc.getFileID());
-  while (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion) {
-    Loc = FIDInfo->IncludeLoc;
-    FIDInfo = getFIDInfo(Loc.getFileID());
-  }
-  
-  return getFilePos(Loc);
-}
-
 /// PrintStats - Print statistics to stderr.
 ///
 void SourceManager::PrintStats() const {
@@ -346,17 +321,8 @@
   std::cerr << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
             << " mem buffers mapped, " << FileIDs.size() 
             << " file ID's allocated.\n";
-  unsigned NumBuffers = 0, NumMacros = 0;
-  for (unsigned i = 0, e = FileIDs.size(); i != e; ++i) {
-    if (FileIDs[i].IDType == FileIDInfo::NormalBuffer)
-      ++NumBuffers;
-    else if (FileIDs[i].IDType == FileIDInfo::MacroExpansion)
-      ++NumMacros;
-    else
-      assert(0 && "Unknown FileID!");
-  }
-  std::cerr << "  " << NumBuffers << " normal buffer FileID's, "
-            << NumMacros << " macro expansion FileID's.\n";
+  std::cerr << "  " << FileIDs.size() << " normal buffer FileID's, "
+            << MacroIDs.size() << " macro expansion FileID's.\n";
     
   
   

Modified: cfe/trunk/Driver/DiagChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/DiagChecker.cpp?rev=40103&r1=40102&r2=40103&view=diff

==============================================================================
--- cfe/trunk/Driver/DiagChecker.cpp (original)
+++ cfe/trunk/Driver/DiagChecker.cpp Fri Jul 20 11:37:10 2007
@@ -60,7 +60,7 @@
     if (OpenDiag == std::string::npos) {
       fprintf(stderr,
               "oops:%d: Cannot find beginning of expected error string\n",
-              SourceMgr.getLineNumber(Pos));
+              SourceMgr.getLogicalLineNumber(Pos));
       break;
     }
 
@@ -70,7 +70,7 @@
     if (CloseDiag == std::string::npos) {
       fprintf(stderr,
               "oops:%d: Cannot find end of expected error string\n",
-              SourceMgr.getLineNumber(Pos));
+              SourceMgr.getLogicalLineNumber(Pos));
       break;
     }
 
@@ -126,7 +126,7 @@
 
   for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I)
     fprintf(stderr, "  Line %d: %s\n",
-            SourceMgr.getLineNumber(I->first),
+            SourceMgr.getLogicalLineNumber(I->first),
             I->second.c_str());
 
   return true;
@@ -144,12 +144,12 @@
   DiagList DiffList;
 
   for (const_diag_iterator I = d1_begin, E = d1_end; I != E; ++I) {
-    unsigned LineNo1 = SourceMgr.getLineNumber(I->first);
+    unsigned LineNo1 = SourceMgr.getLogicalLineNumber(I->first);
     const std::string &Diag1 = I->second;
     bool Found = false;
 
     for (const_diag_iterator II = d2_begin, IE = d2_end; II != IE; ++II) {
-      unsigned LineNo2 = SourceMgr.getLineNumber(II->first);
+      unsigned LineNo2 = SourceMgr.getLogicalLineNumber(II->first);
       if (LineNo1 != LineNo2) continue;
 
       const std::string &Diag2 = II->second;

Modified: cfe/trunk/Driver/PrintPreprocessedOutput.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/PrintPreprocessedOutput.cpp?rev=40103&r1=40102&r2=40103&view=diff

==============================================================================
--- cfe/trunk/Driver/PrintPreprocessedOutput.cpp (original)
+++ cfe/trunk/Driver/PrintPreprocessedOutput.cpp Fri Jul 20 11:37:10 2007
@@ -146,7 +146,7 @@
     return;
   }
   
-  unsigned LineNo = PP.getSourceManager().getLineNumber(Loc);
+  unsigned LineNo = PP.getSourceManager().getLogicalLineNumber(Loc);
   
   // If this line is "close enough" to the original line, just print newlines,
   // otherwise print a #line directive.
@@ -191,7 +191,7 @@
   // #include directive was at.
   SourceManager &SourceMgr = PP.getSourceManager();
   if (Reason == PPCallbacks::EnterFile) {
-    MoveToLine(SourceMgr.getIncludeLoc(Loc.getFileID()));
+    MoveToLine(SourceMgr.getIncludeLoc(Loc));
   } else if (Reason == PPCallbacks::SystemHeaderPragma) {
     MoveToLine(Loc);
     
@@ -200,6 +200,7 @@
     // strange behavior.
   }
   
+  Loc = SourceMgr.getLogicalLoc(Loc);
   CurLine = SourceMgr.getLineNumber(Loc);
   CurFilename = '"' + Lexer::Stringify(SourceMgr.getSourceName(Loc)) + '"';
   FileType = FileType;
@@ -256,8 +257,8 @@
   
   // Print out space characters so that the first token on a line is
   // indented for easy reading.
-  unsigned ColNo = 
-    PP.getSourceManager().getColumnNumber(Tok.getLocation());
+  const SourceManager &SourceMgr = PP.getSourceManager();
+  unsigned ColNo = SourceMgr.getLogicalColumnNumber(Tok.getLocation());
   
   // This hack prevents stuff like:
   // #define HASH #

Modified: cfe/trunk/Driver/TextDiagnosticPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/TextDiagnosticPrinter.cpp?rev=40103&r1=40102&r2=40103&view=diff

==============================================================================
--- cfe/trunk/Driver/TextDiagnosticPrinter.cpp (original)
+++ cfe/trunk/Driver/TextDiagnosticPrinter.cpp Fri Jul 20 11:37:10 2007
@@ -32,16 +32,15 @@
 
 void TextDiagnosticPrinter::
 PrintIncludeStack(SourceLocation Pos) {
-  unsigned FileID = Pos.getFileID();
-  if (FileID == 0) return;
-  
+  if (Pos.isInvalid()) return;
+
+  Pos = SourceMgr.getLogicalLoc(Pos);
+
   // Print out the other include frames first.
-  PrintIncludeStack(SourceMgr.getIncludeLoc(FileID));
-  
+  PrintIncludeStack(SourceMgr.getIncludeLoc(Pos));
   unsigned LineNo = SourceMgr.getLineNumber(Pos);
   
-  const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(FileID);
-  std::cerr << "In file included from " << Buffer->getBufferIdentifier()
+  std::cerr << "In file included from " << SourceMgr.getSourceName(Pos)
             << ":" << LineNo << ":\n";
 }
 
@@ -55,16 +54,16 @@
          "Expect a correspondence between source and carat line!");
   if (!R.isValid()) return;
 
-  unsigned StartLineNo = SourceMgr.getLineNumber(R.Begin());
+  unsigned StartLineNo = SourceMgr.getLogicalLineNumber(R.Begin());
   if (StartLineNo > LineNo) return;  // No intersection.
   
-  unsigned EndLineNo = SourceMgr.getLineNumber(R.End());
+  unsigned EndLineNo = SourceMgr.getLogicalLineNumber(R.End());
   if (EndLineNo < LineNo) return;  // No intersection.
   
   // Compute the column number of the start.
   unsigned StartColNo = 0;
   if (StartLineNo == LineNo) {
-    StartColNo = SourceMgr.getColumnNumber(R.Begin());
+    StartColNo = SourceMgr.getLogicalColumnNumber(R.Begin());
     if (StartColNo) --StartColNo;  // Zero base the col #.
   }
 
@@ -76,7 +75,7 @@
   // Compute the column number of the end.
   unsigned EndColNo = CaratLine.size();
   if (EndLineNo == LineNo) {
-    EndColNo = SourceMgr.getColumnNumber(R.End());
+    EndColNo = SourceMgr.getLogicalColumnNumber(R.End());
     if (EndColNo) {
       --EndColNo;  // Zero base the col #.
       
@@ -112,8 +111,8 @@
   unsigned FileID = Loc.getFileID();
   
   // Create a lexer starting at the beginning of this token.
-  Lexer TheLexer(SourceMgr.getBuffer(FileID), FileID,
-                 *ThePreprocessor,  StrData);
+  Lexer TheLexer(SourceMgr.getBuffer(FileID), Loc,
+                 *ThePreprocessor, StrData);
   
   LexerToken TheTok;
   TheLexer.LexRawToken(TheTok);
@@ -128,35 +127,33 @@
                                              unsigned NumStrs,
                                              const SourceRange *Ranges,
                                              unsigned NumRanges) {
-  unsigned LineNo = 0, FilePos = 0, FileID = 0, ColNo = 0;
-  unsigned LineStart = 0, LineEnd = 0;
-  const llvm::MemoryBuffer *Buffer = 0;
+  unsigned LineNo = 0, ColNo = 0;
+  const char *LineStart = 0, *LineEnd = 0;
   
   if (Pos.isValid()) {
-    LineNo = SourceMgr.getLineNumber(Pos);
-    FileID  = SourceMgr.getLogicalLoc(Pos).getFileID();
+    SourceLocation LPos = SourceMgr.getLogicalLoc(Pos);
+    LineNo = SourceMgr.getLineNumber(LPos);
     
     // First, if this diagnostic is not in the main file, print out the
     // "included from" lines.
-    if (LastWarningLoc != SourceMgr.getIncludeLoc(FileID)) {
-      LastWarningLoc = SourceMgr.getIncludeLoc(FileID);
+    if (LastWarningLoc != SourceMgr.getIncludeLoc(LPos)) {
+      LastWarningLoc = SourceMgr.getIncludeLoc(LPos);
       PrintIncludeStack(LastWarningLoc);
     }
   
     // Compute the column number.  Rewind from the current position to the start
     // of the line.
-    ColNo = SourceMgr.getColumnNumber(Pos);
-    FilePos = SourceMgr.getSourceFilePos(Pos);
-    LineStart = FilePos-ColNo+1;  // Column # is 1-based
+    ColNo = SourceMgr.getColumnNumber(LPos);
+    const char *TokLogicalPtr = SourceMgr.getCharacterData(LPos);
+    LineStart = TokLogicalPtr-ColNo+1;  // Column # is 1-based
   
     // Compute the line end.  Scan forward from the error position to the end of
     // the line.
-    Buffer = SourceMgr.getBuffer(FileID);
-    const char *Buf = Buffer->getBufferStart();
+    const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(LPos.getFileID());
     const char *BufEnd = Buffer->getBufferEnd();
-    LineEnd = FilePos;
-    while (Buf+LineEnd != BufEnd && 
-           Buf[LineEnd] != '\n' && Buf[LineEnd] != '\r')
+    LineEnd = TokLogicalPtr;
+    while (LineEnd != BufEnd && 
+           *LineEnd != '\n' && *LineEnd != '\r')
       ++LineEnd;
   
     std::cerr << Buffer->getBufferIdentifier() 
@@ -180,8 +177,7 @@
   
   if (!NoCaretDiagnostics && Pos.isValid()) {
     // Get the line of the source file.
-    const char *Buf = Buffer->getBufferStart();
-    std::string SourceLine(Buf+LineStart, Buf+LineEnd);
+    std::string SourceLine(LineStart, LineEnd);
     
     // Create a line for the carat that is filled with spaces that is the same
     // length as the line of source code.

Modified: cfe/trunk/Driver/TextDiagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/TextDiagnostics.cpp?rev=40103&r1=40102&r2=40103&view=diff

==============================================================================
--- cfe/trunk/Driver/TextDiagnostics.cpp (original)
+++ cfe/trunk/Driver/TextDiagnostics.cpp Fri Jul 20 11:37:10 2007
@@ -45,9 +45,7 @@
     // diagnostic.
     if (Level == Diagnostic::Warning ||
         Level == Diagnostic::Note) {
-      SourceLocation PhysLoc = SourceMgr.getPhysicalLoc(Pos);
-      const FileEntry *F = SourceMgr.getFileEntryForFileID(PhysLoc.getFileID());
-      if (F) {
+      if (const FileEntry *F = SourceMgr.getFileEntryForLoc(Pos)) {
         DirectoryLookup::DirType DirInfo = TheHeaderSearch->getFileDirFlavor(F);
         if (DirInfo == DirectoryLookup::SystemHeaderDir ||
             DirInfo == DirectoryLookup::ExternCSystemHeaderDir)

Modified: cfe/trunk/Lex/Lexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Lex/Lexer.cpp?rev=40103&r1=40102&r2=40103&view=diff

==============================================================================
--- cfe/trunk/Lex/Lexer.cpp (original)
+++ cfe/trunk/Lex/Lexer.cpp Fri Jul 20 11:37:10 2007
@@ -27,17 +27,17 @@
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include <cctype>
 using namespace clang;
 
 static void InitCharacterInfo();
 
-Lexer::Lexer(const llvm::MemoryBuffer *File, unsigned fileid, Preprocessor &pp,
-             const char *BufStart, const char *BufEnd)
+Lexer::Lexer(const llvm::MemoryBuffer *File, SourceLocation fileloc,
+             Preprocessor &pp, const char *BufStart, const char *BufEnd)
   : BufferEnd(BufEnd ? BufEnd : File->getBufferEnd()),
-    InputFile(File), CurFileID(fileid), PP(pp), Features(PP.getLangOptions()) {
+    InputFile(File), FileLoc(fileloc), PP(pp), Features(PP.getLangOptions()) {
   Is_PragmaLexer = false;
   IsMainFile = false;
   InitCharacterInfo();
@@ -151,7 +151,24 @@
 SourceLocation Lexer::getSourceLocation(const char *Loc) const {
   assert(Loc >= InputFile->getBufferStart() && Loc <= BufferEnd &&
          "Location out of range for this buffer!");
-  return SourceLocation(CurFileID, Loc-InputFile->getBufferStart());
+
+  // In the normal case, we're just lexing from a simple file buffer, return
+  // the file id from FileLoc with the offset specified.
+  unsigned CharNo = Loc-InputFile->getBufferStart();
+  if (FileLoc.isFileID())
+    return SourceLocation::getFileLoc(FileLoc.getFileID(), CharNo);
+  
+  // Otherwise, we're lexing "mapped tokens".  This is used for things like
+  // _Pragma handling.  Combine the instantiation location of FileLoc with the
+  // physical location.
+  SourceManager &SourceMgr = PP.getSourceManager();
+
+  // Create a new SLoc which is expanded from logical(FileLoc) but whose
+  // characters come from phys(FileLoc)+Offset.
+  SourceLocation VirtLoc = SourceMgr.getLogicalLoc(FileLoc);
+  SourceLocation PhysLoc = SourceMgr.getPhysicalLoc(FileLoc);
+  PhysLoc = SourceLocation::getFileLoc(PhysLoc.getFileID(), CharNo);
+  return SourceMgr.getInstantiationLoc(PhysLoc, VirtLoc);
 }
 
 

Modified: cfe/trunk/Lex/MacroExpander.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Lex/MacroExpander.cpp?rev=40103&r1=40102&r2=40103&view=diff

==============================================================================
--- cfe/trunk/Lex/MacroExpander.cpp (original)
+++ cfe/trunk/Lex/MacroExpander.cpp Fri Jul 20 11:37:10 2007
@@ -582,7 +582,8 @@
       assert(FileID && "Could not get FileID for paste?");
       
       // Make a lexer object so that we lex and expand the paste result.
-      Lexer *TL = new Lexer(SourceMgr.getBuffer(FileID), FileID, PP,
+      Lexer *TL = new Lexer(SourceMgr.getBuffer(FileID),
+                            SourceLocation::getFileLoc(FileID, 0), PP,
                             ResultStrData, 
                             ResultStrData+LHSLen+RHSLen /*don't include null*/);
       

Modified: cfe/trunk/Lex/Pragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Lex/Pragma.cpp?rev=40103&r1=40102&r2=40103&view=diff

==============================================================================
--- cfe/trunk/Lex/Pragma.cpp (original)
+++ cfe/trunk/Lex/Pragma.cpp Fri Jul 20 11:37:10 2007
@@ -140,12 +140,12 @@
   SourceLocation TokLoc = CreateString(&StrVal[0], StrVal.size(), StrLoc);
   const char *StrData = SourceMgr.getCharacterData(TokLoc);
 
-  unsigned FileID = TokLoc.getFileID();
+  unsigned FileID = SourceMgr.getPhysicalLoc(TokLoc).getFileID();
   assert(FileID && "Could not get FileID for _Pragma?");
 
   // Make and enter a lexer object so that we lex and expand the tokens just
   // like any others.
-  Lexer *TL = new Lexer(SourceMgr.getBuffer(FileID), FileID, *this,
+  Lexer *TL = new Lexer(SourceMgr.getBuffer(FileID), TokLoc, *this,
                         StrData, StrData+StrVal.size()-1 /* no null */);
   
   // Ensure that the lexer thinks it is inside a directive, so that end \n will
@@ -175,10 +175,10 @@
   }
   
   // Get the current file lexer we're looking at.  Ignore _Pragma 'files' etc.
-  unsigned FileID = getCurrentFileLexer()->getCurFileID();
+  SourceLocation FileLoc = getCurrentFileLexer()->getFileLoc();
   
   // Mark the file as a once-only file now.
-  HeaderInfo.MarkFileIncludeOnce(SourceMgr.getFileEntryForFileID(FileID));
+  HeaderInfo.MarkFileIncludeOnce(SourceMgr.getFileEntryForLoc(FileLoc));
 }
 
 /// HandlePragmaPoison - Handle #pragma GCC poison.  PoisonTok is the 'poison'.
@@ -233,8 +233,7 @@
   Lexer *TheLexer = getCurrentFileLexer();
   
   // Mark the file as a system header.
-  const FileEntry *File = 
-    SourceMgr.getFileEntryForFileID(TheLexer->getCurFileID());
+  const FileEntry *File = SourceMgr.getFileEntryForLoc(TheLexer->getFileLoc());
   HeaderInfo.MarkFileSystemHeader(File);
   
   // Notify the client, if desired, that we are in a new source file.
@@ -274,8 +273,8 @@
     return Diag(FilenameTok, diag::err_pp_file_not_found,
                 std::string(FilenameStart, FilenameEnd));
   
-  unsigned FileID = getCurrentFileLexer()->getCurFileID();
-  const FileEntry *CurFile = SourceMgr.getFileEntryForFileID(FileID);
+  SourceLocation FileLoc = getCurrentFileLexer()->getFileLoc();
+  const FileEntry *CurFile = SourceMgr.getFileEntryForLoc(FileLoc);
 
   // If this file is older than the file it depends on, emit a diagnostic.
   if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) {

Modified: cfe/trunk/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Lex/Preprocessor.cpp?rev=40103&r1=40102&r2=40103&view=diff

==============================================================================
--- cfe/trunk/Lex/Preprocessor.cpp (original)
+++ cfe/trunk/Lex/Preprocessor.cpp Fri Jul 20 11:37:10 2007
@@ -258,34 +258,41 @@
 /// token, return a new location that specifies a character within the token.
 SourceLocation Preprocessor::AdvanceToTokenCharacter(SourceLocation TokStart, 
                                                      unsigned CharNo) {
-  // If they request the first char of the token, we're trivially done.
-  if (CharNo == 0) return TokStart;
+  // If they request the first char of the token, we're trivially done.  If this
+  // is a macro expansion, it doesn't make sense to point to a character within
+  // the instantiation point (the name).  We could point to the source
+  // character, but without also pointing to instantiation info, this is
+  // confusing.
+  if (CharNo == 0 || TokStart.isMacroID()) return TokStart;
   
   // Figure out how many physical characters away the specified logical
   // character is.  This needs to take into consideration newlines and
   // trigraphs.
-  const char *TokStartPtr = SourceMgr.getCharacterData(TokStart);
-  const char *TokPtr = TokStartPtr;
+  const char *TokPtr = SourceMgr.getCharacterData(TokStart);
+  unsigned PhysOffset = 0;
   
   // The usual case is that tokens don't contain anything interesting.  Skip
   // over the uninteresting characters.  If a token only consists of simple
   // chars, this method is extremely fast.
   while (CharNo && Lexer::isObviouslySimpleCharacter(*TokPtr))
-    ++TokPtr, --CharNo;
+    ++TokPtr, --CharNo, ++PhysOffset;
   
   // If we have a character that may be a trigraph or escaped newline, create a
   // lexer to parse it correctly.
-  unsigned FileID = TokStart.getFileID();
-  const llvm::MemoryBuffer *SrcBuf = SourceMgr.getBuffer(FileID);
   if (CharNo != 0) {
     // Create a lexer starting at this token position.
-    Lexer TheLexer(SrcBuf, FileID, *this, TokPtr);
+    const llvm::MemoryBuffer *SrcBuf =SourceMgr.getBuffer(TokStart.getFileID());
+    Lexer TheLexer(SrcBuf, TokStart, *this, TokPtr);
     LexerToken Tok;
     // Skip over characters the remaining characters.
+    const char *TokStartPtr = TokPtr;
     for (; CharNo; --CharNo)
       TheLexer.getAndAdvanceChar(TokPtr, Tok);
+    
+    PhysOffset += TokPtr-TokStartPtr;
   }
-  return SourceLocation(FileID, TokPtr-SrcBuf->getBufferStart());
+  
+  return TokStart.getFileLocWithOffset(PhysOffset);
 }
 
 
@@ -306,8 +313,8 @@
   // info about where the current file is.
   const FileEntry *CurFileEnt = 0;
   if (!FromDir) {
-    unsigned TheFileID = getCurrentFileLexer()->getCurFileID();
-    CurFileEnt = SourceMgr.getFileEntryForFileID(TheFileID);
+    SourceLocation FileLoc = getCurrentFileLexer()->getFileLoc();
+    CurFileEnt = SourceMgr.getFileEntryForLoc(FileLoc);
   }
   
   // Do a standard file entry lookup.
@@ -321,7 +328,7 @@
   // to one of the headers on the #include stack.  Walk the list of the current
   // headers on the #include stack and pass them to HeaderInfo.
   if (CurLexer && !CurLexer->Is_PragmaLexer) {
-    CurFileEnt = SourceMgr.getFileEntryForFileID(CurLexer->getCurFileID());
+    CurFileEnt = SourceMgr.getFileEntryForLoc(CurLexer->getFileLoc());
     if ((FE = HeaderInfo.LookupSubframeworkHeader(FilenameStart, FilenameEnd,
                                                   CurFileEnt)))
       return FE;
@@ -330,8 +337,7 @@
   for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
     IncludeStackInfo &ISEntry = IncludeMacroStack[e-i-1];
     if (ISEntry.TheLexer && !ISEntry.TheLexer->Is_PragmaLexer) {
-      CurFileEnt =
-        SourceMgr.getFileEntryForFileID(ISEntry.TheLexer->getCurFileID());
+      CurFileEnt = SourceMgr.getFileEntryForLoc(ISEntry.TheLexer->getFileLoc());
       if ((FE = HeaderInfo.LookupSubframeworkHeader(FilenameStart, FilenameEnd,
                                                     CurFileEnt)))
         return FE;
@@ -385,7 +391,8 @@
     MaxIncludeStackDepth = IncludeMacroStack.size();
 
   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(FileID);
-  Lexer *TheLexer = new Lexer(Buffer, FileID, *this);
+  Lexer *TheLexer = new Lexer(Buffer, SourceLocation::getFileLoc(FileID, 0),
+                              *this);
   if (isMainFile) TheLexer->setIsMainFile();
   EnterSourceFileWithLexer(TheLexer, CurDir);
 }  
@@ -410,10 +417,10 @@
     
     // Get the file entry for the current file.
     if (const FileEntry *FE = 
-          SourceMgr.getFileEntryForFileID(CurLexer->getCurFileID()))
+           SourceMgr.getFileEntryForLoc(CurLexer->getFileLoc()))
       FileType = HeaderInfo.getFileDirFlavor(FE);
     
-    Callbacks->FileChanged(SourceLocation(CurLexer->getCurFileID(), 0),
+    Callbacks->FileChanged(CurLexer->getFileLoc(),
                            PPCallbacks::EnterFile, FileType);
   }
 }
@@ -878,7 +885,7 @@
   
   if (II == Ident__LINE__) {
     // __LINE__ expands to a simple numeric value.
-    sprintf(TmpBuffer, "%u", SourceMgr.getLineNumber(Tok.getLocation()));
+    sprintf(TmpBuffer, "%u", SourceMgr.getLogicalLineNumber(Tok.getLocation()));
     unsigned Length = strlen(TmpBuffer);
     Tok.setKind(tok::numeric_constant);
     Tok.setLength(Length);
@@ -887,15 +894,15 @@
     SourceLocation Loc = Tok.getLocation();
     if (II == Ident__BASE_FILE__) {
       Diag(Tok, diag::ext_pp_base_file);
-      SourceLocation NextLoc = SourceMgr.getIncludeLoc(Loc.getFileID());
-      while (NextLoc.getFileID() != 0) {
+      SourceLocation NextLoc = SourceMgr.getIncludeLoc(Loc);
+      while (NextLoc.isValid()) {
         Loc = NextLoc;
-        NextLoc = SourceMgr.getIncludeLoc(Loc.getFileID());
+        NextLoc = SourceMgr.getIncludeLoc(Loc);
       }
     }
     
     // Escape this filename.  Turn '\' -> '\\' '"' -> '\"'
-    std::string FN = SourceMgr.getSourceName(Loc);
+    std::string FN = SourceMgr.getSourceName(SourceMgr.getLogicalLoc(Loc));
     FN = '"' + Lexer::Stringify(FN) + '"';
     Tok.setKind(tok::string_literal);
     Tok.setLength(FN.size());
@@ -917,9 +924,9 @@
 
     // Compute the include depth of this token.
     unsigned Depth = 0;
-    SourceLocation Loc = SourceMgr.getIncludeLoc(Tok.getLocation().getFileID());
-    for (; Loc.getFileID() != 0; ++Depth)
-      Loc = SourceMgr.getIncludeLoc(Loc.getFileID());
+    SourceLocation Loc = SourceMgr.getIncludeLoc(Tok.getLocation());
+    for (; Loc.isValid(); ++Depth)
+      Loc = SourceMgr.getIncludeLoc(Loc);
     
     // __INCLUDE_LEVEL__ expands to a simple numeric value.
     sprintf(TmpBuffer, "%u", Depth);
@@ -938,7 +945,7 @@
     Lexer *TheLexer = getCurrentFileLexer();
     
     if (TheLexer)
-      CurFile = SourceMgr.getFileEntryForFileID(TheLexer->getCurFileID());
+      CurFile = SourceMgr.getFileEntryForLoc(TheLexer->getFileLoc());
     
     // If this file is older than the file it depends on, emit a diagnostic.
     const char *Result;
@@ -1061,7 +1068,7 @@
           CurLexer->MIOpt.GetControllingMacroAtEndOfFile()) {
       // Okay, this has a controlling macro, remember in PerFileInfo.
       if (const FileEntry *FE = 
-            SourceMgr.getFileEntryForFileID(CurLexer->getCurFileID()))
+            SourceMgr.getFileEntryForLoc(CurLexer->getFileLoc()))
         HeaderInfo.SetFileControllingMacro(FE, ControllingMacro);
     }
   }
@@ -1078,7 +1085,7 @@
       
       // Get the file entry for the current file.
       if (const FileEntry *FE = 
-            SourceMgr.getFileEntryForFileID(CurLexer->getCurFileID()))
+            SourceMgr.getFileEntryForLoc(CurLexer->getFileLoc()))
         FileType = HeaderInfo.getFileDirFlavor(FE);
 
       Callbacks->FileChanged(CurLexer->getSourceLocation(CurLexer->BufferPtr),

Modified: cfe/trunk/Lex/ScratchBuffer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Lex/ScratchBuffer.cpp?rev=40103&r1=40102&r2=40103&view=diff

==============================================================================
--- cfe/trunk/Lex/ScratchBuffer.cpp (original)
+++ cfe/trunk/Lex/ScratchBuffer.cpp Fri Jul 20 11:37:10 2007
@@ -43,7 +43,7 @@
   assert(BytesUsed-Len < (1 << SourceLocation::FilePosBits) &&
          "Out of range file position!");
   
-  return SourceLocation(FileID, BytesUsed-Len);
+  return SourceLocation::getFileLoc(FileID, BytesUsed-Len);
 }
 
 

Modified: cfe/trunk/include/clang/Basic/SourceLocation.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceLocation.h?rev=40103&r1=40102&r2=40103&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/SourceLocation.h (original)
+++ cfe/trunk/include/clang/Basic/SourceLocation.h Fri Jul 20 11:37:10 2007
@@ -14,6 +14,8 @@
 #ifndef LLVM_CLANG_SOURCELOCATION_H
 #define LLVM_CLANG_SOURCELOCATION_H
 
+#include <cassert>
+
 namespace clang {
     
 /// SourceLocation - This is a carefully crafted 32-bit identifier that encodes
@@ -24,14 +26,20 @@
 public:
   enum {
     FileIDBits  = 14,
-    FilePosBits = 32-FileIDBits
+    FilePosBits = 32-1-FileIDBits,
+    
+    MacroIDBits       = 23,
+    MacroPhysOffsBits = 5,
+    MacroLogOffBits   = 3
   };
 
   SourceLocation() : ID(0) {}  // 0 is an invalid FileID.
   
-  /// SourceLocation constructor - Create a new SourceLocation object with the 
-  /// specified FileID and FilePos.
-  SourceLocation(unsigned FileID, unsigned FilePos) {
+  bool isFileID() const { return (ID >> 31) == 0; }
+  bool isMacroID() const { return (ID >> 31) != 0; }
+  
+  static SourceLocation getFileLoc(unsigned FileID, unsigned FilePos) {
+    SourceLocation L;
     // If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
     // enough consequtive FileIDs that we have one for each chunk.
     if (FilePos >= (1 << FilePosBits)) {
@@ -44,26 +52,68 @@
     if (FileID >= (1 << FileIDBits))
       FileID = (1 << FileIDBits)-1;
     
-    ID = (FileID << FilePosBits) | FilePos;
+    L.ID = (FileID << FilePosBits) | FilePos;
+    return L;
   }
   
+  static SourceLocation getMacroLoc(unsigned MacroID, unsigned PhysOffs,
+                                    unsigned LogOffs) {
+    SourceLocation L;
+    
+    assert(MacroID < (1 << MacroIDBits) && "Too many macros!");
+    assert(PhysOffs < (1 << MacroPhysOffsBits) && "Physoffs too large!");
+    assert(LogOffs  < (1 << MacroLogOffBits) && "Logical offs too large!");
+    
+    L.ID = (1 << 31) | (MacroID << (MacroPhysOffsBits+MacroLogOffBits)) |
+           (PhysOffs << MacroLogOffBits) | LogOffs;
+    return L;
+  }
+  
+  
   /// isValid - Return true if this is a valid SourceLocation object.  Invalid
   /// SourceLocations are often used when events have no corresponding location
   /// in the source (e.g. a diagnostic is required for a command line option).
   ///
   bool isValid() const { return ID != 0; }
+  bool isInvalid() const { return ID == 0; }
   
   /// getFileID - Return the file identifier for this SourceLocation.  This
   /// FileID can be used with the SourceManager object to obtain an entire
   /// include stack for a file position reference.
-  unsigned getFileID() const { return ID >> FilePosBits; }
+  unsigned getFileID() const {
+    assert(isFileID() && "can't get the file id of a non-file sloc!");
+    return ID >> FilePosBits;
+  }
   
   /// getRawFilePos - Return the byte offset from the start of the file-chunk
   /// referred to by FileID.  This method should not be used to get the offset
   /// from the start of the file, instead you should use
   /// SourceManager::getFilePos.  This method will be incorrect for large files.
-  unsigned getRawFilePos() const { return ID & ((1 << FilePosBits)-1); }
+  unsigned getRawFilePos() const { 
+    assert(isFileID() && "can't get the file id of a non-file sloc!");
+    return ID & ((1 << FilePosBits)-1);
+  }
+
+  unsigned getMacroID() const {
+    assert(isMacroID() && "Is not a macro id!");
+    return (ID >> (MacroPhysOffsBits+MacroLogOffBits)) & ((1 << MacroIDBits)-1);
+  }
+  
+  unsigned getMacroPhysOffs() const {
+    assert(isMacroID() && "Is not a macro id!");
+    return (ID >> MacroLogOffBits) & ((1 << MacroPhysOffsBits)-1);
+  }
+  
+  unsigned getMacroLogOffs() const {
+    assert(isMacroID() && "Is not a macro id!");
+    return ID & ((1 << MacroPhysOffsBits)-1);
+  }
   
+  /// getFileLocWithOffset - Return a source location with the specified offset
+  /// from this file SourceLocation.
+  SourceLocation getFileLocWithOffset(unsigned Offset) const {
+    return getFileLoc(getFileID(), getRawFilePos()+Offset);
+  }
   
   /// getRawEncoding - When a SourceLocation itself cannot be used, this returns
   /// an (opaque) 32-bit integer encoding for it.  This should only be passed

Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=40103&r1=40102&r2=40103&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Fri Jul 20 11:37:10 2007
@@ -75,70 +75,51 @@
   ///      from MacroTokenFileID.
   ///
   struct FileIDInfo {
-    enum FileIDType {
-      NormalBuffer,
-      MacroExpansion
-    };
-    
-    /// The type of this FileID.
-    FileIDType IDType;
-    
+  private:
     /// IncludeLoc - The location of the #include that brought in this file.
-    /// This SourceLocation object has a FileId of 0 for the main file.
+    /// This SourceLocation object has an invalid SLOC for the main file.
     SourceLocation IncludeLoc;
     
-    /// This union is discriminated by IDType.
+    /// ChunkNo - Really large buffers are broken up into chunks that are
+    /// each (1 << SourceLocation::FilePosBits) in size.  This specifies the
+    /// chunk number of this FileID.
+    unsigned ChunkNo;
+    
+    /// FileInfo - Information about the source buffer itself.
     ///
-    union {
-      struct NormalBufferInfo {
-        /// ChunkNo - Really large buffers are broken up into chunks that are
-        /// each (1 << SourceLocation::FilePosBits) in size.  This specifies the
-        /// chunk number of this FileID.
-        unsigned ChunkNo;
-        
-        /// FileInfo - Information about the source buffer itself.
-        ///
-        const InfoRec *Info;
-      } NormalBuffer;
-      
-      /// MacroTokenFileID - This is the File ID that contains the characters
-      /// that make up the expanded token.
-      unsigned MacroTokenFileID;
-    } u;
+    const InfoRec *Info;
+  public:
     
-    /// getNormalBuffer - Return a FileIDInfo object for a normal buffer
-    /// reference.
-    static FileIDInfo getNormalBuffer(SourceLocation IL, unsigned CN,
-                                      const InfoRec *Inf) {
+    /// get - Return a FileIDInfo object.
+    static FileIDInfo get(SourceLocation IL, unsigned CN, const InfoRec *Inf) {
       FileIDInfo X;
-      X.IDType = NormalBuffer;
       X.IncludeLoc = IL;
-      X.u.NormalBuffer.ChunkNo = CN;
-      X.u.NormalBuffer.Info = Inf;
+      X.ChunkNo = CN;
+      X.Info = Inf;
       return X;
     }
     
-    /// getMacroExpansion - Return a FileID for a macro expansion.  IL specifies
-    /// the instantiation location, and MacroFID specifies the FileID that the
-    /// token's characters come from. 
-    static FileIDInfo getMacroExpansion(SourceLocation IL,
-                                        unsigned MacroFID) {
-      FileIDInfo X;
-      X.IDType = MacroExpansion;
-      X.IncludeLoc = IL;
-      X.u.MacroTokenFileID = MacroFID;
+    SourceLocation getIncludeLoc() const { return IncludeLoc; }
+    unsigned getChunkNo() const { return ChunkNo; }
+    const InfoRec *getInfo() const { return Info; }
+  };
+  
+  class MacroIDInfo {
+    SourceLocation InstantiationLoc, PhysicalLoc;
+  public:
+    SourceLocation getInstantiationLoc() const { return InstantiationLoc; }
+    SourceLocation getPhysicalLoc() const { return PhysicalLoc; }
+    
+    /// get - Return a MacroID for a macro expansion.  IL specifies
+    /// the instantiation location, and PL specifies the physical location
+    /// (where the characters from the token come from).  Both IL and PL refer
+    /// to normal File SLocs.
+    static MacroIDInfo get(SourceLocation IL, SourceLocation PL) {
+      MacroIDInfo X;
+      X.InstantiationLoc = IL;
+      X.PhysicalLoc = PL;
       return X;
     }
-    
-    unsigned getNormalBufferChunkNo() const {
-      assert(IDType == NormalBuffer && "Not a normal buffer!");
-      return u.NormalBuffer.ChunkNo;
-    }
-
-    const InfoRec *getNormalBufferInfo() const {
-      assert(IDType == NormalBuffer && "Not a normal buffer!");
-      return u.NormalBuffer.Info;
-    }
   };
 }  // end SrcMgr namespace.
 
@@ -169,6 +150,9 @@
   /// entries are off by one.
   std::vector<SrcMgr::FileIDInfo> FileIDs;
   
+  /// MacroIDs - Information about each MacroID.
+  std::vector<SrcMgr::MacroIDInfo> MacroIDs;
+  
   /// LastInstantiationLoc_* - Cache the last instantiation request for fast
   /// lookup.  Macros often want many tokens instantated at the same location.
   SourceLocation LastInstantiationLoc_InstantLoc;
@@ -206,82 +190,76 @@
   }
   
   /// getIncludeLoc - Return the location of the #include for the specified
-  /// FileID.
-  SourceLocation getIncludeLoc(unsigned FileID) const;
-  
-  /// getFilePos - This (efficient) method returns the offset from the start of
-  /// the file that the specified SourceLocation represents.  This returns the
-  /// location of the physical character data, not the logical file position.
-  unsigned getFilePos(SourceLocation Loc) const {
-    const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(Loc.getFileID());
-
-    // For Macros, the physical loc is specified by the MacroTokenFileID.
-    if (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion)
-      FIDInfo = &FileIDs[FIDInfo->u.MacroTokenFileID-1];
-    
-    // If this file has been split up into chunks, factor in the chunk number
-    // that the FileID references.
-    unsigned ChunkNo = FIDInfo->getNormalBufferChunkNo();
-    return Loc.getRawFilePos() + (ChunkNo << SourceLocation::FilePosBits);
+  /// SourceLocation.  If this is a macro expansion, this transparently figures
+  /// out which file includes the file being expanded into.
+  SourceLocation getIncludeLoc(SourceLocation ID) const {
+    return getFIDInfo(getLogicalLoc(ID).getFileID())->getIncludeLoc();
   }
   
   /// getCharacterData - Return a pointer to the start of the specified location
   /// in the appropriate MemoryBuffer.
   const char *getCharacterData(SourceLocation SL) const;
   
-  /// getColumnNumber - Return the column # for the specified include position.
-  /// this is significantly cheaper to compute than the line number.  This
-  /// returns zero if the column number isn't known.
+  /// getColumnNumber - Return the column # for the specified file position.
+  /// This is significantly cheaper to compute than the line number.  This
+  /// returns zero if the column number isn't known.  This may only be called on
+  /// a file sloc, so you must choose a physical or logical location before
+  /// calling this method.
   unsigned getColumnNumber(SourceLocation Loc) const;
   
+  unsigned getPhysicalColumnNumber(SourceLocation Loc) const {
+    return getColumnNumber(getPhysicalLoc(Loc));
+  }
+  unsigned getLogicalColumnNumber(SourceLocation Loc) const {
+    return getColumnNumber(getLogicalLoc(Loc));
+  }
+  
+  
   /// getLineNumber - Given a SourceLocation, return the physical line number
   /// for the position indicated.  This requires building and caching a table of
   /// line offsets for the MemoryBuffer, so this is not cheap: use only when
   /// about to emit a diagnostic.
   unsigned getLineNumber(SourceLocation Loc);
+
+  unsigned getLogicalLineNumber(SourceLocation Loc) {
+    return getLineNumber(getLogicalLoc(Loc));
+  }
+  unsigned getPhysicalLineNumber(SourceLocation Loc) {
+    return getLineNumber(getPhysicalLoc(Loc));
+  }
   
-  /// getSourceFilePos - This method returns the *logical* offset from the start
-  /// of the file that the specified SourceLocation represents.  This returns
-  /// the location of the *logical* character data, not the physical file
-  /// position.  In the case of macros, for example, this returns where the
-  /// macro was instantiated, not where the characters for the macro can be
-  /// found.
-  unsigned getSourceFilePos(SourceLocation Loc) const;
-    
   /// getSourceName - This method returns the name of the file or buffer that
   /// the SourceLocation specifies.  This can be modified with #line directives,
   /// etc.
   std::string getSourceName(SourceLocation Loc);
 
-  /// getFileEntryForFileID - Return the FileEntry record for the specified
-  /// FileID if one exists.
-  const FileEntry *getFileEntryForFileID(unsigned FileID) const {
-    assert(FileID-1 < FileIDs.size() && "Invalid FileID!");
-    return FileIDs[FileID-1].getNormalBufferInfo()->first;
-  }
-  
   /// Given a SourceLocation object, return the logical location referenced by
   /// the ID.  This logical location is subject to #line directives, etc.
   SourceLocation getLogicalLoc(SourceLocation Loc) const {
-    if (Loc.getFileID() == 0) return Loc;
-    
-    const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(Loc.getFileID());
-    if (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion)
-      return FIDInfo->IncludeLoc;
-    return Loc;
+    // File locations are both physical and logical.
+    if (Loc.isFileID()) return Loc;
+
+    SourceLocation ILoc = MacroIDs[Loc.getMacroID()].getInstantiationLoc();
+    return ILoc.getFileLocWithOffset(Loc.getMacroLogOffs());
   }
   
   /// getPhysicalLoc - Given a SourceLocation object, return the physical
   /// location referenced by the ID.
   SourceLocation getPhysicalLoc(SourceLocation Loc) const {
-    if (Loc.getFileID() == 0) return Loc;
+    // File locations are both physical and logical.
+    if (Loc.isFileID()) return Loc;
     
-    // For Macros, the physical loc is specified by the MacroTokenFileID.
-    const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(Loc.getFileID());
-    if (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion)
-      return SourceLocation(FIDInfo->u.MacroTokenFileID,
-                            Loc.getRawFilePos());
-    return Loc;
+    SourceLocation ILoc = MacroIDs[Loc.getMacroID()].getPhysicalLoc();
+    return ILoc.getFileLocWithOffset(Loc.getMacroPhysOffs());
+  }
+
+  /// getFileEntryForLoc - Return the FileEntry record for the physloc of the 
+  /// specified SourceLocation, if one exists.
+  const FileEntry *getFileEntryForLoc(SourceLocation Loc) const {
+    Loc = getPhysicalLoc(Loc);
+    unsigned FileID = Loc.getFileID();
+    assert(FileID-1 < FileIDs.size() && "Invalid FileID!");
+    return FileIDs[FileID-1].getInfo()->first;
   }
   
   /// PrintStats - Print statistics to stderr.
@@ -305,33 +283,36 @@
     assert(FileID-1 < FileIDs.size() && "Invalid FileID!");
     return &FileIDs[FileID-1];
   }
-    
-  /// Return the InfoRec structure for the specified FileID.  This is always the
-  /// physical reference for the ID.
-  const SrcMgr::InfoRec *getInfoRec(const SrcMgr::FileIDInfo *FIDInfo) const {
-    // For Macros, the physical loc is specified by the MacroTokenFileID.
-    if (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion)
-      FIDInfo = &FileIDs[FIDInfo->u.MacroTokenFileID-1];
-    return FIDInfo->getNormalBufferInfo();
-  }
+  
   const SrcMgr::InfoRec *getInfoRec(unsigned FileID) const {
     return getInfoRec(getFIDInfo(FileID));
   }
   
-  SrcMgr::FileInfo *getFileInfo(const SrcMgr::FileIDInfo *FIDInfo) const {
-    if (const SrcMgr::InfoRec *IR = getInfoRec(FIDInfo))
-      return const_cast<SrcMgr::FileInfo *>(&IR->second);
-    return 0;
-  }
   SrcMgr::FileInfo *getFileInfo(unsigned FileID) const {
     if (const SrcMgr::InfoRec *IR = getInfoRec(FileID))
       return const_cast<SrcMgr::FileInfo *>(&IR->second);
     return 0;
   }
-  SrcMgr::FileInfo *getFileInfo(const FileEntry *SourceFile) {
-    if (const SrcMgr::InfoRec *IR = getInfoRec(SourceFile))
-      return const_cast<SrcMgr::FileInfo *>(&IR->second);
-    return 0;
+  
+  /// Return the InfoRec structure for the specified FileID.  This is always the
+  /// physical reference for the ID.
+  const SrcMgr::InfoRec *getInfoRec(const SrcMgr::FileIDInfo *FIDInfo) const {
+    return FIDInfo->getInfo();
+  }
+  
+  
+  /// getFullFilePos - This (efficient) method returns the offset from the start
+  /// of the file that the specified physical SourceLocation represents.  This
+  /// returns the location of the physical character data, not the logical file
+  /// position.
+  unsigned getFullFilePos(SourceLocation PhysLoc) const {
+    // TODO: Add a flag "is first chunk" to SLOC.
+    const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(PhysLoc.getFileID());
+    
+    // If this file has been split up into chunks, factor in the chunk number
+    // that the FileID references.
+    unsigned ChunkNo = FIDInfo->getChunkNo();
+    return PhysLoc.getRawFilePos() + (ChunkNo << SourceLocation::FilePosBits);
   }
 };
 

Modified: cfe/trunk/include/clang/Lex/Lexer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Lexer.h?rev=40103&r1=40102&r2=40103&view=diff

==============================================================================
--- cfe/trunk/include/clang/Lex/Lexer.h (original)
+++ cfe/trunk/include/clang/Lex/Lexer.h Fri Jul 20 11:37:10 2007
@@ -38,7 +38,7 @@
   // Constant configuration values for this lexer.
   const char * const BufferEnd;  // End of the buffer.
   const llvm::MemoryBuffer *InputFile; // The file we are reading from.
-  unsigned CurFileID;            // FileID for the current input file.
+  SourceLocation FileLoc;        // Location for start of file.
   Preprocessor &PP;              // Preprocessor object controlling lexing.
   LangOptions Features;          // Features enabled by this language (cache).
   bool Is_PragmaLexer;           // True if lexer for _Pragma handling.
@@ -100,16 +100,18 @@
   /// with the specified preprocessor managing the lexing process.  This lexer
   /// assumes that the specified MemoryBuffer and Preprocessor objects will
   /// outlive it, but doesn't take ownership of either pointer.
-    Lexer(const llvm::MemoryBuffer *InBuffer, unsigned CurFileID, 
-          Preprocessor &PP, const char *BufStart = 0, const char *BufEnd = 0);
+  Lexer(const llvm::MemoryBuffer *InBuffer, SourceLocation FileLoc, 
+        Preprocessor &PP, const char *BufStart = 0, const char *BufEnd = 0);
   
   /// getFeatures - Return the language features currently enabled.  NOTE: this
   /// lexer modifies features as a file is parsed!
   const LangOptions &getFeatures() const { return Features; }
 
-  /// getCurFileID - Return the FileID for the file we are lexing out of.  This
-  /// implicitly encodes the include path to get to the file.
-  unsigned getCurFileID() const { return CurFileID; }
+  /// getFileLoc - Return the File Location for the file we are lexing out of.
+  /// The physical location encodes the location where the characters come from,
+  /// the virtual location encodes where we should *claim* the characters came
+  /// from.  Currently this is only used by _Pragma handling.
+  SourceLocation getFileLoc() const { return FileLoc; }
   
   /// setIsMainFile - Mark this lexer as being the lexer for the top-level
   /// source file.





More information about the cfe-commits mailing list