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