1ee3c74fbSChris Lattner //===- FileCheck.cpp - Check that File's Contents match what is expected --===//
2ee3c74fbSChris Lattner //
3ee3c74fbSChris Lattner //                     The LLVM Compiler Infrastructure
4ee3c74fbSChris Lattner //
5ee3c74fbSChris Lattner // This file is distributed under the University of Illinois Open Source
6ee3c74fbSChris Lattner // License. See LICENSE.TXT for details.
7ee3c74fbSChris Lattner //
8ee3c74fbSChris Lattner //===----------------------------------------------------------------------===//
9ee3c74fbSChris Lattner //
10ee3c74fbSChris Lattner // FileCheck does a line-by line check of a file that validates whether it
11ee3c74fbSChris Lattner // contains the expected content.  This is useful for regression tests etc.
12ee3c74fbSChris Lattner //
13b5ecceffSJames Henderson // This program exits with an exit status of 2 on error, exit status of 0 if
14ee3c74fbSChris Lattner // the file matched the expected contents, and exit status of 1 if it did not
15ee3c74fbSChris Lattner // contain the expected contents.
16ee3c74fbSChris Lattner //
17ee3c74fbSChris Lattner //===----------------------------------------------------------------------===//
18ee3c74fbSChris Lattner 
19ee3c74fbSChris Lattner #include "llvm/Support/CommandLine.h"
20197194b6SRui Ueyama #include "llvm/Support/InitLLVM.h"
21ee3c74fbSChris Lattner #include "llvm/Support/raw_ostream.h"
22*ffa9d2e4SAditya Nandakumar #include "llvm/Support/FileCheck.h"
23ee3c74fbSChris Lattner using namespace llvm;
24ee3c74fbSChris Lattner 
25ee3c74fbSChris Lattner static cl::opt<std::string>
26ee3c74fbSChris Lattner     CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);
27ee3c74fbSChris Lattner 
28ee3c74fbSChris Lattner static cl::opt<std::string>
29ee3c74fbSChris Lattner     InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
30ee3c74fbSChris Lattner                   cl::init("-"), cl::value_desc("filename"));
31ee3c74fbSChris Lattner 
32e8f2fb20SChandler Carruth static cl::list<std::string> CheckPrefixes(
33e8f2fb20SChandler Carruth     "check-prefix",
34ee3c74fbSChris Lattner     cl::desc("Prefix to use from check file (defaults to 'CHECK')"));
35fd557cb0SDaniel Sanders static cl::alias CheckPrefixesAlias(
36fd557cb0SDaniel Sanders     "check-prefixes", cl::aliasopt(CheckPrefixes), cl::CommaSeparated,
37fd557cb0SDaniel Sanders     cl::NotHidden,
38fd557cb0SDaniel Sanders     cl::desc(
39fd557cb0SDaniel Sanders         "Alias for -check-prefix permitting multiple comma separated values"));
40ee3c74fbSChris Lattner 
41e8f2fb20SChandler Carruth static cl::opt<bool> NoCanonicalizeWhiteSpace(
42e8f2fb20SChandler Carruth     "strict-whitespace",
432c3e5cdfSChris Lattner     cl::desc("Do not treat all horizontal whitespace as equivalent"));
442c3e5cdfSChris Lattner 
4556ccdbbdSAlexander Kornienko static cl::list<std::string> ImplicitCheckNot(
4656ccdbbdSAlexander Kornienko     "implicit-check-not",
4756ccdbbdSAlexander Kornienko     cl::desc("Add an implicit negative check with this pattern to every\n"
4856ccdbbdSAlexander Kornienko              "positive check. This can be used to ensure that no instances of\n"
4956ccdbbdSAlexander Kornienko              "this pattern occur which are not matched by a positive pattern"),
5056ccdbbdSAlexander Kornienko     cl::value_desc("pattern"));
5156ccdbbdSAlexander Kornienko 
5246e1fd61SAlexander Richardson static cl::list<std::string> GlobalDefines("D", cl::Prefix,
5346e1fd61SAlexander Richardson     cl::desc("Define a variable to be used in capture patterns."),
5446e1fd61SAlexander Richardson     cl::value_desc("VAR=VALUE"));
5546e1fd61SAlexander Richardson 
561b9f936fSJustin Bogner static cl::opt<bool> AllowEmptyInput(
571b9f936fSJustin Bogner     "allow-empty", cl::init(false),
581b9f936fSJustin Bogner     cl::desc("Allow the input file to be empty. This is useful when making\n"
591b9f936fSJustin Bogner              "checks that some error message does not occur, for example."));
601b9f936fSJustin Bogner 
6185913ccaSJames Y Knight static cl::opt<bool> MatchFullLines(
6285913ccaSJames Y Knight     "match-full-lines", cl::init(false),
6385913ccaSJames Y Knight     cl::desc("Require all positive matches to cover an entire input line.\n"
6485913ccaSJames Y Knight              "Allows leading and trailing whitespace if --strict-whitespace\n"
6585913ccaSJames Y Knight              "is not also passed."));
6685913ccaSJames Y Knight 
67f55e72a5SArtem Belevich static cl::opt<bool> EnableVarScope(
68f55e72a5SArtem Belevich     "enable-var-scope", cl::init(false),
69f55e72a5SArtem Belevich     cl::desc("Enables scope for regex variables. Variables with names that\n"
70f55e72a5SArtem Belevich              "do not start with '$' will be reset at the beginning of\n"
71f55e72a5SArtem Belevich              "each CHECK-LABEL block."));
72f55e72a5SArtem Belevich 
73bcf5b441SJoel E. Denny static cl::opt<bool> AllowDeprecatedDagOverlap(
74bcf5b441SJoel E. Denny     "allow-deprecated-dag-overlap", cl::init(false),
75bcf5b441SJoel E. Denny     cl::desc("Enable overlapping among matches in a group of consecutive\n"
76bcf5b441SJoel E. Denny              "CHECK-DAG directives.  This option is deprecated and is only\n"
77bcf5b441SJoel E. Denny              "provided for convenience as old tests are migrated to the new\n"
78bcf5b441SJoel E. Denny              "non-overlapping CHECK-DAG implementation.\n"));
79bcf5b441SJoel E. Denny 
80dc5ba317SJoel E. Denny static cl::opt<bool> Verbose("v", cl::init(false),
81dc5ba317SJoel E. Denny                              cl::desc("Print directive pattern matches.\n"));
82dc5ba317SJoel E. Denny 
83dc5ba317SJoel E. Denny static cl::opt<bool> VerboseVerbose(
84dc5ba317SJoel E. Denny     "vv", cl::init(false),
85dc5ba317SJoel E. Denny     cl::desc("Print information helpful in diagnosing internal FileCheck\n"
86dc5ba317SJoel E. Denny              "issues.  Implies -v.\n"));
87346dfbe2SGeorge Karpenkov static const char * DumpInputEnv = "FILECHECK_DUMP_INPUT_ON_FAILURE";
88346dfbe2SGeorge Karpenkov 
89346dfbe2SGeorge Karpenkov static cl::opt<bool> DumpInputOnFailure(
90346dfbe2SGeorge Karpenkov     "dump-input-on-failure", cl::init(std::getenv(DumpInputEnv)),
91346dfbe2SGeorge Karpenkov     cl::desc("Dump original input to stderr before failing.\n"
92346dfbe2SGeorge Karpenkov              "The value can be also controlled using\n"
93346dfbe2SGeorge Karpenkov              "FILECHECK_DUMP_INPUT_ON_FAILURE environment variable.\n"));
94dc5ba317SJoel E. Denny 
9513df4626SMatt Arsenault typedef cl::list<std::string>::const_iterator prefix_iterator;
9613df4626SMatt Arsenault 
9713df4626SMatt Arsenault 
9813df4626SMatt Arsenault 
99726774cbSChandler Carruth 
100726774cbSChandler Carruth 
101726774cbSChandler Carruth 
102c2735158SRui Ueyama 
1032bd4f8b6SXinliang David Li static void DumpCommandLine(int argc, char **argv) {
1042bd4f8b6SXinliang David Li   errs() << "FileCheck command line: ";
1052bd4f8b6SXinliang David Li   for (int I = 0; I < argc; I++)
1062bd4f8b6SXinliang David Li     errs() << " " << argv[I];
1072bd4f8b6SXinliang David Li   errs() << "\n";
1082bd4f8b6SXinliang David Li }
1092bd4f8b6SXinliang David Li 
110ee3c74fbSChris Lattner int main(int argc, char **argv) {
111197194b6SRui Ueyama   InitLLVM X(argc, argv);
112ee3c74fbSChris Lattner   cl::ParseCommandLineOptions(argc, argv);
113ee3c74fbSChris Lattner 
114*ffa9d2e4SAditya Nandakumar   FileCheckRequest Req;
115*ffa9d2e4SAditya Nandakumar   for (auto Prefix : CheckPrefixes)
116*ffa9d2e4SAditya Nandakumar     Req.CheckPrefixes.push_back(Prefix);
117*ffa9d2e4SAditya Nandakumar 
118*ffa9d2e4SAditya Nandakumar   for (auto CheckNot : ImplicitCheckNot)
119*ffa9d2e4SAditya Nandakumar     Req.ImplicitCheckNot.push_back(CheckNot);
120*ffa9d2e4SAditya Nandakumar 
121*ffa9d2e4SAditya Nandakumar   for (auto G : GlobalDefines)
122*ffa9d2e4SAditya Nandakumar     Req.GlobalDefines.push_back(G);
123*ffa9d2e4SAditya Nandakumar 
124*ffa9d2e4SAditya Nandakumar   Req.AllowEmptyInput = AllowEmptyInput;
125*ffa9d2e4SAditya Nandakumar   Req.EnableVarScope = EnableVarScope;
126*ffa9d2e4SAditya Nandakumar   Req.AllowDeprecatedDagOverlap = AllowDeprecatedDagOverlap;
127*ffa9d2e4SAditya Nandakumar   Req.Verbose = Verbose;
128*ffa9d2e4SAditya Nandakumar   Req.VerboseVerbose = VerboseVerbose;
129*ffa9d2e4SAditya Nandakumar   Req.NoCanonicalizeWhiteSpace = NoCanonicalizeWhiteSpace;
130*ffa9d2e4SAditya Nandakumar   Req.MatchFullLines = MatchFullLines;
131*ffa9d2e4SAditya Nandakumar 
132*ffa9d2e4SAditya Nandakumar   if (VerboseVerbose)
133*ffa9d2e4SAditya Nandakumar     Req.Verbose = true;
134*ffa9d2e4SAditya Nandakumar 
135*ffa9d2e4SAditya Nandakumar   FileCheck FC(Req);
136*ffa9d2e4SAditya Nandakumar   if (!FC.ValidateCheckPrefixes()) {
13713df4626SMatt Arsenault     errs() << "Supplied check-prefix is invalid! Prefixes must be unique and "
13813df4626SMatt Arsenault               "start with a letter and contain only alphanumeric characters, "
13913df4626SMatt Arsenault               "hyphens and underscores\n";
140c2735158SRui Ueyama     return 2;
141c2735158SRui Ueyama   }
142c2735158SRui Ueyama 
143*ffa9d2e4SAditya Nandakumar   Regex PrefixRE = FC.buildCheckPrefixRegex();
144726774cbSChandler Carruth   std::string REError;
145726774cbSChandler Carruth   if (!PrefixRE.isValid(REError)) {
146726774cbSChandler Carruth     errs() << "Unable to combine check-prefix strings into a prefix regular "
147726774cbSChandler Carruth               "expression! This is likely a bug in FileCheck's verification of "
148726774cbSChandler Carruth               "the check-prefix strings. Regular expression parsing failed "
149726774cbSChandler Carruth               "with the following error: "
150726774cbSChandler Carruth            << REError << "\n";
151726774cbSChandler Carruth     return 2;
152726774cbSChandler Carruth   }
15313df4626SMatt Arsenault 
154dc5ba317SJoel E. Denny 
155ee3c74fbSChris Lattner   SourceMgr SM;
156ee3c74fbSChris Lattner 
157ee3c74fbSChris Lattner   // Read the expected strings from the check file.
15820247900SChandler Carruth   ErrorOr<std::unique_ptr<MemoryBuffer>> CheckFileOrErr =
15920247900SChandler Carruth       MemoryBuffer::getFileOrSTDIN(CheckFilename);
16020247900SChandler Carruth   if (std::error_code EC = CheckFileOrErr.getError()) {
16120247900SChandler Carruth     errs() << "Could not open check file '" << CheckFilename
16220247900SChandler Carruth            << "': " << EC.message() << '\n';
16320247900SChandler Carruth     return 2;
16420247900SChandler Carruth   }
16520247900SChandler Carruth   MemoryBuffer &CheckFile = *CheckFileOrErr.get();
16620247900SChandler Carruth 
16720247900SChandler Carruth   SmallString<4096> CheckFileBuffer;
168*ffa9d2e4SAditya Nandakumar   StringRef CheckFileText = FC.CanonicalizeFile(CheckFile, CheckFileBuffer);
16920247900SChandler Carruth 
17020247900SChandler Carruth   SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
17120247900SChandler Carruth                             CheckFileText, CheckFile.getBufferIdentifier()),
17220247900SChandler Carruth                         SMLoc());
17320247900SChandler Carruth 
174*ffa9d2e4SAditya Nandakumar   std::vector<FileCheckString> CheckStrings;
175*ffa9d2e4SAditya Nandakumar   if (FC.ReadCheckFile(SM, CheckFileText, PrefixRE, CheckStrings))
176ee3c74fbSChris Lattner     return 2;
177ee3c74fbSChris Lattner 
178ee3c74fbSChris Lattner   // Open the file to check and add it to SourceMgr.
17920247900SChandler Carruth   ErrorOr<std::unique_ptr<MemoryBuffer>> InputFileOrErr =
180adf21f2aSRafael Espindola       MemoryBuffer::getFileOrSTDIN(InputFilename);
18120247900SChandler Carruth   if (std::error_code EC = InputFileOrErr.getError()) {
182adf21f2aSRafael Espindola     errs() << "Could not open input file '" << InputFilename
183adf21f2aSRafael Espindola            << "': " << EC.message() << '\n';
1848e1c6477SEli Bendersky     return 2;
185ee3c74fbSChris Lattner   }
18620247900SChandler Carruth   MemoryBuffer &InputFile = *InputFileOrErr.get();
1872c3e5cdfSChris Lattner 
18820247900SChandler Carruth   if (InputFile.getBufferSize() == 0 && !AllowEmptyInput) {
189b692bed7SChris Lattner     errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
1902bd4f8b6SXinliang David Li     DumpCommandLine(argc, argv);
1918e1c6477SEli Bendersky     return 2;
192b692bed7SChris Lattner   }
193b692bed7SChris Lattner 
19420247900SChandler Carruth   SmallString<4096> InputFileBuffer;
195*ffa9d2e4SAditya Nandakumar   StringRef InputFileText = FC.CanonicalizeFile(InputFile, InputFileBuffer);
1962c3e5cdfSChris Lattner 
197e8f2fb20SChandler Carruth   SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
198e8f2fb20SChandler Carruth                             InputFileText, InputFile.getBufferIdentifier()),
199e8f2fb20SChandler Carruth                         SMLoc());
200ee3c74fbSChris Lattner 
201*ffa9d2e4SAditya Nandakumar   int ExitCode =
202*ffa9d2e4SAditya Nandakumar       FC.CheckInput(SM, InputFileText, CheckStrings) ? EXIT_SUCCESS : 1;
203346dfbe2SGeorge Karpenkov   if (ExitCode == 1 && DumpInputOnFailure)
204346dfbe2SGeorge Karpenkov     errs() << "Full input was:\n<<<<<<\n" << InputFileText << "\n>>>>>>\n";
205346dfbe2SGeorge Karpenkov 
206346dfbe2SGeorge Karpenkov   return ExitCode;
207ee3c74fbSChris Lattner }
208