aboutsummaryrefslogtreecommitdiff
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.cpp96
1 files changed, 55 insertions, 41 deletions
diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp
index 6cfd0fd..ef6c62b 100644
--- a/llvm/utils/FileCheck/FileCheck.cpp
+++ b/llvm/utils/FileCheck/FileCheck.cpp
@@ -241,11 +241,8 @@ static void DumpInputAnnotationHelp(raw_ostream &OS) {
/// An annotation for a single input line.
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 index of the match result across all checks
+ unsigned DiagIndex;
/// The label for this annotation.
std::string Label;
/// What input line (one-origin indexing) this annotation marks. This might
@@ -253,7 +250,7 @@ struct InputAnnotation {
/// a non-initial fragment of a diagnostic that has been broken across
/// multiple lines.
unsigned InputLine;
- /// The column range (one-origin indexing, open end) in which to to mark the
+ /// The column range (one-origin indexing, open end) in which to mark the
/// input line. If InputEndCol is UINT_MAX, treat it as the last column
/// before the newline.
unsigned InputStartCol, InputEndCol;
@@ -300,6 +297,8 @@ BuildInputAnnotations(const SourceMgr &SM, unsigned CheckFileBufferID,
const std::vector<FileCheckDiag> &Diags,
std::vector<InputAnnotation> &Annotations,
unsigned &LabelWidth) {
+ // How many diagnostics have we seen so far?
+ unsigned DiagCount = 0;
// How many diagnostics has the current check seen so far?
unsigned CheckDiagCount = 0;
// What's the widest label?
@@ -307,12 +306,12 @@ BuildInputAnnotations(const SourceMgr &SM, unsigned CheckFileBufferID,
for (auto DiagItr = Diags.begin(), DiagEnd = Diags.end(); DiagItr != DiagEnd;
++DiagItr) {
InputAnnotation A;
+ A.DiagIndex = DiagCount++;
// Build label, which uniquely identifies this check result.
unsigned CheckBufferID = SM.FindBufferContainingLoc(DiagItr->CheckLoc);
auto CheckLineAndCol =
SM.getLineAndColumn(DiagItr->CheckLoc, CheckBufferID);
- A.CheckLine = CheckLineAndCol.first;
llvm::raw_string_ostream Label(A.Label);
Label << GetCheckTypeAbbreviation(DiagItr->CheckTy) << ":";
if (CheckBufferID == CheckFileBufferID)
@@ -323,19 +322,17 @@ BuildInputAnnotations(const SourceMgr &SM, unsigned CheckFileBufferID,
else
llvm_unreachable("expected diagnostic's check location to be either in "
"the check file or for an implicit pattern");
- A.CheckDiagIndex = UINT_MAX;
+ unsigned CheckDiagIndex = UINT_MAX;
auto DiagNext = std::next(DiagItr);
if (DiagNext != DiagEnd && DiagItr->CheckTy == DiagNext->CheckTy &&
DiagItr->CheckLoc == DiagNext->CheckLoc)
- A.CheckDiagIndex = CheckDiagCount++;
+ CheckDiagIndex = CheckDiagCount++;
else if (CheckDiagCount) {
- A.CheckDiagIndex = CheckDiagCount;
+ CheckDiagIndex = CheckDiagCount;
CheckDiagCount = 0;
}
- if (A.CheckDiagIndex != UINT_MAX)
- Label << "'" << A.CheckDiagIndex;
- else
- A.CheckDiagIndex = 0;
+ if (CheckDiagIndex != UINT_MAX)
+ Label << "'" << CheckDiagIndex;
Label.flush();
LabelWidth = std::max((std::string::size_type)LabelWidth, A.Label.size());
@@ -366,8 +363,7 @@ BuildInputAnnotations(const SourceMgr &SM, unsigned CheckFileBufferID,
if (DiagItr->InputEndCol == 1 && L == E)
break;
InputAnnotation B;
- B.CheckLine = A.CheckLine;
- B.CheckDiagIndex = A.CheckDiagIndex;
+ B.DiagIndex = A.DiagIndex;
B.Label = A.Label;
B.InputLine = L;
B.Marker = A.Marker;
@@ -392,35 +388,53 @@ static void DumpAnnotatedInput(raw_ostream &OS, const FileCheckRequest &Req,
OS << "Full input was:\n<<<<<<\n";
// Sort annotations.
- //
- // First, sort in the order of input lines to make it easier to find relevant
- // annotations while iterating input lines in the implementation below.
- // FileCheck diagnostics are not always reported and recorded in the order of
- // input lines due to, for example, CHECK-DAG and CHECK-NOT.
- //
- // 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) 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) {
+ // 1. Sort annotations in the order of the input lines.
+ //
+ // This makes it easier to find relevant annotations while
+ // iterating input lines in the implementation below. FileCheck
+ // does not always produce diagnostics in the order of input
+ // lines due to, for example, CHECK-DAG and CHECK-NOT.
if (A.InputLine != B.InputLine)
return A.InputLine < B.InputLine;
- if (A.CheckLine != B.CheckLine)
- return A.CheckLine < B.CheckLine;
- // FIXME: Sometimes CHECK-LABEL reports its match twice with
- // other diagnostics in between, and then diag index incrementing
- // fails to work properly, and then this assert fails. We should
- // suppress one of those diagnostics or do a better job of
- // computing this index. For now, we just produce a redundant
- // CHECK-LABEL annotation.
- // assert(A.CheckDiagIndex != B.CheckDiagIndex &&
- // "expected diagnostic indices to be unique within a "
- // " check line");
- return A.CheckDiagIndex < B.CheckDiagIndex;
+ // 2. Sort annotations in the temporal order FileCheck produced
+ // their associated diagnostics.
+ //
+ // This sort offers several benefits:
+ //
+ // A. On a single input line, the order of annotations reflects
+ // the FileCheck logic for processing directives/patterns.
+ // This can be helpful in understanding cases in which the
+ // order of the associated directives/patterns in the check
+ // file or on the command line either (i) does not match the
+ // temporal order in which FileCheck looks for matches for the
+ // directives/patterns (due to, for example, CHECK-LABEL,
+ // CHECK-NOT, or `--implicit-check-not`) or (ii) does match
+ // that order but does not match the order of those
+ // diagnostics along an input line (due to, for example,
+ // CHECK-DAG).
+ //
+ // On the other hand, because our presentation format presents
+ // input lines in order, there's no clear way to offer the
+ // same benefit across input lines. For consistency, it might
+ // then seem worthwhile to have annotations on a single line
+ // also sorted in input order (that is, by input column).
+ // However, in practice, this appears to be more confusing
+ // than helpful. Perhaps it's intuitive to expect annotations
+ // to be listed in the temporal order in which they were
+ // produced except in cases the presentation format obviously
+ // and inherently cannot support it (that is, across input
+ // lines).
+ //
+ // B. When diagnostics' annotations are split among multiple
+ // input lines, the user must track them from one input line
+ // to the next. One property of the sort chosen here is that
+ // it facilitates the user in this regard by ensuring the
+ // following: when comparing any two input lines, a
+ // diagnostic's annotations are sorted in the same position
+ // relative to all other diagnostics' annotations.
+ return A.DiagIndex < B.DiagIndex;
});
// Compute the width of the label column.