diff options
| -rw-r--r-- | clang/include/clang/Basic/SourceManager.h | 24 | ||||
| -rw-r--r-- | clang/include/clang/Frontend/ASTUnit.h | 49 | ||||
| -rw-r--r-- | clang/lib/Basic/SourceManager.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/Frontend/ASTUnit.cpp | 44 | ||||
| -rw-r--r-- | clang/lib/Frontend/CompilerInstance.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 18 | ||||
| -rw-r--r-- | clang/test/PCH/preamble.c | 6 | ||||
| -rw-r--r-- | clang/tools/libclang/CIndex.cpp | 13 | 
8 files changed, 127 insertions, 46 deletions
diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index 09aadcebba4..46fdbe50663 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -559,6 +559,9 @@ class SourceManager : public llvm::RefCountedBase<SourceManager> {    /// 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 @@ public:      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 @@ public:    /// 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 @@ public:    ///             ^    /// 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 @@ private:    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; diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h index e2fa5574fe6..4a8475bb6c4 100644 --- a/clang/include/clang/Frontend/ASTUnit.h +++ b/clang/include/clang/Frontend/ASTUnit.h @@ -196,9 +196,41 @@ private:    /// \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 @@ public:    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; diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 38cc9946be1..68c98fe02c6 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -1324,7 +1324,8 @@ static llvm::Optional<ino_t> getActualFileInode(const FileEntry *File) {  /// 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 @@ SourceLocation SourceManager::translateFileLineCol(const FileEntry *SourceFile,  /// \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 @@ SourceLocation SourceManager::translateLineCol(FileID FID,  ///     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 @@ void SourceManager::computeMacroArgsCache(ContentCache *Content, FileID FID) {  ///             ^  /// 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; diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 6f9b4378141..53e0412750e 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -1200,7 +1200,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(      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 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(    // 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 @@ void ASTUnit::TranslateStoredDiagnostics(    }    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; +} diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 92798c8c292..924864c8ccd 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -539,11 +539,8 @@ bool CompilerInstance::InitializeSourceManager(StringRef InputFile,                                                 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; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 0f3cad55139..02d7eeaa8dd 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2508,23 +2508,15 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,    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; diff --git a/clang/test/PCH/preamble.c b/clang/test/PCH/preamble.c index bdc0aea6563..6a61fa10ffa 100644 --- a/clang/test/PCH/preamble.c +++ b/clang/test/PCH/preamble.c @@ -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 @@ float f(int); // Not an error, because we skip this via the preamble!  int g(int x) {    return FOO(x);  } + +// CHECK: call {{.*}} @f( diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 3654a58a5d4..8390a7ce8db 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2750,8 +2750,7 @@ CXSourceLocation clang_getLocation(CXTranslationUnit tu,    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 @@ CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu,      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);  | 

