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