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/raw_ostream.h"
23 #include "llvm/Support/FileCheck.h"
24 using namespace llvm;
25 
26 static cl::opt<std::string>
27     CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);
28 
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"));
32 
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"));
41 
42 static cl::opt<bool> NoCanonicalizeWhiteSpace(
43     "strict-whitespace",
44     cl::desc("Do not treat all horizontal whitespace as equivalent"));
45 
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"));
52 
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"));
56 
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."));
61 
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."));
67 
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."));
73 
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"));
80 
81 static cl::opt<bool> Verbose("v", cl::init(false),
82                              cl::desc("Print directive pattern matches.\n"));
83 
84 static cl::opt<bool> VerboseVerbose(
85     "vv", cl::init(false),
86     cl::desc("Print information helpful in diagnosing internal FileCheck\n"
87              "issues.  Implies -v.\n"));
88 static const char * DumpInputEnv = "FILECHECK_DUMP_INPUT_ON_FAILURE";
89 
90 static cl::opt<bool> DumpInputOnFailure(
91     "dump-input-on-failure", cl::init(std::getenv(DumpInputEnv)),
92     cl::desc("Dump original input to stderr before failing.\n"
93              "The value can be also controlled using\n"
94              "FILECHECK_DUMP_INPUT_ON_FAILURE environment variable.\n"));
95 
96 typedef cl::list<std::string>::const_iterator prefix_iterator;
97 
98 
99 
100 
101 
102 
103 
104 static void DumpCommandLine(int argc, char **argv) {
105   errs() << "FileCheck command line: ";
106   for (int I = 0; I < argc; I++)
107     errs() << " " << argv[I];
108   errs() << "\n";
109 }
110 
111 int main(int argc, char **argv) {
112   // Enable use of ANSI color codes because FileCheck is using them to
113   // highlight text.
114   llvm::sys::Process::UseANSIEscapeCodes(true);
115 
116   InitLLVM X(argc, argv);
117   cl::ParseCommandLineOptions(argc, argv, /*Overview*/ "", /*Errs*/ nullptr,
118                               "FILECHECK_OPTS");
119 
120   FileCheckRequest Req;
121   for (auto Prefix : CheckPrefixes)
122     Req.CheckPrefixes.push_back(Prefix);
123 
124   for (auto CheckNot : ImplicitCheckNot)
125     Req.ImplicitCheckNot.push_back(CheckNot);
126 
127   for (auto G : GlobalDefines)
128     Req.GlobalDefines.push_back(G);
129 
130   Req.AllowEmptyInput = AllowEmptyInput;
131   Req.EnableVarScope = EnableVarScope;
132   Req.AllowDeprecatedDagOverlap = AllowDeprecatedDagOverlap;
133   Req.Verbose = Verbose;
134   Req.VerboseVerbose = VerboseVerbose;
135   Req.NoCanonicalizeWhiteSpace = NoCanonicalizeWhiteSpace;
136   Req.MatchFullLines = MatchFullLines;
137 
138   if (VerboseVerbose)
139     Req.Verbose = true;
140 
141   FileCheck FC(Req);
142   if (!FC.ValidateCheckPrefixes()) {
143     errs() << "Supplied check-prefix is invalid! Prefixes must be unique and "
144               "start with a letter and contain only alphanumeric characters, "
145               "hyphens and underscores\n";
146     return 2;
147   }
148 
149   Regex PrefixRE = FC.buildCheckPrefixRegex();
150   std::string REError;
151   if (!PrefixRE.isValid(REError)) {
152     errs() << "Unable to combine check-prefix strings into a prefix regular "
153               "expression! This is likely a bug in FileCheck's verification of "
154               "the check-prefix strings. Regular expression parsing failed "
155               "with the following error: "
156            << REError << "\n";
157     return 2;
158   }
159 
160 
161   SourceMgr SM;
162 
163   // Read the expected strings from the check file.
164   ErrorOr<std::unique_ptr<MemoryBuffer>> CheckFileOrErr =
165       MemoryBuffer::getFileOrSTDIN(CheckFilename);
166   if (std::error_code EC = CheckFileOrErr.getError()) {
167     errs() << "Could not open check file '" << CheckFilename
168            << "': " << EC.message() << '\n';
169     return 2;
170   }
171   MemoryBuffer &CheckFile = *CheckFileOrErr.get();
172 
173   SmallString<4096> CheckFileBuffer;
174   StringRef CheckFileText = FC.CanonicalizeFile(CheckFile, CheckFileBuffer);
175 
176   SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
177                             CheckFileText, CheckFile.getBufferIdentifier()),
178                         SMLoc());
179 
180   std::vector<FileCheckString> CheckStrings;
181   if (FC.ReadCheckFile(SM, CheckFileText, PrefixRE, CheckStrings))
182     return 2;
183 
184   // Open the file to check and add it to SourceMgr.
185   ErrorOr<std::unique_ptr<MemoryBuffer>> InputFileOrErr =
186       MemoryBuffer::getFileOrSTDIN(InputFilename);
187   if (std::error_code EC = InputFileOrErr.getError()) {
188     errs() << "Could not open input file '" << InputFilename
189            << "': " << EC.message() << '\n';
190     return 2;
191   }
192   MemoryBuffer &InputFile = *InputFileOrErr.get();
193 
194   if (InputFile.getBufferSize() == 0 && !AllowEmptyInput) {
195     errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
196     DumpCommandLine(argc, argv);
197     return 2;
198   }
199 
200   SmallString<4096> InputFileBuffer;
201   StringRef InputFileText = FC.CanonicalizeFile(InputFile, InputFileBuffer);
202 
203   SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
204                             InputFileText, InputFile.getBufferIdentifier()),
205                         SMLoc());
206 
207   int ExitCode =
208       FC.CheckInput(SM, InputFileText, CheckStrings) ? EXIT_SUCCESS : 1;
209   if (ExitCode == 1 && DumpInputOnFailure)
210     errs() << "Full input was:\n<<<<<<\n" << InputFileText << "\n>>>>>>\n";
211 
212   return ExitCode;
213 }
214