[llvm-branch-commits] [cfe-branch] r125034 - in /cfe/branches/Apple/sill: include/clang/Basic/SourceManager.h lib/Basic/SourceManager.cpp tools/libclang/CIndex.cpp

Daniel Dunbar daniel at zuster.org
Mon Feb 7 11:59:44 PST 2011


Author: ddunbar
Date: Mon Feb  7 13:59:44 2011
New Revision: 125034

URL: http://llvm.org/viewvc/llvm-project?rev=125034&view=rev
Log:
Merge r124800:
--
Author: Douglas Gregor <dgregor at apple.com>
Date:   Thu Feb 3 17:17:35 2011 +0000

    Teach SourceManager::getLocation() how to cope with a source file
    whose inode has changed since the file was first created and that is
    being seen through a different path name (e.g., due to symlinks or
    relative path elements), such that its FileEntry pointer doesn't match
    a known FileEntry pointer. Since this requires a system call (to
    stat()), we only perform this deeper checking if we can't find the
    file by comparing FileEntry pointers.

    Also, add a micro-optimization where we don't bother to compute line
    numbers when given the location (1, 1). This improves the
    efficiency of clang_getLocationForOffset().

*** MANUAL MERGE ***

Modified:
    cfe/branches/Apple/sill/include/clang/Basic/SourceManager.h
    cfe/branches/Apple/sill/lib/Basic/SourceManager.cpp
    cfe/branches/Apple/sill/tools/libclang/CIndex.cpp

Modified: cfe/branches/Apple/sill/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/sill/include/clang/Basic/SourceManager.h?rev=125034&r1=125033&r2=125034&view=diff
==============================================================================
--- cfe/branches/Apple/sill/include/clang/Basic/SourceManager.h (original)
+++ cfe/branches/Apple/sill/include/clang/Basic/SourceManager.h Mon Feb  7 13:59:44 2011
@@ -792,7 +792,7 @@
   /// If the source file is included multiple times, the source location will
   /// be based upon the first inclusion.
   SourceLocation getLocation(const FileEntry *SourceFile,
-                             unsigned Line, unsigned Col) const;
+                             unsigned Line, unsigned Col);
 
   /// \brief Determines the order of 2 source locations in the translation unit.
   ///

Modified: cfe/branches/Apple/sill/lib/Basic/SourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/sill/lib/Basic/SourceManager.cpp?rev=125034&r1=125033&r2=125034&view=diff
==============================================================================
--- cfe/branches/Apple/sill/lib/Basic/SourceManager.cpp (original)
+++ cfe/branches/Apple/sill/lib/Basic/SourceManager.cpp Mon Feb  7 13:59:44 2011
@@ -16,12 +16,14 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/FileManager.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/ADT/Optional.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/System/Path.h"
 #include <algorithm>
 #include <string>
 #include <cstring>
+#include <sys/stat.h>
 
 using namespace clang;
 using namespace SrcMgr;
@@ -1113,38 +1115,58 @@
 // Other miscellaneous methods.
 //===----------------------------------------------------------------------===//
 
+/// \brief Retrieve the inode for the given file entry, if possible.
+///
+/// This routine involves a system call, and therefore should only be used
+/// in non-performance-critical code.
+static llvm::Optional<ino_t> getActualFileInode(const FileEntry *File) {
+  if (!File)
+    return llvm::Optional<ino_t>();
+  
+  struct stat StatBuf;
+  if (::stat(File->getName(), &StatBuf))
+    return llvm::Optional<ino_t>();
+    
+  return StatBuf.st_ino;
+}
+
 /// \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 SourceManager::getLocation(const FileEntry *SourceFile,
-                                          unsigned Line, unsigned Col) const {
+                                          unsigned Line, unsigned Col) {
   assert(SourceFile && "Null source file!");
   assert(Line && Col && "Line and column should start from 1!");
 
-  fileinfo_iterator FI = FileInfos.find(SourceFile);
-  if (FI == FileInfos.end())
-    return SourceLocation();
-  ContentCache *Content = FI->second;
-
-  // If this is the first use of line information for this buffer, compute the
-  /// SourceLineCache for it on demand.
-  if (Content->SourceLineCache == 0) {
-    bool MyInvalid = false;
-    ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid);
-    if (MyInvalid)
-      return SourceLocation();
-  }
-
   // Find the first file ID that corresponds to the given file.
   FileID FirstFID;
 
   // First, check the main file ID, since it is common to look for a
   // location in the main file.
+  llvm::Optional<ino_t> SourceFileInode;
+  llvm::Optional<llvm::StringRef> SourceFileName;
   if (!MainFileID.isInvalid()) {
     const SLocEntry &MainSLoc = getSLocEntry(MainFileID);
-    if (MainSLoc.isFile() && MainSLoc.getFile().getContentCache() == Content)
-      FirstFID = MainFileID;
+    if (MainSLoc.isFile()) {
+      const ContentCache *MainContentCache
+        = MainSLoc.getFile().getContentCache();
+      if (MainContentCache->Entry == SourceFile)
+        FirstFID = MainFileID;
+      else if (MainContentCache) {
+        // Fall back: check whether we have the same base name and inode
+        // as the main file.
+        const FileEntry *MainFile = MainContentCache->Entry;
+        SourceFileName = llvm::sys::Path(SourceFile->getName()).getLast();
+        if (*SourceFileName == llvm::sys::Path(MainFile->getName()).getLast()) {
+          SourceFileInode = getActualFileInode(SourceFile);
+          if (SourceFileInode == getActualFileInode(MainFile)) {
+            FirstFID = MainFileID;
+            SourceFile = MainFile;
+          }
+        }
+      }
+    }
   }
 
   if (FirstFID.isInvalid()) {
@@ -1152,16 +1174,60 @@
     // through all of the source locations.
     for (unsigned I = 0, N = sloc_entry_size(); I != N; ++I) {
       const SLocEntry &SLoc = getSLocEntry(I);
-      if (SLoc.isFile() && SLoc.getFile().getContentCache() == Content) {
+      if (SLoc.isFile() && 
+          SLoc.getFile().getContentCache() &&
+          SLoc.getFile().getContentCache()->Entry == SourceFile) {
         FirstFID = FileID::get(I);
         break;
       }
     }
   }
+
+  // If we haven't found what we want yet, try again, but this time stat()
+  // each of the files in case the files have changed since we originally 
+  // parsed the file. 
+  if (FirstFID.isInvalid() &&
+      (SourceFileName || 
+       (SourceFileName = llvm::sys::Path(SourceFile->getName()).getLast())) &&
+      (SourceFileInode ||
+       (SourceFileInode = getActualFileInode(SourceFile)))) {
+    for (unsigned I = 0, N = sloc_entry_size(); I != N; ++I) {
+      const SLocEntry &SLoc = getSLocEntry(I);
+      if (SLoc.isFile()) { 
+        const ContentCache *FileContentCache 
+          = SLoc.getFile().getContentCache();
+        const FileEntry *Entry =FileContentCache? FileContentCache->Entry : 0;
+        if (Entry && 
+            *SourceFileName == llvm::sys::Path(Entry->getName()).getLast() &&
+            SourceFileInode == getActualFileInode(Entry)) {
+          FirstFID = FileID::get(I);
+          SourceFile = Entry;
+          break;
+        }
+      }
+    }      
+  }
     
   if (FirstFID.isInvalid())
     return SourceLocation();
 
+  if (Line == 1 && Col == 1)
+    return getLocForStartOfFile(FirstFID);
+
+  ContentCache *Content
+    = const_cast<ContentCache *>(getOrCreateContentCache(SourceFile));
+  if (!Content)
+    return SourceLocation();
+    
+  // If this is the first use of line information for this buffer, compute the
+  /// SourceLineCache for it on demand.
+  if (Content->SourceLineCache == 0) {
+    bool MyInvalid = false;
+    ComputeLineNumbers(Diag, Content, ContentCacheAlloc, *this, MyInvalid);
+    if (MyInvalid)
+      return SourceLocation();
+  }
+
   if (Line > Content->NumLines) {
     unsigned Size = Content->getBuffer(Diag, *this)->getBufferSize();
     if (Size > 0)

Modified: cfe/branches/Apple/sill/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/sill/tools/libclang/CIndex.cpp?rev=125034&r1=125033&r2=125034&view=diff
==============================================================================
--- cfe/branches/Apple/sill/tools/libclang/CIndex.cpp (original)
+++ cfe/branches/Apple/sill/tools/libclang/CIndex.cpp Mon Feb  7 13:59:44 2011
@@ -2439,12 +2439,22 @@
   if (!tu || !file)
     return clang_getNullLocation();
   
+  bool Logging = ::getenv("LIBCLANG_LOGGING");
   ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
+  const FileEntry *File = static_cast<const FileEntry *>(file);
   SourceLocation SLoc
-    = CXXUnit->getSourceManager().getLocation(
-                                        static_cast<const FileEntry *>(file),
-                                              line, column);
-  if (SLoc.isInvalid()) return clang_getNullLocation();
+    = CXXUnit->getSourceManager().getLocation(File, line, column);
+  if (SLoc.isInvalid()) {
+    if (Logging)
+      llvm::errs() << "clang_getLocation(\"" << File->getName() 
+                   << "\", " << line << ", " << column << ") = invalid\n";
+    return clang_getNullLocation();
+  }
+
+  if (Logging)
+    llvm::errs() << "clang_getLocation(\"" << File->getName() 
+                 << "\", " << line << ", " << column << ") = " 
+                 << SLoc.getRawEncoding() << "\n";
 
   return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
 }





More information about the llvm-branch-commits mailing list