diff options
author | Richard Smith <richard@metafoo.co.uk> | 2022-11-09 15:45:54 -0800 |
---|---|---|
committer | Richard Smith <richard@metafoo.co.uk> | 2022-11-16 14:36:16 -0800 |
commit | 9e52db182794d87bb8527dda313afd1ac491ab11 (patch) | |
tree | a740353e0359b726ed4e51e61f362322823bb2ff /clang/lib/Basic/SourceManager.cpp | |
parent | bcc9c5d959b9cdfbb535ea298805c4993cf0bb64 (diff) | |
download | llvm-9e52db182794d87bb8527dda313afd1ac491ab11.zip llvm-9e52db182794d87bb8527dda313afd1ac491ab11.tar.gz llvm-9e52db182794d87bb8527dda313afd1ac491ab11.tar.bz2 |
When we run out of source locations, try to produce useful information
indicating why we ran out.
Diffstat (limited to 'clang/lib/Basic/SourceManager.cpp')
-rw-r--r-- | clang/lib/Basic/SourceManager.cpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index caa5573..ecb771a 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -17,6 +17,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManagerInternals.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" @@ -615,6 +616,7 @@ FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename, if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset && NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) { Diag.Report(IncludePos, diag::err_include_too_large); + noteSLocAddressSpaceUsage(Diag); return FileID(); } LocalSLocEntryTable.push_back( @@ -671,6 +673,7 @@ SourceManager::createExpansionLocImpl(const ExpansionInfo &Info, return SourceLocation::getMacroLoc(LoadedOffset); } LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info)); + // FIXME: Produce a proper diagnostic for this case. assert(NextLocalOffset + Length + 1 > NextLocalOffset && NextLocalOffset + Length + 1 <= CurrentLoadedOffset && "Ran out of source locations!"); @@ -2230,6 +2233,94 @@ LLVM_DUMP_METHOD void SourceManager::dump() const { } } +void SourceManager::noteSLocAddressSpaceUsage( + DiagnosticsEngine &Diag, Optional<unsigned> MaxNotes) const { + struct Info { + // A location where this file was entered. + SourceLocation Loc; + // Number of times this FileEntry was entered. + unsigned Inclusions = 0; + // Size usage from the file itself. + uint64_t DirectSize = 0; + // Total size usage from the file and its macro expansions. + uint64_t TotalSize = 0; + }; + using UsageMap = llvm::MapVector<const FileEntry*, Info>; + + UsageMap Usage; + uint64_t CountedSize = 0; + + auto AddUsageForFileID = [&](FileID ID) { + // The +1 here is because getFileIDSize doesn't include the extra byte for + // the one-past-the-end location. + unsigned Size = getFileIDSize(ID) + 1; + + // Find the file that used this address space, either directly or by + // macro expansion. + SourceLocation FileStart = getFileLoc(getComposedLoc(ID, 0)); + FileID FileLocID = getFileID(FileStart); + const FileEntry *Entry = getFileEntryForID(FileLocID); + + Info &EntryInfo = Usage[Entry]; + if (EntryInfo.Loc.isInvalid()) + EntryInfo.Loc = FileStart; + if (ID == FileLocID) { + ++EntryInfo.Inclusions; + EntryInfo.DirectSize += Size; + } + EntryInfo.TotalSize += Size; + CountedSize += Size; + }; + + // Loaded SLocEntries have indexes counting downwards from -2. + for (size_t Index = 0; Index != LoadedSLocEntryTable.size(); ++Index) { + AddUsageForFileID(FileID::get(-2 - Index)); + } + // Local SLocEntries have indexes counting upwards from 0. + for (size_t Index = 0; Index != LocalSLocEntryTable.size(); ++Index) { + AddUsageForFileID(FileID::get(Index)); + } + + // Sort the usage by size from largest to smallest. Break ties by raw source + // location. + auto SortedUsage = Usage.takeVector(); + auto Cmp = [](const UsageMap::value_type &A, const UsageMap::value_type &B) { + return A.second.TotalSize > B.second.TotalSize || + (A.second.TotalSize == B.second.TotalSize && + A.second.Loc < B.second.Loc); + }; + auto SortedEnd = SortedUsage.end(); + if (MaxNotes && SortedUsage.size() > *MaxNotes) { + SortedEnd = SortedUsage.begin() + *MaxNotes; + std::nth_element(SortedUsage.begin(), SortedEnd, SortedUsage.end(), Cmp); + } + std::sort(SortedUsage.begin(), SortedEnd, Cmp); + + // Produce note on sloc address space usage total. + uint64_t LocalUsage = NextLocalOffset; + uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset; + int UsagePercent = static_cast<int>(100.0 * double(LocalUsage + LoadedUsage) / + MaxLoadedOffset); + Diag.Report(SourceLocation(), diag::note_total_sloc_usage) + << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage) << UsagePercent; + + // Produce notes on sloc address space usage for each file with a high usage. + uint64_t ReportedSize = 0; + for (auto &[Entry, FileInfo] : + llvm::make_range(SortedUsage.begin(), SortedEnd)) { + Diag.Report(FileInfo.Loc, diag::note_file_sloc_usage) + << FileInfo.Inclusions << FileInfo.DirectSize + << (FileInfo.TotalSize - FileInfo.DirectSize); + ReportedSize += FileInfo.TotalSize; + } + + // Describe any remaining usage not reported in the per-file usage. + if (ReportedSize != CountedSize) { + Diag.Report(SourceLocation(), diag::note_file_misc_sloc_usage) + << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize; + } +} + ExternalSLocEntrySource::~ExternalSLocEntrySource() = default; /// Return the amount of memory used by memory buffers, breaking down |