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