[clang] c23ee77 - [www] List both the regular and expanded form of %diff in the
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 30 17:25:29 PDT 2021
Author: Richard Smith
Date: 2021-03-30T17:25:01-07:00
New Revision: c23ee7718ea4f9292622af3d80efe2491eb2a506
URL: https://github.com/llvm/llvm-project/commit/c23ee7718ea4f9292622af3d80efe2491eb2a506
DIFF: https://github.com/llvm/llvm-project/commit/c23ee7718ea4f9292622af3d80efe2491eb2a506.diff
LOG: [www] List both the regular and expanded form of %diff in the
diagnostics reference.
In passing, properly validate and diagnose errors in %diff format
specifiers.
Added:
Modified:
clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
Removed:
################################################################################
diff --git a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
index 77c4786723247..014c1adcd8092 100644
--- a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
@@ -557,7 +557,7 @@ struct PluralPiece : SelectPiece {
struct DiffPiece : Piece {
DiffPiece() : Piece(DiffPieceClass) {}
- Piece *Options[2] = {};
+ Piece *Parts[4] = {};
int Indexes[2] = {};
static bool classof(const Piece *P) {
@@ -633,9 +633,18 @@ struct DiagnosticTextBuilder {
}
DiagText(DiagnosticTextBuilder &Builder, StringRef Text)
- : Builder(Builder), Root(parseDiagText(Text)) {}
-
- Piece *parseDiagText(StringRef &Text, bool Nested = false);
+ : Builder(Builder), Root(parseDiagText(Text, StopAt::End)) {}
+
+ enum class StopAt {
+ // Parse until the end of the string.
+ End,
+ // Additionally stop if we hit a non-nested '|' or '}'.
+ PipeOrCloseBrace,
+ // Additionally stop if we hit a non-nested '$'.
+ Dollar,
+ };
+
+ Piece *parseDiagText(StringRef &Text, StopAt Stop);
int parseModifier(StringRef &) const;
public:
@@ -901,7 +910,24 @@ struct DiagTextDocPrinter : DiagTextVisitor<DiagTextDocPrinter> {
void VisitPlural(PluralPiece *P) { VisitSelect(P); }
- void VisitDiff(DiffPiece *P) { Visit(P->Options[1]); }
+ void VisitDiff(DiffPiece *P) {
+ // Render %
diff {a $ b $ c|d}e,f as %select{a %e b %f c|d}.
+ PlaceholderPiece E(MT_Placeholder, P->Indexes[0]);
+ PlaceholderPiece F(MT_Placeholder, P->Indexes[1]);
+
+ MultiPiece FirstOption;
+ FirstOption.Pieces.push_back(P->Parts[0]);
+ FirstOption.Pieces.push_back(&E);
+ FirstOption.Pieces.push_back(P->Parts[1]);
+ FirstOption.Pieces.push_back(&F);
+ FirstOption.Pieces.push_back(P->Parts[2]);
+
+ SelectPiece Select(MT_Diff);
+ Select.Options.push_back(&FirstOption);
+ Select.Options.push_back(P->Parts[3]);
+
+ VisitSelect(&Select);
+ }
std::vector<std::string> &RST;
};
@@ -955,9 +981,13 @@ struct DiagTextPrinter : DiagTextVisitor<DiagTextPrinter> {
void VisitDiff(DiffPiece *P) {
Result += "%
diff {";
- Visit(P->Options[0]);
+ Visit(P->Parts[0]);
+ Result += "$";
+ Visit(P->Parts[1]);
+ Result += "$";
+ Visit(P->Parts[2]);
Result += "|";
- Visit(P->Options[1]);
+ Visit(P->Parts[3]);
Result += "}";
addInt(mapIndex(P->Indexes[0]));
Result += ",";
@@ -982,16 +1012,19 @@ int DiagnosticTextBuilder::DiagText::parseModifier(StringRef &Text) const {
}
Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text,
- bool Nested) {
+ StopAt Stop) {
std::vector<Piece *> Parsed;
+ constexpr llvm::StringLiteral StopSets[] = {"%", "%|}", "%|}$"};
+ llvm::StringRef StopSet = StopSets[static_cast<int>(Stop)];
+
while (!Text.empty()) {
size_t End = (size_t)-2;
do
- End = Nested ? Text.find_first_of("%|}", End + 2)
- : Text.find_first_of('%', End + 2);
- while (End < Text.size() - 1 && Text[End] == '%' &&
- (Text[End + 1] == '%' || Text[End + 1] == '|'));
+ End = Text.find_first_of(StopSet, End + 2);
+ while (
+ End < Text.size() - 1 && Text[End] == '%' &&
+ (Text[End + 1] == '%' || Text[End + 1] == '|' || Text[End + 1] == '$'));
if (End) {
Parsed.push_back(New<TextPiece>(Text.slice(0, End), "diagtext"));
@@ -1000,7 +1033,7 @@ Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text,
break;
}
- if (Text[0] == '|' || Text[0] == '}')
+ if (Text[0] == '|' || Text[0] == '}' || Text[0] == '$')
break;
// Drop the '%'.
@@ -1023,6 +1056,12 @@ Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text,
.Case("", MT_Placeholder)
.Default(MT_Unknown);
+ auto ExpectAndConsume = [&](StringRef Prefix) {
+ if (!Text.consume_front(Prefix))
+ Builder.PrintFatalError("expected '" + Prefix + "' while parsing %" +
+ Modifier);
+ };
+
switch (ModType) {
case MT_Unknown:
Builder.PrintFatalError("Unknown modifier type: " + Modifier);
@@ -1030,11 +1069,11 @@ Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text,
SelectPiece *Select = New<SelectPiece>(MT_Select);
do {
Text = Text.drop_front(); // '{' or '|'
- Select->Options.push_back(parseDiagText(Text, true));
+ Select->Options.push_back(
+ parseDiagText(Text, StopAt::PipeOrCloseBrace));
assert(!Text.empty() && "malformed %select");
} while (Text.front() == '|');
- // Drop the trailing '}'.
- Text = Text.drop_front(1);
+ ExpectAndConsume("}");
Select->Index = parseModifier(Text);
Parsed.push_back(Select);
continue;
@@ -1051,24 +1090,24 @@ Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text,
Plural->OptionPrefixes.push_back(
New<TextPiece>(Text.slice(0, End), "diagtext"));
Text = Text.slice(End, StringRef::npos);
- Plural->Options.push_back(parseDiagText(Text, true));
- assert(!Text.empty() && "malformed %select");
+ Plural->Options.push_back(
+ parseDiagText(Text, StopAt::PipeOrCloseBrace));
+ assert(!Text.empty() && "malformed %plural");
} while (Text.front() == '|');
- // Drop the trailing '}'.
- Text = Text.drop_front(1);
+ ExpectAndConsume("}");
Plural->Index = parseModifier(Text);
Parsed.push_back(Plural);
continue;
}
case MT_Sub: {
SubstitutionPiece *Sub = New<SubstitutionPiece>();
- Text = Text.drop_front(); // '{'
+ ExpectAndConsume("{");
size_t NameSize = Text.find_first_of('}');
assert(NameSize != size_t(-1) && "failed to find the end of the name");
assert(NameSize != 0 && "empty name?");
Sub->Name = Text.substr(0, NameSize).str();
Text = Text.drop_front(NameSize);
- Text = Text.drop_front(); // '}'
+ ExpectAndConsume("}");
if (!Text.empty()) {
while (true) {
if (!isdigit(Text[0]))
@@ -1086,14 +1125,17 @@ Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text,
}
case MT_Diff: {
DiffPiece *Diff = New<DiffPiece>();
- Text = Text.drop_front(); // '{'
- Diff->Options[0] = parseDiagText(Text, true);
- Text = Text.drop_front(); // '|'
- Diff->Options[1] = parseDiagText(Text, true);
-
- Text = Text.drop_front(); // '}'
+ ExpectAndConsume("{");
+ Diff->Parts[0] = parseDiagText(Text, StopAt::Dollar);
+ ExpectAndConsume("$");
+ Diff->Parts[1] = parseDiagText(Text, StopAt::Dollar);
+ ExpectAndConsume("$");
+ Diff->Parts[2] = parseDiagText(Text, StopAt::PipeOrCloseBrace);
+ ExpectAndConsume("|");
+ Diff->Parts[3] = parseDiagText(Text, StopAt::PipeOrCloseBrace);
+ ExpectAndConsume("}");
Diff->Indexes[0] = parseModifier(Text);
- Text = Text.drop_front(); // ','
+ ExpectAndConsume(",");
Diff->Indexes[1] = parseModifier(Text);
Parsed.push_back(Diff);
continue;
More information about the cfe-commits
mailing list