summaryrefslogtreecommitdiffstats
path: root/llvm/utils/FileCheck/FileCheck.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/FileCheck/FileCheck.cpp')
-rw-r--r--llvm/utils/FileCheck/FileCheck.cpp51
1 files changed, 43 insertions, 8 deletions
diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp
index 33449147fcc..c6846f7da71 100644
--- a/llvm/utils/FileCheck/FileCheck.cpp
+++ b/llvm/utils/FileCheck/FileCheck.cpp
@@ -145,6 +145,8 @@ static MarkerStyle GetMarker(FileCheckDiag::MatchType MatchTy) {
switch (MatchTy) {
case FileCheckDiag::MatchNoneButExpected:
return MarkerStyle('X', raw_ostream::RED, "error: no match found");
+ case FileCheckDiag::MatchFuzzy:
+ return MarkerStyle('?', raw_ostream::MAGENTA, "possible intended match");
case FileCheckDiag::MatchTypeCount:
llvm_unreachable_internal("unexpected match type");
}
@@ -164,18 +166,28 @@ static void DumpInputAnnotationHelp(raw_ostream &OS) {
// Labels for annotation lines.
OS << " - ";
WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "T:L";
- OS << " labels the match result for a pattern of type T from "
+ OS << " labels the only match result for a pattern of type T from "
<< "line L of\n"
<< " the check file\n";
+ OS << " - ";
+ WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "T:L'N";
+ OS << " labels the Nth match result for a pattern of type T from line "
+ << "L of\n"
+ << " the check file\n";
// Markers on annotation lines.
OS << " - ";
WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "X~~";
- OS << " marks search range when no match is found\n";
+ OS << " marks search range when no match is found\n"
+ << " - ";
+ WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "?";
+ OS << " marks fuzzy match when no match is found\n";
// Colors.
OS << " - colors ";
WithColor(OS, raw_ostream::RED, true) << "error";
+ OS << ", ";
+ WithColor(OS, raw_ostream::MAGENTA, true) << "fuzzy match";
OS << "\n\n"
<< "If you are not seeing color above or in input dumps, try: -color\n";
}
@@ -185,6 +197,8 @@ struct InputAnnotation {
/// The check file line (one-origin indexing) where the directive that
/// produced this annotation is located.
unsigned CheckLine;
+ /// The index of the match result for this check.
+ unsigned CheckDiagIndex;
/// The label for this annotation.
std::string Label;
/// What input line (one-origin indexing) this annotation marks. This might
@@ -234,6 +248,8 @@ std::string GetCheckTypeAbbreviation(Check::FileCheckType Ty) {
static void BuildInputAnnotations(const std::vector<FileCheckDiag> &Diags,
std::vector<InputAnnotation> &Annotations,
unsigned &LabelWidth) {
+ // How many diagnostics has the current check seen so far?
+ unsigned CheckDiagCount = 0;
// What's the widest label?
LabelWidth = 0;
for (auto DiagItr = Diags.begin(), DiagEnd = Diags.end(); DiagItr != DiagEnd;
@@ -245,6 +261,19 @@ static void BuildInputAnnotations(const std::vector<FileCheckDiag> &Diags,
llvm::raw_string_ostream Label(A.Label);
Label << GetCheckTypeAbbreviation(DiagItr->CheckTy) << ":"
<< DiagItr->CheckLine;
+ A.CheckDiagIndex = UINT_MAX;
+ auto DiagNext = std::next(DiagItr);
+ if (DiagNext != DiagEnd && DiagItr->CheckTy == DiagNext->CheckTy &&
+ DiagItr->CheckLine == DiagNext->CheckLine)
+ A.CheckDiagIndex = CheckDiagCount++;
+ else if (CheckDiagCount) {
+ A.CheckDiagIndex = CheckDiagCount;
+ CheckDiagCount = 0;
+ }
+ if (A.CheckDiagIndex != UINT_MAX)
+ Label << "'" << A.CheckDiagIndex;
+ else
+ A.CheckDiagIndex = 0;
Label.flush();
LabelWidth = std::max((std::string::size_type)LabelWidth, A.Label.size());
@@ -278,6 +307,7 @@ static void BuildInputAnnotations(const std::vector<FileCheckDiag> &Diags,
}
InputAnnotation B;
B.CheckLine = A.CheckLine;
+ B.CheckDiagIndex = A.CheckDiagIndex;
B.Label = A.Label;
B.InputLine = L;
B.Marker = Marker;
@@ -308,16 +338,21 @@ static void DumpAnnotatedInput(
//
// Second, for annotations for the same input line, sort in the order of the
// FileCheck directive's line in the check file (where there's at most one
- // directive per line). The rationale of this choice is that, for any input
- // line, this sort establishes a total order of annotations that, with
- // respect to match results, is consistent across multiple lines, thus
- // making match results easier to track from one line to the next when they
- // span multiple lines.
+ // directive per line) and then by the index of the match result for that
+ // directive. The rationale of this choice is that, for any input line, this
+ // sort establishes a total order of annotations that, with respect to match
+ // results, is consistent across multiple lines, thus making match results
+ // easier to track from one line to the next when they span multiple lines.
std::sort(Annotations.begin(), Annotations.end(),
[](const InputAnnotation &A, const InputAnnotation &B) {
if (A.InputLine != B.InputLine)
return A.InputLine < B.InputLine;
- return A.CheckLine < B.CheckLine;
+ if (A.CheckLine != B.CheckLine)
+ return A.CheckLine < B.CheckLine;
+ assert(A.CheckDiagIndex != B.CheckDiagIndex &&
+ "expected diagnostic indices to be unique within a "
+ " check line");
+ return A.CheckDiagIndex < B.CheckDiagIndex;
});
// Compute the width of the label column.
OpenPOWER on IntegriCloud