Skip to content

[Clang] [NFC] Add "human" diagnostic argument format #115835

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions clang/docs/InternalsManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,17 @@ Description:
than ``1`` are not supported. This formatter is currently hard-coded to use
English ordinals.

**"human" format**

Example:
``"total size is %human0 bytes"``
Class:
Integers
Description:
This is a formatter which represents the argument number in a human readable
format: the value ``123`` stays ``123``, ``12345`` becomes ``12.34k``,
``6666666` becomes ``6.67M``, and so on for 'G' and 'T'.

**"objcclass" format**

Example:
Expand Down
12 changes: 6 additions & 6 deletions clang/include/clang/Basic/DiagnosticCommonKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -389,14 +389,14 @@ def remark_sloc_usage : Remark<
"source manager location address space usage:">,
InGroup<DiagGroup<"sloc-usage">>, DefaultRemark, ShowInSystemHeader;
def note_total_sloc_usage : Note<
"%0B (%1B) in local locations, %2B (%3B) "
"in locations loaded from AST files, for a total of %4B (%5B) "
"(%6%% of available space)">;
"%0B (%human0B) in local locations, %1B (%human1B) "
"in locations loaded from AST files, for a total of %2B (%human2B) "
"(%3%% of available space)">;
def note_file_sloc_usage : Note<
"file entered %0 time%s0 using %1B (%2B) of space"
"%plural{0:|: plus %3B (%4B) for macro expansions}3">;
"file entered %0 time%s0 using %1B (%human1B) of space"
"%plural{0:|: plus %2B (%human2B) for macro expansions}2">;
def note_file_misc_sloc_usage : Note<
"%0 additional files entered using a total of %1B (%2B) of space">;
"%0 additional files entered using a total of %1B (%human1B) of space">;

// Modules
def err_module_format_unhandled : Error<
Expand Down
33 changes: 33 additions & 0 deletions clang/lib/Basic/Diagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,35 @@ static void HandleOrdinalModifier(unsigned ValNo,
Out << ValNo << llvm::getOrdinalSuffix(ValNo);
}

// 123 -> "123".
// 1234 -> "1.23k".
// 123456 -> "123.46k".
// 1234567 -> "1.23M".
// 1234567890 -> "1.23G".
// 1234567890123 -> "1.23T".
static void HandleIntegerHumanModifier(int64_t ValNo,
SmallVectorImpl<char> &OutStr) {
static constexpr std::array<std::pair<int64_t, char>, 4> Units = {
{{1'000'000'000'000L, 'T'},
{1'000'000'000L, 'G'},
{1'000'000L, 'M'},
{1'000L, 'k'}}};

llvm::raw_svector_ostream Out(OutStr);
if (ValNo < 0) {
Out << "-";
ValNo = -ValNo;
}
for (const auto &[UnitSize, UnitSign] : Units) {
if (ValNo >= UnitSize) {
Out << llvm::format("%0.2f%c", ValNo / static_cast<double>(UnitSize),
UnitSign);
return;
}
}
Out << ValNo;
}

/// PluralNumber - Parse an unsigned integer and advance Start.
static unsigned PluralNumber(const char *&Start, const char *End) {
// Programming 101: Parse a decimal number :-)
Expand Down Expand Up @@ -988,6 +1017,8 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
OutStr);
} else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
HandleOrdinalModifier((unsigned)Val, OutStr);
} else if (ModifierIs(Modifier, ModifierLen, "human")) {
HandleIntegerHumanModifier(Val, OutStr);
} else {
assert(ModifierLen == 0 && "Unknown integer modifier");
llvm::raw_svector_ostream(OutStr) << Val;
Expand All @@ -1006,6 +1037,8 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
OutStr);
} else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
HandleOrdinalModifier(Val, OutStr);
} else if (ModifierIs(Modifier, ModifierLen, "human")) {
HandleIntegerHumanModifier(Val, OutStr);
} else {
assert(ModifierLen == 0 && "Unknown integer modifier");
llvm::raw_svector_ostream(OutStr) << Val;
Expand Down
35 changes: 4 additions & 31 deletions clang/lib/Basic/SourceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
Expand Down Expand Up @@ -2228,28 +2227,6 @@ LLVM_DUMP_METHOD void SourceManager::dump() const {
}
}

// 123 -> "123".
// 1234 -> "1.23k".
// 123456 -> "123.46k".
// 1234567 -> "1.23M".
// 1234567890 -> "1.23G".
// 1234567890123 -> "1.23T".
static std::string humanizeNumber(uint64_t Number) {
static constexpr std::array<std::pair<uint64_t, char>, 4> Units = {
{{1'000'000'000'000UL, 'T'},
{1'000'000'000UL, 'G'},
{1'000'000UL, 'M'},
{1'000UL, 'k'}}};

for (const auto &[UnitSize, UnitSign] : Units) {
if (Number >= UnitSize) {
return llvm::formatv("{0:F}{1}", Number / static_cast<double>(UnitSize),
UnitSign);
}
}
return std::to_string(Number);
}

void SourceManager::noteSLocAddressSpaceUsage(
DiagnosticsEngine &Diag, std::optional<unsigned> MaxNotes) const {
struct Info {
Expand Down Expand Up @@ -2319,27 +2296,23 @@ void SourceManager::noteSLocAddressSpaceUsage(
int UsagePercent = static_cast<int>(100.0 * double(LocalUsage + LoadedUsage) /
MaxLoadedOffset);
Diag.Report(SourceLocation(), diag::note_total_sloc_usage)
<< LocalUsage << humanizeNumber(LocalUsage) << LoadedUsage
<< humanizeNumber(LoadedUsage) << (LocalUsage + LoadedUsage)
<< humanizeNumber(LocalUsage + LoadedUsage) << UsagePercent;
<< 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
<< humanizeNumber(FileInfo.DirectSize)
<< (FileInfo.TotalSize - FileInfo.DirectSize)
<< humanizeNumber(FileInfo.TotalSize - 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
<< humanizeNumber(CountedSize - ReportedSize);
<< (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize;
}
}

Expand Down
7 changes: 6 additions & 1 deletion clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ enum ModifierType {
MT_Plural,
MT_Diff,
MT_Ordinal,
MT_Human,
MT_S,
MT_Q,
MT_ObjCClass,
Expand All @@ -458,6 +459,8 @@ static StringRef getModifierName(ModifierType MT) {
return "plural";
case MT_Ordinal:
return "ordinal";
case MT_Human:
return "human";
case MT_S:
return "s";
case MT_Q:
Expand Down Expand Up @@ -1053,6 +1056,7 @@ Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text,
.Case("plural", MT_Plural)
.Case("s", MT_S)
.Case("ordinal", MT_Ordinal)
.Case("human", MT_Human)
.Case("q", MT_Q)
.Case("objcclass", MT_ObjCClass)
.Case("objcinstance", MT_ObjCInstance)
Expand Down Expand Up @@ -1154,7 +1158,8 @@ Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text,
case MT_Placeholder:
case MT_ObjCClass:
case MT_ObjCInstance:
case MT_Ordinal: {
case MT_Ordinal:
case MT_Human: {
Parsed.push_back(New<PlaceholderPiece>(ModType, parseModifier(Text)));
continue;
}
Expand Down
Loading