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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits