diff options
| author | 2019-01-27 16:42:12 +0000 | |
|---|---|---|
| committer | 2019-01-27 16:42:12 +0000 | |
| commit | b773203fb58f3ef282fb69c832d8710cab5bc82d (patch) | |
| tree | e75913f147570fbd75169647b144df85b88a038c /gnu/llvm/lib/Support/SourceMgr.cpp | |
| parent | tweak errno in previous (diff) | |
| download | wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.tar.xz wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.zip | |
Import LLVM 7.0.1 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/lib/Support/SourceMgr.cpp')
| -rw-r--r-- | gnu/llvm/lib/Support/SourceMgr.cpp | 152 |
1 files changed, 87 insertions, 65 deletions
diff --git a/gnu/llvm/lib/Support/SourceMgr.cpp b/gnu/llvm/lib/Support/SourceMgr.cpp index a8f6208a558..d8fde7fa899 100644 --- a/gnu/llvm/lib/Support/SourceMgr.cpp +++ b/gnu/llvm/lib/Support/SourceMgr.cpp @@ -28,6 +28,7 @@ #include <algorithm> #include <cassert> #include <cstddef> +#include <limits> #include <memory> #include <string> #include <utility> @@ -36,24 +37,6 @@ using namespace llvm; static const size_t TabStop = 8; -namespace { - - struct LineNoCacheTy { - const char *LastQuery; - unsigned LastQueryBufferID; - unsigned LineNoOfQuery; - }; - -} // end anonymous namespace - -static LineNoCacheTy *getCache(void *Ptr) { - return (LineNoCacheTy*)Ptr; -} - -SourceMgr::~SourceMgr() { - delete getCache(LineNoCache); -} - unsigned SourceMgr::AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, std::string &IncludedFile) { @@ -85,46 +68,85 @@ unsigned SourceMgr::FindBufferContainingLoc(SMLoc Loc) const { return 0; } +template <typename T> +unsigned SourceMgr::SrcBuffer::getLineNumber(const char *Ptr) const { + + // Ensure OffsetCache is allocated and populated with offsets of all the + // '\n' bytes. + std::vector<T> *Offsets = nullptr; + if (OffsetCache.isNull()) { + Offsets = new std::vector<T>(); + OffsetCache = Offsets; + size_t Sz = Buffer->getBufferSize(); + assert(Sz <= std::numeric_limits<T>::max()); + StringRef S = Buffer->getBuffer(); + for (size_t N = 0; N < Sz; ++N) { + if (S[N] == '\n') { + Offsets->push_back(static_cast<T>(N)); + } + } + } else { + Offsets = OffsetCache.get<std::vector<T> *>(); + } + + const char *BufStart = Buffer->getBufferStart(); + assert(Ptr >= BufStart && Ptr <= Buffer->getBufferEnd()); + ptrdiff_t PtrDiff = Ptr - BufStart; + assert(PtrDiff >= 0 && static_cast<size_t>(PtrDiff) <= std::numeric_limits<T>::max()); + T PtrOffset = static_cast<T>(PtrDiff); + + // std::lower_bound returns the first EOL offset that's not-less-than + // PtrOffset, meaning the EOL that _ends the line_ that PtrOffset is on + // (including if PtrOffset refers to the EOL itself). If there's no such + // EOL, returns end(). + auto EOL = std::lower_bound(Offsets->begin(), Offsets->end(), PtrOffset); + + // Lines count from 1, so add 1 to the distance from the 0th line. + return (1 + (EOL - Offsets->begin())); +} + +SourceMgr::SrcBuffer::SrcBuffer(SourceMgr::SrcBuffer &&Other) + : Buffer(std::move(Other.Buffer)), + OffsetCache(Other.OffsetCache), + IncludeLoc(Other.IncludeLoc) { + Other.OffsetCache = nullptr; +} + +SourceMgr::SrcBuffer::~SrcBuffer() { + if (!OffsetCache.isNull()) { + if (OffsetCache.is<std::vector<uint8_t>*>()) + delete OffsetCache.get<std::vector<uint8_t>*>(); + else if (OffsetCache.is<std::vector<uint16_t>*>()) + delete OffsetCache.get<std::vector<uint16_t>*>(); + else if (OffsetCache.is<std::vector<uint32_t>*>()) + delete OffsetCache.get<std::vector<uint32_t>*>(); + else + delete OffsetCache.get<std::vector<uint64_t>*>(); + OffsetCache = nullptr; + } +} + std::pair<unsigned, unsigned> SourceMgr::getLineAndColumn(SMLoc Loc, unsigned BufferID) const { if (!BufferID) BufferID = FindBufferContainingLoc(Loc); assert(BufferID && "Invalid Location!"); - const MemoryBuffer *Buff = getMemoryBuffer(BufferID); - - // Count the number of \n's between the start of the file and the specified - // location. - unsigned LineNo = 1; - - const char *BufStart = Buff->getBufferStart(); - const char *Ptr = BufStart; - - // If we have a line number cache, and if the query is to a later point in the - // same file, start searching from the last query location. This optimizes - // for the case when multiple diagnostics come out of one file in order. - if (LineNoCacheTy *Cache = getCache(LineNoCache)) - if (Cache->LastQueryBufferID == BufferID && - Cache->LastQuery <= Loc.getPointer()) { - Ptr = Cache->LastQuery; - LineNo = Cache->LineNoOfQuery; - } - - // Scan for the location being queried, keeping track of the number of lines - // we see. - for (; SMLoc::getFromPointer(Ptr) != Loc; ++Ptr) - if (*Ptr == '\n') ++LineNo; - - // Allocate the line number cache if it doesn't exist. - if (!LineNoCache) - LineNoCache = new LineNoCacheTy(); - - // Update the line # cache. - LineNoCacheTy &Cache = *getCache(LineNoCache); - Cache.LastQueryBufferID = BufferID; - Cache.LastQuery = Ptr; - Cache.LineNoOfQuery = LineNo; - + auto &SB = getBufferInfo(BufferID); + const char *Ptr = Loc.getPointer(); + + size_t Sz = SB.Buffer->getBufferSize(); + unsigned LineNo; + if (Sz <= std::numeric_limits<uint8_t>::max()) + LineNo = SB.getLineNumber<uint8_t>(Ptr); + else if (Sz <= std::numeric_limits<uint16_t>::max()) + LineNo = SB.getLineNumber<uint16_t>(Ptr); + else if (Sz <= std::numeric_limits<uint32_t>::max()) + LineNo = SB.getLineNumber<uint32_t>(Ptr); + else + LineNo = SB.getLineNumber<uint64_t>(Ptr); + + const char *BufStart = SB.Buffer->getBufferStart(); size_t NewlineOffs = StringRef(BufStart, Ptr-BufStart).find_last_of("\n\r"); if (NewlineOffs == StringRef::npos) NewlineOffs = ~(size_t)0; return std::make_pair(LineNo, Ptr-BufStart-NewlineOffs); @@ -153,14 +175,14 @@ SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind, std::pair<unsigned, unsigned> LineAndCol; StringRef BufferID = "<unknown>"; std::string LineStr; - + if (Loc.isValid()) { unsigned CurBuf = FindBufferContainingLoc(Loc); assert(CurBuf && "Invalid or unspecified location!"); const MemoryBuffer *CurMB = getMemoryBuffer(CurBuf); BufferID = CurMB->getBufferIdentifier(); - + // Scan backward to find the start of the line. const char *LineStart = Loc.getPointer(); const char *BufStart = CurMB->getBufferStart(); @@ -180,17 +202,17 @@ SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind, for (unsigned i = 0, e = Ranges.size(); i != e; ++i) { SMRange R = Ranges[i]; if (!R.isValid()) continue; - + // If the line doesn't contain any part of the range, then ignore it. if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart) continue; - + // Ignore pieces of the range that go onto other lines. if (R.Start.getPointer() < LineStart) R.Start = SMLoc::getFromPointer(LineStart); if (R.End.getPointer() > LineEnd) R.End = SMLoc::getFromPointer(LineEnd); - + // Translate from SMLoc ranges to column ranges. // FIXME: Handle multibyte characters. ColRanges.push_back(std::make_pair(R.Start.getPointer()-LineStart, @@ -199,7 +221,7 @@ SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind, LineAndCol = getLineAndColumn(Loc, CurBuf); } - + return SMDiagnostic(*this, Loc, BufferID, LineAndCol.first, LineAndCol.second-1, Kind, Msg.str(), LineStr, ColRanges, FixIts); @@ -247,7 +269,7 @@ SMDiagnostic::SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN, : SM(&sm), Loc(L), Filename(FN), LineNo(Line), ColumnNo(Col), Kind(Kind), Message(Msg), LineContents(LineStr), Ranges(Ranges.vec()), FixIts(Hints.begin(), Hints.end()) { - std::sort(FixIts.begin(), FixIts.end()); + llvm::sort(FixIts.begin(), FixIts.end()); } static void buildFixItLine(std::string &CaretLine, std::string &FixItLine, @@ -418,7 +440,7 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S, bool ShowColors, // Build the line with the caret and ranges. std::string CaretLine(NumColumns+1, ' '); - + // Expand any ranges. for (unsigned r = 0, e = Ranges.size(); r != e; ++r) { std::pair<unsigned, unsigned> R = Ranges[r]; @@ -437,14 +459,14 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S, bool ShowColors, // Finally, plop on the caret. if (unsigned(ColumnNo) <= NumColumns) CaretLine[ColumnNo] = '^'; - else + else CaretLine[NumColumns] = '^'; - + // ... and remove trailing whitespace so the output doesn't wrap for it. We // know that the line isn't completely empty because it has the caret in it at // least. CaretLine.erase(CaretLine.find_last_not_of(' ')+1); - + printSourceLine(S, LineContents); if (ShowColors) @@ -457,7 +479,7 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S, bool ShowColors, ++OutCol; continue; } - + // Okay, we have a tab. Insert the appropriate number of characters. do { S << CaretLine[i]; @@ -472,7 +494,7 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S, bool ShowColors, // Print out the replacement line, matching tabs in the source line. if (FixItInsertionLine.empty()) return; - + for (size_t i = 0, e = FixItInsertionLine.size(), OutCol = 0; i < e; ++i) { if (i >= LineContents.size() || LineContents[i] != '\t') { S << FixItInsertionLine[i]; |
