Index: clang/include/clang/Basic/SourceManager.h =================================================================== --- clang/include/clang/Basic/SourceManager.h +++ clang/include/clang/Basic/SourceManager.h @@ -90,6 +90,34 @@ return CK == C_User_ModuleMap || CK == C_System_ModuleMap; } + /// Mapping of line offsets into a source file. This does not own the storage + /// for the line numbers. + class LineOffsetMapping { + public: + explicit operator bool() const { return Storage; } + unsigned getNumLines() const { + assert(Storage); + return Storage[0]; + } + ArrayRef getLines() const { + assert(Storage); + return ArrayRef(Storage + 1, Storage + 1 + Storage[0]); + } + const unsigned *begin() const { return getLines().begin(); } + const unsigned *end() const { return getLines().end(); } + const unsigned &operator[](int I) const { return getLines()[I]; } + + static LineOffsetMapping get(llvm::MemoryBufferRef Buffer, + llvm::BumpPtrAllocator &Alloc); + + LineOffsetMapping() = default; + LineOffsetMapping(ArrayRef LineOffsets, + llvm::BumpPtrAllocator &Alloc); + + private: + unsigned *Storage = nullptr; + }; + /// One instance of this struct is kept for every file loaded or used. /// /// This object owns the MemoryBuffer object. @@ -115,14 +143,9 @@ /// A bump pointer allocated array of offsets for each source line. /// - /// This is lazily computed. This is owned by the SourceManager + /// This is lazily computed. The lines are owned by the SourceManager /// BumpPointerAllocator object. - unsigned *SourceLineCache = nullptr; - - /// The number of lines in this ContentCache. - /// - /// This is only valid if SourceLineCache is non-null. - unsigned NumLines = 0; + LineOffsetMapping SourceLineCache; /// Indicates whether the buffer itself was provided to override /// the actual file contents. @@ -157,10 +180,8 @@ OrigEntry = RHS.OrigEntry; ContentsEntry = RHS.ContentsEntry; - assert(!RHS.Buffer && RHS.SourceLineCache == nullptr && + assert(!RHS.Buffer && !RHS.SourceLineCache && "Passed ContentCache object cannot own a buffer."); - - NumLines = RHS.NumLines; } ContentCache &operator=(const ContentCache& RHS) = delete; Index: clang/lib/Basic/SourceManager.cpp =================================================================== --- clang/lib/Basic/SourceManager.cpp +++ clang/lib/Basic/SourceManager.cpp @@ -1198,10 +1198,11 @@ const char *Buf = MemBuf->getBufferStart(); // See if we just calculated the line number for this FilePos and can use // that to lookup the start of the line instead of searching for it. - if (LastLineNoFileIDQuery == FID && - LastLineNoContentCache->SourceLineCache != nullptr && - LastLineNoResult < LastLineNoContentCache->NumLines) { - unsigned *SourceLineCache = LastLineNoContentCache->SourceLineCache; + if (LastLineNoFileIDQuery == FID && LastLineNoContentCache->SourceLineCache && + LastLineNoResult < + LastLineNoContentCache->SourceLineCache.getNumLines()) { + const unsigned *SourceLineCache = + LastLineNoContentCache->SourceLineCache.begin(); unsigned LineStart = SourceLineCache[LastLineNoResult - 1]; unsigned LineEnd = SourceLineCache[LastLineNoResult]; if (FilePos >= LineStart && FilePos < LineEnd) { @@ -1272,6 +1273,11 @@ if (Invalid) return; + FI->SourceLineCache = LineOffsetMapping::get(*Buffer, Alloc); +} + +LineOffsetMapping LineOffsetMapping::get(llvm::MemoryBufferRef Buffer, + llvm::BumpPtrAllocator &Alloc) { // Find the file offsets of all of the *physical* source lines. This does // not look at trigraphs, escaped newlines, or anything else tricky. SmallVector LineOffsets; @@ -1279,8 +1285,8 @@ // Line #1 starts at char 0. LineOffsets.push_back(0); - const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart(); - const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd(); + const unsigned char *Buf = (const unsigned char *)Buffer.getBufferStart(); + const unsigned char *End = (const unsigned char *)Buffer.getBufferEnd(); const std::size_t BufLen = End - Buf; unsigned I = 0; while (I < BufLen) { @@ -1295,10 +1301,14 @@ ++I; } - // Copy the offsets into the FileInfo structure. - FI->NumLines = LineOffsets.size(); - FI->SourceLineCache = Alloc.Allocate(LineOffsets.size()); - std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache); + return LineOffsetMapping(LineOffsets, Alloc); +} + +LineOffsetMapping::LineOffsetMapping(ArrayRef LineOffsets, + llvm::BumpPtrAllocator & Alloc) + : Storage(Alloc.Allocate(LineOffsets.size())) { + Storage[0] = LineOffsets.size(); + std::copy(LineOffsets.begin(), LineOffsets.end(), Storage + 1); } /// getLineNumber - Given a SourceLocation, return the spelling line number @@ -1342,9 +1352,9 @@ // Okay, we know we have a line number table. Do a binary search to find the // line number that this character position lands on. - unsigned *SourceLineCache = Content->SourceLineCache; - unsigned *SourceLineCacheStart = SourceLineCache; - unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines; + const unsigned *SourceLineCache = Content->SourceLineCache.begin(); + const unsigned *SourceLineCacheStart = SourceLineCache; + const unsigned *SourceLineCacheEnd = Content->SourceLineCache.end(); unsigned QueriedFilePos = FilePos+1; @@ -1383,12 +1393,12 @@ } } } else { - if (LastLineNoResult < Content->NumLines) + if (LastLineNoResult < Content->SourceLineCache.getNumLines()) SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1; } } - unsigned *Pos + const unsigned *Pos = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos); unsigned LineNo = Pos-SourceLineCacheStart; @@ -1695,7 +1705,7 @@ if (!Buffer) return SourceLocation(); - if (Line > Content->NumLines) { + if (Line > Content->SourceLineCache.getNumLines()) { unsigned Size = Buffer->getBufferSize(); if (Size > 0) --Size; @@ -2102,7 +2112,7 @@ unsigned NumLineNumsComputed = 0; unsigned NumFileBytesMapped = 0; for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){ - NumLineNumsComputed += I->second->SourceLineCache != nullptr; + NumLineNumsComputed += bool(I->second->SourceLineCache); NumFileBytesMapped += I->second->getSizeBytesMapped(); } unsigned NumMacroArgsComputed = MacroArgsCacheMap.size(); Index: clang/lib/Lex/ScratchBuffer.cpp =================================================================== --- clang/lib/Lex/ScratchBuffer.cpp +++ clang/lib/Lex/ScratchBuffer.cpp @@ -40,7 +40,7 @@ auto *ContentCache = const_cast( SourceMgr.getSLocEntry(SourceMgr.getFileID(BufferStartLoc)) .getFile().getContentCache()); - ContentCache->SourceLineCache = nullptr; + ContentCache->SourceLineCache = SrcMgr::LineOffsetMapping(); } // Prefix the token with a \n, so that it looks like it is the first thing on