[cfe-commits] r140060 - in /cfe/trunk: include/clang/Basic/SourceManager.h include/clang/Frontend/ASTUnit.h lib/Basic/SourceManager.cpp lib/Frontend/ASTUnit.cpp lib/Frontend/CompilerInstance.cpp lib/Serialization/ASTReader.cpp test/PCH/preamble.c tools/libclang/CIndex.cpp

Argyrios Kyrtzidis akyrtzi at gmail.com
Mon Sep 19 13:40:35 PDT 2011


Author: akirtzidis
Date: Mon Sep 19 15:40:35 2011
New Revision: 140060

URL: http://llvm.org/viewvc/llvm-project?rev=140060&view=rev
Log:
[libclang] When getting a source location from a file:line:col triplet
check whether the requested location points inside the precompiled preamble,
in which case the returned source location will be a "loaded" one.

Modified:
    cfe/trunk/include/clang/Basic/SourceManager.h
    cfe/trunk/include/clang/Frontend/ASTUnit.h
    cfe/trunk/lib/Basic/SourceManager.cpp
    cfe/trunk/lib/Frontend/ASTUnit.cpp
    cfe/trunk/lib/Frontend/CompilerInstance.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/test/PCH/preamble.c
    cfe/trunk/tools/libclang/CIndex.cpp

Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=140060&r1=140059&r2=140060&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Mon Sep 19 15:40:35 2011
@@ -559,6 +559,9 @@
   /// MainFileID - The file ID for the main source file of the translation unit.
   FileID MainFileID;
 
+  /// \brief The file ID for the precompiled preamble there is one.
+  FileID PreambleFileID;
+
   // Statistics for -print-stats.
   mutable unsigned NumLinearScans, NumBinaryProbes;
 
@@ -610,13 +613,15 @@
     return MainFileID;
   }
 
-  /// \brief Set the file ID for the precompiled preamble, which is also the
-  /// main file.
-  void SetPreambleFileID(FileID Preamble) {
-    assert(MainFileID.isInvalid() && "MainFileID already set!");
-    MainFileID = Preamble;
+  /// \brief Set the file ID for the precompiled preamble.
+  void setPreambleFileID(FileID Preamble) {
+    assert(PreambleFileID.isInvalid() && "PreambleFileID already set!");
+    PreambleFileID = Preamble;
   }
 
+  /// \brief Get the file ID for the precompiled preamble if there is one.
+  FileID getPreambleFileID() const { return PreambleFileID; }
+
   //===--------------------------------------------------------------------===//
   // Methods to create new FileID's and macro expansions.
   //===--------------------------------------------------------------------===//
@@ -1117,11 +1122,12 @@
   /// 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);
+                                      unsigned Line, unsigned Col) const;
 
   /// \brief Get the source location in \arg FID for the given line:col.
   /// Returns null location if \arg FID is not a file SLocEntry.
-  SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col);
+  SourceLocation translateLineCol(FileID FID,
+                                  unsigned Line, unsigned Col) const;
 
   /// \brief If \arg Loc points inside a function macro argument, the returned
   /// location will be the macro location in which the argument was expanded.
@@ -1132,7 +1138,7 @@
   ///             ^
   /// Passing a file location pointing at 'foo', will yield a macro location
   /// where 'foo' was expanded into.
-  SourceLocation getMacroArgExpandedLocation(SourceLocation Loc);
+  SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const;
 
   /// \brief Determines the order of 2 source locations in the translation unit.
   ///
@@ -1309,7 +1315,7 @@
   std::pair<FileID, unsigned>
   getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
                                    unsigned Offset) const;
-  void computeMacroArgsCache(SrcMgr::ContentCache *Content, FileID FID);
+  void computeMacroArgsCache(SrcMgr::ContentCache *Content, FileID FID) const;
 
   friend class ASTReader;
   friend class ASTWriter;

Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=140060&r1=140059&r2=140060&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTUnit.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h Mon Sep 19 15:40:35 2011
@@ -196,9 +196,41 @@
   /// \brief The file in which the precompiled preamble is stored.
   std::string PreambleFile;
   
+  class PreambleData {
+    const FileEntry *File;
+    std::vector<char> Buffer;
+    mutable unsigned NumLines;
+    
+  public:
+    PreambleData() : File(0), NumLines(0) { }
+    
+    void assign(const FileEntry *F, const char *begin, const char *end) {
+      File = F;
+      Buffer.assign(begin, end);
+      NumLines = 0;
+    }
+
+    void clear() { Buffer.clear(); File = 0; NumLines = 0; }
+
+    size_t size() const { return Buffer.size(); }
+    bool empty() const { return Buffer.empty(); }
+
+    const char *getBufferStart() const { return &Buffer[0]; }
+
+    unsigned getNumLines() const {
+      if (NumLines)
+        return NumLines;
+      countLines();
+      return NumLines;
+    }
+
+  private:
+    void countLines() const;
+  };
+
   /// \brief The contents of the preamble that has been precompiled to
   /// \c PreambleFile.
-  std::vector<char> Preamble;
+  PreambleData Preamble;
 
   /// \brief Whether the preamble ends at the start of a new line.
   /// 
@@ -515,6 +547,21 @@
   PreprocessedEntitiesByFileMap &getPreprocessedEntitiesByFile() {
     return PreprocessedEntitiesByFile;
   }
+
+  /// \brief Get the source location for the given file:line:col triplet.
+  ///
+  /// The difference with SourceManager::getLocation is that this method checks
+  /// whether the requested location points inside the precompiled preamble
+  /// in which case the returned source location will be a "loaded" one.
+  SourceLocation getLocation(const FileEntry *File,
+                             unsigned Line, unsigned Col) const;
+
+  /// \brief Get the source location for the given file:offset pair.
+  ///
+  /// The difference with SourceManager::getLocation is that this method checks
+  /// whether the requested location points inside the precompiled preamble
+  /// in which case the returned source location will be a "loaded" one.
+  SourceLocation getLocation(const FileEntry *File, unsigned Offset) const;
   
   // Retrieve the diagnostics associated with this AST
   typedef const StoredDiagnostic *stored_diag_iterator;

Modified: cfe/trunk/lib/Basic/SourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/SourceManager.cpp?rev=140060&r1=140059&r2=140060&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/SourceManager.cpp (original)
+++ cfe/trunk/lib/Basic/SourceManager.cpp Mon Sep 19 15:40:35 2011
@@ -1324,7 +1324,8 @@
 /// If the source file is included multiple times, the source location will
 /// be based upon an arbitrary inclusion.
 SourceLocation SourceManager::translateFileLineCol(const FileEntry *SourceFile,
-                                                  unsigned Line, unsigned Col) {
+                                                  unsigned Line,
+                                                  unsigned Col) const {
   assert(SourceFile && "Null source file!");
   assert(Line && Col && "Line and column should start from 1!");
 
@@ -1439,7 +1440,8 @@
 /// \brief Get the source location in \arg FID for the given line:col.
 /// Returns null location if \arg FID is not a file SLocEntry.
 SourceLocation SourceManager::translateLineCol(FileID FID,
-                                               unsigned Line, unsigned Col) {
+                                               unsigned Line,
+                                               unsigned Col) const {
   if (FID.isInvalid())
     return SourceLocation();
 
@@ -1496,7 +1498,8 @@
 ///     0   -> SourceLocation()
 ///     100 -> Expanded macro arg location
 ///     110 -> SourceLocation()
-void SourceManager::computeMacroArgsCache(ContentCache *Content, FileID FID) {
+void SourceManager::computeMacroArgsCache(ContentCache *Content,
+                                          FileID FID) const {
   assert(!Content->MacroArgsCache);
   assert(!FID.isInvalid());
 
@@ -1575,7 +1578,8 @@
 ///             ^
 /// Passing a file location pointing at 'foo', will yield a macro location
 /// where 'foo' was expanded into.
-SourceLocation SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) {
+SourceLocation
+SourceManager::getMacroArgExpandedLocation(SourceLocation Loc) const {
   if (Loc.isInvalid() || !Loc.isFileID())
     return Loc;
 

Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=140060&r1=140059&r2=140060&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Mon Sep 19 15:40:35 2011
@@ -1200,7 +1200,7 @@
     if (Preamble.size() == NewPreamble.second.first &&
         PreambleEndsAtStartOfLine == NewPreamble.second.second &&
         NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
-        memcmp(&Preamble[0], NewPreamble.first->getBufferStart(),
+        memcmp(Preamble.getBufferStart(), NewPreamble.first->getBufferStart(),
                NewPreamble.second.first) == 0) {
       // The preamble has not changed. We may be able to re-use the precompiled
       // preamble.
@@ -1332,7 +1332,9 @@
 
   // Save the preamble text for later; we'll need to compare against it for
   // subsequent reparses.
-  Preamble.assign(NewPreamble.first->getBufferStart(), 
+  StringRef MainFilename = PreambleInvocation->getFrontendOpts().Inputs[0].second;
+  Preamble.assign(FileMgr->getFile(MainFilename),
+                  NewPreamble.first->getBufferStart(), 
                   NewPreamble.first->getBufferStart() 
                                                   + NewPreamble.second.first);
   PreambleEndsAtStartOfLine = NewPreamble.second.second;
@@ -2396,3 +2398,41 @@
   }
   Result.swap(Out);
 }
+
+SourceLocation ASTUnit::getLocation(const FileEntry *File,
+                                    unsigned Line, unsigned Col) const {
+  const SourceManager &SM = getSourceManager();
+  SourceLocation Loc;
+  if (!Preamble.empty() && Line <= Preamble.getNumLines())
+    Loc = SM.translateLineCol(SM.getPreambleFileID(), Line, Col);
+  else
+    Loc = SM.translateFileLineCol(File, Line, Col);
+
+  return SM.getMacroArgExpandedLocation(Loc);
+}
+
+SourceLocation ASTUnit::getLocation(const FileEntry *File,
+                                    unsigned Offset) const {
+  const SourceManager &SM = getSourceManager();
+  SourceLocation FileLoc;
+  if (!Preamble.empty() && Offset < Preamble.size())
+    FileLoc = SM.getLocForStartOfFile(SM.getPreambleFileID());
+  else
+    FileLoc = SM.translateFileLineCol(File, 1, 1);
+
+  return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset));
+}
+
+void ASTUnit::PreambleData::countLines() const {
+  NumLines = 0;
+  if (empty())
+    return;
+
+  for (std::vector<char>::const_iterator
+         I = Buffer.begin(), E = Buffer.end(); I != E; ++I) {
+    if (*I == '\n')
+      ++NumLines;
+  }
+  if (Buffer.back() != '\n')
+    ++NumLines;
+}

Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=140060&r1=140059&r2=140060&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Mon Sep 19 15:40:35 2011
@@ -539,11 +539,8 @@
                                                FileManager &FileMgr,
                                                SourceManager &SourceMgr,
                                                const FrontendOptions &Opts) {
-  // Figure out where to get and map in the main file, unless it's already
-  // been created (e.g., by a precompiled preamble).
-  if (!SourceMgr.getMainFileID().isInvalid()) {
-    // Do nothing: the main file has already been set.
-  } else if (InputFile != "-") {
+  // Figure out where to get and map in the main file.
+  if (InputFile != "-") {
     const FileEntry *File = FileMgr.getFile(InputFile);
     if (!File) {
       Diags.Report(diag::err_fe_error_reading) << InputFile;

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=140060&r1=140059&r2=140060&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Sep 19 15:40:35 2011
@@ -2508,23 +2508,15 @@
   if (DeserializationListener)
     DeserializationListener->ReaderInitialized(this);
 
-  // If this AST file is a precompiled preamble, then set the main file ID of 
-  // the source manager to the file source file from which the preamble was
-  // built. This is the only valid way to use a precompiled preamble.
+  // If this AST file is a precompiled preamble, then set the preamble file ID
+  // of the source manager to the file source file from which the preamble was
+  // built.
   if (Type == MK_Preamble) {
-    if (OriginalFileID.isInvalid()) {
-      SourceLocation Loc
-        = SourceMgr.getLocation(FileMgr.getFile(getOriginalSourceFile()), 1, 1);
-      if (Loc.isValid())
-        OriginalFileID = SourceMgr.getDecomposedLoc(Loc).first;
-    }
-    else {
+    if (!OriginalFileID.isInvalid()) {
       OriginalFileID = FileID::get(ModuleMgr.getPrimaryModule().SLocEntryBaseID
                                         + OriginalFileID.getOpaqueValue() - 1);
+      SourceMgr.setPreambleFileID(OriginalFileID);
     }
-
-    if (!OriginalFileID.isInvalid())
-      SourceMgr.SetPreambleFileID(OriginalFileID);
   }
   
   return Success;

Modified: cfe/trunk/test/PCH/preamble.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/preamble.c?rev=140060&r1=140059&r2=140060&view=diff
==============================================================================
--- cfe/trunk/test/PCH/preamble.c (original)
+++ cfe/trunk/test/PCH/preamble.c Mon Sep 19 15:40:35 2011
@@ -1,7 +1,7 @@
 // Check that using the preamble option actually skips the preamble.
 
-// RUN: %clang_cc1 -emit-pch -o %t %S/Inputs/preamble.h
-// RUN: %clang_cc1 -include-pch %t -preamble-bytes=278,1 -DFOO=f -verify %s
+// RUN: %clang_cc1 -emit-pch -o %t %S/Inputs/preamble.h -DFOO=f
+// RUN: %clang_cc1 -include-pch %t -preamble-bytes=317,1 -DFOO=f -verify %s -emit-llvm -o - | FileCheck %s
 
 float f(int); // Not an error, because we skip this via the preamble!
 
@@ -19,3 +19,5 @@
 int g(int x) {
   return FOO(x);
 }
+
+// CHECK: call {{.*}} @f(

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=140060&r1=140059&r2=140060&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Mon Sep 19 15:40:35 2011
@@ -2750,8 +2750,7 @@
   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(File, line, column);
+  SourceLocation SLoc = CXXUnit->getLocation(File, line, column);
   if (SLoc.isInvalid()) {
     if (Logging)
       llvm::errs() << "clang_getLocation(\"" << File->getName() 
@@ -2774,14 +2773,8 @@
     return clang_getNullLocation();
   
   ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData);
-  SourceLocation Start 
-    = CXXUnit->getSourceManager().getLocation(
-                                        static_cast<const FileEntry *>(file),
-                                              1, 1);
-  if (Start.isInvalid()) return clang_getNullLocation();
-
-  SourceLocation SLoc = Start.getLocWithOffset(offset);
-
+  SourceLocation SLoc 
+    = CXXUnit->getLocation(static_cast<const FileEntry *>(file), offset);
   if (SLoc.isInvalid()) return clang_getNullLocation();
 
   return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);





More information about the cfe-commits mailing list