1 //===- FileCheck.cpp - Check that File's Contents match what is expected --===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // FileCheck does a line-by line check of a file that validates whether it
10 // contains the expected content.  This is useful for regression tests etc.
11 //
12 // This program exits with an exit status of 2 on error, exit status of 0 if
13 // the file matched the expected contents, and exit status of 1 if it did not
14 // contain the expected contents.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #include "llvm/Support/CommandLine.h"
19 #include "llvm/Support/InitLLVM.h"
20 #include "llvm/Support/Process.h"
21 #include "llvm/Support/WithColor.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include "llvm/Support/FileCheck.h"
24 #include <cmath>
25 using namespace llvm;
26 
27 static cl::opt<std::string>
28     CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Optional);
29 
30 static cl::opt<std::string>
31     InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
32                   cl::init("-"), cl::value_desc("filename"));
33 
34 static cl::list<std::string> CheckPrefixes(
35     "check-prefix",
36     cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
37 static cl::alias CheckPrefixesAlias(
38     "check-prefixes", cl::aliasopt(CheckPrefixes), cl::CommaSeparated,
39     cl::NotHidden,
40     cl::desc(
41         "Alias for -check-prefix permitting multiple comma separated values"));
42 
43 static cl::opt<bool> NoCanonicalizeWhiteSpace(
44     "strict-whitespace",
45     cl::desc("Do not treat all horizontal whitespace as equivalent"));
46 
47 static cl::list<std::string> ImplicitCheckNot(
48     "implicit-check-not",
49     cl::desc("Add an implicit negative check with this pattern to every\n"
50              "positive check. This can be used to ensure that no instances of\n"
51              "this pattern occur which are not matched by a positive pattern"),
52     cl::value_desc("pattern"));
53 
54 static cl::list<std::string>
55     GlobalDefines("D", cl::AlwaysPrefix,
56                   cl::desc("Define a variable to be used in capture patterns."),
57                   cl::value_desc("VAR=VALUE"));
58 
59 static cl::opt<bool> AllowEmptyInput(
60     "allow-empty", cl::init(false),
61     cl::desc("Allow the input file to be empty. This is useful when making\n"
62              "checks that some error message does not occur, for example."));
63 
64 static cl::opt<bool> MatchFullLines(
65     "match-full-lines", cl::init(false),
66     cl::desc("Require all positive matches to cover an entire input line.\n"
67              "Allows leading and trailing whitespace if --strict-whitespace\n"
68              "is not also passed."));
69 
70 static cl::opt<bool> EnableVarScope(
71     "enable-var-scope", cl::init(false),
72     cl::desc("Enables scope for regex variables. Variables with names that\n"
73              "do not start with '$' will be reset at the beginning of\n"
74              "each CHECK-LABEL block."));
75 
76 static cl::opt<bool> AllowDeprecatedDagOverlap(
77     "allow-deprecated-dag-overlap", cl::init(false),
78     cl::desc("Enable overlapping among matches in a group of consecutive\n"
79              "CHECK-DAG directives.  This option is deprecated and is only\n"
80              "provided for convenience as old tests are migrated to the new\n"
81              "non-overlapping CHECK-DAG implementation.\n"));
82 
83 static cl::opt<bool> Verbose(
84     "v", cl::init(false),
85     cl::desc("Print directive pattern matches, or add them to the input dump\n"
86              "if enabled.\n"));
87 
88 static cl::opt<bool> VerboseVerbose(
89     "vv", cl::init(false),
90     cl::desc("Print information helpful in diagnosing internal FileCheck\n"
91              "issues, or add it to the input dump if enabled.  Implies\n"
92              "-v.\n"));
93 static const char * DumpInputEnv = "FILECHECK_DUMP_INPUT_ON_FAILURE";
94 
95 static cl::opt<bool> DumpInputOnFailure(
96     "dump-input-on-failure", cl::init(std::getenv(DumpInputEnv)),
97     cl::desc("Dump original input to stderr before failing.\n"
98              "The value can be also controlled using\n"
99              "FILECHECK_DUMP_INPUT_ON_FAILURE environment variable.\n"
100              "This option is deprecated in favor of -dump-input=fail.\n"));
101 
102 enum DumpInputValue {
103   DumpInputDefault,
104   DumpInputHelp,
105   DumpInputNever,
106   DumpInputFail,
107   DumpInputAlways
108 };
109 
110 static cl::opt<DumpInputValue> DumpInput(
111     "dump-input", cl::init(DumpInputDefault),
112     cl::desc("Dump input to stderr, adding annotations representing\n"
113              " currently enabled diagnostics\n"),
114     cl::value_desc("mode"),
115     cl::values(clEnumValN(DumpInputHelp, "help",
116                           "Explain dump format and quit"),
117                clEnumValN(DumpInputNever, "never", "Never dump input"),
118                clEnumValN(DumpInputFail, "fail", "Dump input on failure"),
119                clEnumValN(DumpInputAlways, "always", "Always dump input")));
120 
121 typedef cl::list<std::string>::const_iterator prefix_iterator;
122 
123 
124 
125 
126 
127 
128 
129 static void DumpCommandLine(int argc, char **argv) {
130   errs() << "FileCheck command line: ";
131   for (int I = 0; I < argc; I++)
132     errs() << " " << argv[I];
133   errs() << "\n";
134 }
135 
136 struct MarkerStyle {
137   /// The starting char (before tildes) for marking the line.
138   char Lead;
139   /// What color to use for this annotation.
140   raw_ostream::Colors Color;
141   /// A note to follow the marker, or empty string if none.
142   std::string Note;
143   MarkerStyle() {}
144   MarkerStyle(char Lead, raw_ostream::Colors Color,
145               const std::string &Note = "")
146       : Lead(Lead), Color(Color), Note(Note) {}
147 };
148 
149 static MarkerStyle GetMarker(FileCheckDiag::MatchType MatchTy) {
150   switch (MatchTy) {
151   case FileCheckDiag::MatchFoundAndExpected:
152     return MarkerStyle('^', raw_ostream::GREEN);
153   case FileCheckDiag::MatchFoundButExcluded:
154     return MarkerStyle('!', raw_ostream::RED, "error: no match expected");
155   case FileCheckDiag::MatchFoundButWrongLine:
156     return MarkerStyle('!', raw_ostream::RED, "error: match on wrong line");
157   case FileCheckDiag::MatchFoundButDiscarded:
158     return MarkerStyle('!', raw_ostream::CYAN,
159                        "discard: overlaps earlier match");
160   case FileCheckDiag::MatchNoneAndExcluded:
161     return MarkerStyle('X', raw_ostream::GREEN);
162   case FileCheckDiag::MatchNoneButExpected:
163     return MarkerStyle('X', raw_ostream::RED, "error: no match found");
164   case FileCheckDiag::MatchFuzzy:
165     return MarkerStyle('?', raw_ostream::MAGENTA, "possible intended match");
166   }
167   llvm_unreachable_internal("unexpected match type");
168 }
169 
170 static void DumpInputAnnotationHelp(raw_ostream &OS) {
171   OS << "The following description was requested by -dump-input=help to\n"
172      << "explain the input annotations printed by -dump-input=always and\n"
173      << "-dump-input=fail:\n\n";
174 
175   // Labels for input lines.
176   OS << "  - ";
177   WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "L:";
178   OS << "     labels line number L of the input file\n";
179 
180   // Labels for annotation lines.
181   OS << "  - ";
182   WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "T:L";
183   OS << "    labels the only match result for a pattern of type T from "
184      << "line L of\n"
185      << "           the check file\n";
186   OS << "  - ";
187   WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "T:L'N";
188   OS << "  labels the Nth match result for a pattern of type T from line "
189      << "L of\n"
190      << "           the check file\n";
191 
192   // Markers on annotation lines.
193   OS << "  - ";
194   WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "^~~";
195   OS << "    marks good match (reported if -v)\n"
196      << "  - ";
197   WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "!~~";
198   OS << "    marks bad match, such as:\n"
199      << "           - CHECK-NEXT on same line as previous match (error)\n"
200      << "           - CHECK-NOT found (error)\n"
201      << "           - CHECK-DAG overlapping match (discarded, reported if "
202      << "-vv)\n"
203      << "  - ";
204   WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "X~~";
205   OS << "    marks search range when no match is found, such as:\n"
206      << "           - CHECK-NEXT not found (error)\n"
207      << "           - CHECK-NOT not found (success, reported if -vv)\n"
208      << "           - CHECK-DAG not found after discarded matches (error)\n"
209      << "  - ";
210   WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "?";
211   OS << "      marks fuzzy match when no match is found\n";
212 
213   // Colors.
214   OS << "  - colors ";
215   WithColor(OS, raw_ostream::GREEN, true) << "success";
216   OS << ", ";
217   WithColor(OS, raw_ostream::RED, true) << "error";
218   OS << ", ";
219   WithColor(OS, raw_ostream::MAGENTA, true) << "fuzzy match";
220   OS << ", ";
221   WithColor(OS, raw_ostream::CYAN, true, false) << "discarded match";
222   OS << ", ";
223   WithColor(OS, raw_ostream::CYAN, true, true) << "unmatched input";
224   OS << "\n\n"
225      << "If you are not seeing color above or in input dumps, try: -color\n";
226 }
227 
228 /// An annotation for a single input line.
229 struct InputAnnotation {
230   /// The check file line (one-origin indexing) where the directive that
231   /// produced this annotation is located.
232   unsigned CheckLine;
233   /// The index of the match result for this check.
234   unsigned CheckDiagIndex;
235   /// The label for this annotation.
236   std::string Label;
237   /// What input line (one-origin indexing) this annotation marks.  This might
238   /// be different from the starting line of the original diagnostic if this is
239   /// a non-initial fragment of a diagnostic that has been broken across
240   /// multiple lines.
241   unsigned InputLine;
242   /// The column range (one-origin indexing, open end) in which to to mark the
243   /// input line.  If InputEndCol is UINT_MAX, treat it as the last column
244   /// before the newline.
245   unsigned InputStartCol, InputEndCol;
246   /// The marker to use.
247   MarkerStyle Marker;
248   /// Whether this annotation represents a good match for an expected pattern.
249   bool FoundAndExpectedMatch;
250 };
251 
252 /// Get an abbreviation for the check type.
253 std::string GetCheckTypeAbbreviation(Check::FileCheckType Ty) {
254   switch (Ty) {
255   case Check::CheckPlain:
256     if (Ty.getCount() > 1)
257       return "count";
258     return "check";
259   case Check::CheckNext:
260     return "next";
261   case Check::CheckSame:
262     return "same";
263   case Check::CheckNot:
264     return "not";
265   case Check::CheckDAG:
266     return "dag";
267   case Check::CheckLabel:
268     return "label";
269   case Check::CheckEmpty:
270     return "empty";
271   case Check::CheckEOF:
272     return "eof";
273   case Check::CheckBadNot:
274     return "bad-not";
275   case Check::CheckBadCount:
276     return "bad-count";
277   case Check::CheckNone:
278     llvm_unreachable("invalid FileCheckType");
279   }
280   llvm_unreachable("unknown FileCheckType");
281 }
282 
283 static void BuildInputAnnotations(const std::vector<FileCheckDiag> &Diags,
284                                   std::vector<InputAnnotation> &Annotations,
285                                   unsigned &LabelWidth) {
286   // How many diagnostics has the current check seen so far?
287   unsigned CheckDiagCount = 0;
288   // What's the widest label?
289   LabelWidth = 0;
290   for (auto DiagItr = Diags.begin(), DiagEnd = Diags.end(); DiagItr != DiagEnd;
291        ++DiagItr) {
292     InputAnnotation A;
293 
294     // Build label, which uniquely identifies this check result.
295     A.CheckLine = DiagItr->CheckLine;
296     llvm::raw_string_ostream Label(A.Label);
297     Label << GetCheckTypeAbbreviation(DiagItr->CheckTy) << ":"
298           << DiagItr->CheckLine;
299     A.CheckDiagIndex = UINT_MAX;
300     auto DiagNext = std::next(DiagItr);
301     if (DiagNext != DiagEnd && DiagItr->CheckTy == DiagNext->CheckTy &&
302         DiagItr->CheckLine == DiagNext->CheckLine)
303       A.CheckDiagIndex = CheckDiagCount++;
304     else if (CheckDiagCount) {
305       A.CheckDiagIndex = CheckDiagCount;
306       CheckDiagCount = 0;
307     }
308     if (A.CheckDiagIndex != UINT_MAX)
309       Label << "'" << A.CheckDiagIndex;
310     else
311       A.CheckDiagIndex = 0;
312     Label.flush();
313     LabelWidth = std::max((std::string::size_type)LabelWidth, A.Label.size());
314 
315     MarkerStyle Marker = GetMarker(DiagItr->MatchTy);
316     A.Marker = Marker;
317     A.FoundAndExpectedMatch =
318         DiagItr->MatchTy == FileCheckDiag::MatchFoundAndExpected;
319 
320     // Compute the mark location, and break annotation into multiple
321     // annotations if it spans multiple lines.
322     A.InputLine = DiagItr->InputStartLine;
323     A.InputStartCol = DiagItr->InputStartCol;
324     if (DiagItr->InputStartLine == DiagItr->InputEndLine) {
325       // Sometimes ranges are empty in order to indicate a specific point, but
326       // that would mean nothing would be marked, so adjust the range to
327       // include the following character.
328       A.InputEndCol =
329           std::max(DiagItr->InputStartCol + 1, DiagItr->InputEndCol);
330       Annotations.push_back(A);
331     } else {
332       assert(DiagItr->InputStartLine < DiagItr->InputEndLine &&
333              "expected input range not to be inverted");
334       A.InputEndCol = UINT_MAX;
335       A.Marker.Note = "";
336       Annotations.push_back(A);
337       for (unsigned L = DiagItr->InputStartLine + 1, E = DiagItr->InputEndLine;
338            L <= E; ++L) {
339         // If a range ends before the first column on a line, then it has no
340         // characters on that line, so there's nothing to render.
341         if (DiagItr->InputEndCol == 1 && L == E) {
342           Annotations.back().Marker.Note = Marker.Note;
343           break;
344         }
345         InputAnnotation B;
346         B.CheckLine = A.CheckLine;
347         B.CheckDiagIndex = A.CheckDiagIndex;
348         B.Label = A.Label;
349         B.InputLine = L;
350         B.Marker = Marker;
351         B.Marker.Lead = '~';
352         B.InputStartCol = 1;
353         if (L != E) {
354           B.InputEndCol = UINT_MAX;
355           B.Marker.Note = "";
356         } else
357           B.InputEndCol = DiagItr->InputEndCol;
358         B.FoundAndExpectedMatch = A.FoundAndExpectedMatch;
359         Annotations.push_back(B);
360       }
361     }
362   }
363 }
364 
365 static void DumpAnnotatedInput(raw_ostream &OS, const FileCheckRequest &Req,
366                                StringRef InputFileText,
367                                std::vector<InputAnnotation> &Annotations,
368                                unsigned LabelWidth) {
369   OS << "Full input was:\n<<<<<<\n";
370 
371   // Sort annotations.
372   //
373   // First, sort in the order of input lines to make it easier to find relevant
374   // annotations while iterating input lines in the implementation below.
375   // FileCheck diagnostics are not always reported and recorded in the order of
376   // input lines due to, for example, CHECK-DAG and CHECK-NOT.
377   //
378   // Second, for annotations for the same input line, sort in the order of the
379   // FileCheck directive's line in the check file (where there's at most one
380   // directive per line) and then by the index of the match result for that
381   // directive.  The rationale of this choice is that, for any input line, this
382   // sort establishes a total order of annotations that, with respect to match
383   // results, is consistent across multiple lines, thus making match results
384   // easier to track from one line to the next when they span multiple lines.
385   std::sort(Annotations.begin(), Annotations.end(),
386             [](const InputAnnotation &A, const InputAnnotation &B) {
387               if (A.InputLine != B.InputLine)
388                 return A.InputLine < B.InputLine;
389               if (A.CheckLine != B.CheckLine)
390                 return A.CheckLine < B.CheckLine;
391               // FIXME: Sometimes CHECK-LABEL reports its match twice with
392               // other diagnostics in between, and then diag index incrementing
393               // fails to work properly, and then this assert fails.  We should
394               // suppress one of those diagnostics or do a better job of
395               // computing this index.  For now, we just produce a redundant
396               // CHECK-LABEL annotation.
397               // assert(A.CheckDiagIndex != B.CheckDiagIndex &&
398               //        "expected diagnostic indices to be unique within a "
399               //        " check line");
400               return A.CheckDiagIndex < B.CheckDiagIndex;
401             });
402 
403   // Compute the width of the label column.
404   const unsigned char *InputFilePtr = InputFileText.bytes_begin(),
405                       *InputFileEnd = InputFileText.bytes_end();
406   unsigned LineCount = InputFileText.count('\n');
407   if (InputFileEnd[-1] != '\n')
408     ++LineCount;
409   unsigned LineNoWidth = std::log10(LineCount) + 1;
410   // +3 below adds spaces (1) to the left of the (right-aligned) line numbers
411   // on input lines and (2) to the right of the (left-aligned) labels on
412   // annotation lines so that input lines and annotation lines are more
413   // visually distinct.  For example, the spaces on the annotation lines ensure
414   // that input line numbers and check directive line numbers never align
415   // horizontally.  Those line numbers might not even be for the same file.
416   // One space would be enough to achieve that, but more makes it even easier
417   // to see.
418   LabelWidth = std::max(LabelWidth, LineNoWidth) + 3;
419 
420   // Print annotated input lines.
421   auto AnnotationItr = Annotations.begin(), AnnotationEnd = Annotations.end();
422   for (unsigned Line = 1;
423        InputFilePtr != InputFileEnd || AnnotationItr != AnnotationEnd;
424        ++Line) {
425     const unsigned char *InputFileLine = InputFilePtr;
426 
427     // Print right-aligned line number.
428     WithColor(OS, raw_ostream::BLACK, true)
429         << format_decimal(Line, LabelWidth) << ": ";
430 
431     // For the case where -v and colors are enabled, find the annotations for
432     // good matches for expected patterns in order to highlight everything
433     // else in the line.  There are no such annotations if -v is disabled.
434     std::vector<InputAnnotation> FoundAndExpectedMatches;
435     if (Req.Verbose && WithColor(OS).colorsEnabled()) {
436       for (auto I = AnnotationItr; I != AnnotationEnd && I->InputLine == Line;
437            ++I) {
438         if (I->FoundAndExpectedMatch)
439           FoundAndExpectedMatches.push_back(*I);
440       }
441     }
442 
443     // Print numbered line with highlighting where there are no matches for
444     // expected patterns.
445     bool Newline = false;
446     {
447       WithColor COS(OS);
448       bool InMatch = false;
449       if (Req.Verbose)
450         COS.changeColor(raw_ostream::CYAN, true, true);
451       for (unsigned Col = 1; InputFilePtr != InputFileEnd && !Newline; ++Col) {
452         bool WasInMatch = InMatch;
453         InMatch = false;
454         for (auto M : FoundAndExpectedMatches) {
455           if (M.InputStartCol <= Col && Col < M.InputEndCol) {
456             InMatch = true;
457             break;
458           }
459         }
460         if (!WasInMatch && InMatch)
461           COS.resetColor();
462         else if (WasInMatch && !InMatch)
463           COS.changeColor(raw_ostream::CYAN, true, true);
464         if (*InputFilePtr == '\n')
465           Newline = true;
466         else
467           COS << *InputFilePtr;
468         ++InputFilePtr;
469       }
470     }
471     OS << '\n';
472     unsigned InputLineWidth = InputFilePtr - InputFileLine - Newline;
473 
474     // Print any annotations.
475     while (AnnotationItr != AnnotationEnd &&
476            AnnotationItr->InputLine == Line) {
477       WithColor COS(OS, AnnotationItr->Marker.Color, true);
478       // The two spaces below are where the ": " appears on input lines.
479       COS << left_justify(AnnotationItr->Label, LabelWidth) << "  ";
480       unsigned Col;
481       for (Col = 1; Col < AnnotationItr->InputStartCol; ++Col)
482         COS << ' ';
483       COS << AnnotationItr->Marker.Lead;
484       // If InputEndCol=UINT_MAX, stop at InputLineWidth.
485       for (++Col; Col < AnnotationItr->InputEndCol && Col <= InputLineWidth;
486            ++Col)
487         COS << '~';
488       const std::string &Note = AnnotationItr->Marker.Note;
489       if (!Note.empty()) {
490         // Put the note at the end of the input line.  If we were to instead
491         // put the note right after the marker, subsequent annotations for the
492         // same input line might appear to mark this note instead of the input
493         // line.
494         for (; Col <= InputLineWidth; ++Col)
495           COS << ' ';
496         COS << ' ' << Note;
497       }
498       COS << '\n';
499       ++AnnotationItr;
500     }
501   }
502 
503   OS << ">>>>>>\n";
504 }
505 
506 int main(int argc, char **argv) {
507   // Enable use of ANSI color codes because FileCheck is using them to
508   // highlight text.
509   llvm::sys::Process::UseANSIEscapeCodes(true);
510 
511   InitLLVM X(argc, argv);
512   cl::ParseCommandLineOptions(argc, argv, /*Overview*/ "", /*Errs*/ nullptr,
513                               "FILECHECK_OPTS");
514   if (DumpInput == DumpInputHelp) {
515     DumpInputAnnotationHelp(outs());
516     return 0;
517   }
518   if (CheckFilename.empty()) {
519     errs() << "<check-file> not specified\n";
520     return 2;
521   }
522 
523   FileCheckRequest Req;
524   for (auto Prefix : CheckPrefixes)
525     Req.CheckPrefixes.push_back(Prefix);
526 
527   for (auto CheckNot : ImplicitCheckNot)
528     Req.ImplicitCheckNot.push_back(CheckNot);
529 
530   bool GlobalDefineError = false;
531   for (auto G : GlobalDefines) {
532     size_t EqIdx = G.find('=');
533     if (EqIdx == std::string::npos) {
534       errs() << "Missing equal sign in command-line definition '-D" << G
535              << "'\n";
536       GlobalDefineError = true;
537       continue;
538     }
539     if (EqIdx == 0) {
540       errs() << "Missing variable name in command-line definition '-D" << G
541              << "'\n";
542       GlobalDefineError = true;
543       continue;
544     }
545     Req.GlobalDefines.push_back(G);
546   }
547   if (GlobalDefineError)
548     return 2;
549 
550   Req.AllowEmptyInput = AllowEmptyInput;
551   Req.EnableVarScope = EnableVarScope;
552   Req.AllowDeprecatedDagOverlap = AllowDeprecatedDagOverlap;
553   Req.Verbose = Verbose;
554   Req.VerboseVerbose = VerboseVerbose;
555   Req.NoCanonicalizeWhiteSpace = NoCanonicalizeWhiteSpace;
556   Req.MatchFullLines = MatchFullLines;
557 
558   if (VerboseVerbose)
559     Req.Verbose = true;
560 
561   FileCheck FC(Req);
562   if (!FC.ValidateCheckPrefixes()) {
563     errs() << "Supplied check-prefix is invalid! Prefixes must be unique and "
564               "start with a letter and contain only alphanumeric characters, "
565               "hyphens and underscores\n";
566     return 2;
567   }
568 
569   Regex PrefixRE = FC.buildCheckPrefixRegex();
570   std::string REError;
571   if (!PrefixRE.isValid(REError)) {
572     errs() << "Unable to combine check-prefix strings into a prefix regular "
573               "expression! This is likely a bug in FileCheck's verification of "
574               "the check-prefix strings. Regular expression parsing failed "
575               "with the following error: "
576            << REError << "\n";
577     return 2;
578   }
579 
580   SourceMgr SM;
581 
582   // Read the expected strings from the check file.
583   ErrorOr<std::unique_ptr<MemoryBuffer>> CheckFileOrErr =
584       MemoryBuffer::getFileOrSTDIN(CheckFilename);
585   if (std::error_code EC = CheckFileOrErr.getError()) {
586     errs() << "Could not open check file '" << CheckFilename
587            << "': " << EC.message() << '\n';
588     return 2;
589   }
590   MemoryBuffer &CheckFile = *CheckFileOrErr.get();
591 
592   SmallString<4096> CheckFileBuffer;
593   StringRef CheckFileText = FC.CanonicalizeFile(CheckFile, CheckFileBuffer);
594 
595   SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
596                             CheckFileText, CheckFile.getBufferIdentifier()),
597                         SMLoc());
598 
599   std::vector<FileCheckString> CheckStrings;
600   if (FC.ReadCheckFile(SM, CheckFileText, PrefixRE, CheckStrings))
601     return 2;
602 
603   // Open the file to check and add it to SourceMgr.
604   ErrorOr<std::unique_ptr<MemoryBuffer>> InputFileOrErr =
605       MemoryBuffer::getFileOrSTDIN(InputFilename);
606   if (std::error_code EC = InputFileOrErr.getError()) {
607     errs() << "Could not open input file '" << InputFilename
608            << "': " << EC.message() << '\n';
609     return 2;
610   }
611   MemoryBuffer &InputFile = *InputFileOrErr.get();
612 
613   if (InputFile.getBufferSize() == 0 && !AllowEmptyInput) {
614     errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
615     DumpCommandLine(argc, argv);
616     return 2;
617   }
618 
619   SmallString<4096> InputFileBuffer;
620   StringRef InputFileText = FC.CanonicalizeFile(InputFile, InputFileBuffer);
621 
622   SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
623                             InputFileText, InputFile.getBufferIdentifier()),
624                         SMLoc());
625 
626   if (DumpInput == DumpInputDefault)
627     DumpInput = DumpInputOnFailure ? DumpInputFail : DumpInputNever;
628 
629   std::vector<FileCheckDiag> Diags;
630   int ExitCode = FC.CheckInput(SM, InputFileText, CheckStrings,
631                                DumpInput == DumpInputNever ? nullptr : &Diags)
632                      ? EXIT_SUCCESS
633                      : 1;
634   if (DumpInput == DumpInputAlways ||
635       (ExitCode == 1 && DumpInput == DumpInputFail)) {
636     errs() << "\n"
637            << "Input file: "
638            << (InputFilename == "-" ? "<stdin>" : InputFilename.getValue())
639            << "\n"
640            << "Check file: " << CheckFilename << "\n"
641            << "\n"
642            << "-dump-input=help describes the format of the following dump.\n"
643            << "\n";
644     std::vector<InputAnnotation> Annotations;
645     unsigned LabelWidth;
646     BuildInputAnnotations(Diags, Annotations, LabelWidth);
647     DumpAnnotatedInput(errs(), Req, InputFileText, Annotations, LabelWidth);
648   }
649 
650   return ExitCode;
651 }
652