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" 213e66509fSJoel E. Denny #include "llvm/Support/Process.h" 22ee3c74fbSChris Lattner #include "llvm/Support/raw_ostream.h" 23ffa9d2e4SAditya Nandakumar #include "llvm/Support/FileCheck.h" 24ee3c74fbSChris Lattner using namespace llvm; 25ee3c74fbSChris Lattner 26ee3c74fbSChris Lattner static cl::opt<std::string> 27ee3c74fbSChris Lattner CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required); 28ee3c74fbSChris Lattner 29ee3c74fbSChris Lattner static cl::opt<std::string> 30ee3c74fbSChris Lattner InputFilename("input-file", cl::desc("File to check (defaults to stdin)"), 31ee3c74fbSChris Lattner cl::init("-"), cl::value_desc("filename")); 32ee3c74fbSChris Lattner 33e8f2fb20SChandler Carruth static cl::list<std::string> CheckPrefixes( 34e8f2fb20SChandler Carruth "check-prefix", 35ee3c74fbSChris Lattner cl::desc("Prefix to use from check file (defaults to 'CHECK')")); 36fd557cb0SDaniel Sanders static cl::alias CheckPrefixesAlias( 37fd557cb0SDaniel Sanders "check-prefixes", cl::aliasopt(CheckPrefixes), cl::CommaSeparated, 38fd557cb0SDaniel Sanders cl::NotHidden, 39fd557cb0SDaniel Sanders cl::desc( 40fd557cb0SDaniel Sanders "Alias for -check-prefix permitting multiple comma separated values")); 41ee3c74fbSChris Lattner 42e8f2fb20SChandler Carruth static cl::opt<bool> NoCanonicalizeWhiteSpace( 43e8f2fb20SChandler Carruth "strict-whitespace", 442c3e5cdfSChris Lattner cl::desc("Do not treat all horizontal whitespace as equivalent")); 452c3e5cdfSChris Lattner 4656ccdbbdSAlexander Kornienko static cl::list<std::string> ImplicitCheckNot( 4756ccdbbdSAlexander Kornienko "implicit-check-not", 4856ccdbbdSAlexander Kornienko cl::desc("Add an implicit negative check with this pattern to every\n" 4956ccdbbdSAlexander Kornienko "positive check. This can be used to ensure that no instances of\n" 5056ccdbbdSAlexander Kornienko "this pattern occur which are not matched by a positive pattern"), 5156ccdbbdSAlexander Kornienko cl::value_desc("pattern")); 5256ccdbbdSAlexander Kornienko 5346e1fd61SAlexander Richardson static cl::list<std::string> GlobalDefines("D", cl::Prefix, 5446e1fd61SAlexander Richardson cl::desc("Define a variable to be used in capture patterns."), 5546e1fd61SAlexander Richardson cl::value_desc("VAR=VALUE")); 5646e1fd61SAlexander Richardson 571b9f936fSJustin Bogner static cl::opt<bool> AllowEmptyInput( 581b9f936fSJustin Bogner "allow-empty", cl::init(false), 591b9f936fSJustin Bogner cl::desc("Allow the input file to be empty. This is useful when making\n" 601b9f936fSJustin Bogner "checks that some error message does not occur, for example.")); 611b9f936fSJustin Bogner 6285913ccaSJames Y Knight static cl::opt<bool> MatchFullLines( 6385913ccaSJames Y Knight "match-full-lines", cl::init(false), 6485913ccaSJames Y Knight cl::desc("Require all positive matches to cover an entire input line.\n" 6585913ccaSJames Y Knight "Allows leading and trailing whitespace if --strict-whitespace\n" 6685913ccaSJames Y Knight "is not also passed.")); 6785913ccaSJames Y Knight 68f55e72a5SArtem Belevich static cl::opt<bool> EnableVarScope( 69f55e72a5SArtem Belevich "enable-var-scope", cl::init(false), 70f55e72a5SArtem Belevich cl::desc("Enables scope for regex variables. Variables with names that\n" 71f55e72a5SArtem Belevich "do not start with '$' will be reset at the beginning of\n" 72f55e72a5SArtem Belevich "each CHECK-LABEL block.")); 73f55e72a5SArtem Belevich 74bcf5b441SJoel E. Denny static cl::opt<bool> AllowDeprecatedDagOverlap( 75bcf5b441SJoel E. Denny "allow-deprecated-dag-overlap", cl::init(false), 76bcf5b441SJoel E. Denny cl::desc("Enable overlapping among matches in a group of consecutive\n" 77bcf5b441SJoel E. Denny "CHECK-DAG directives. This option is deprecated and is only\n" 78bcf5b441SJoel E. Denny "provided for convenience as old tests are migrated to the new\n" 79bcf5b441SJoel E. Denny "non-overlapping CHECK-DAG implementation.\n")); 80bcf5b441SJoel E. Denny 81dc5ba317SJoel E. Denny static cl::opt<bool> Verbose("v", cl::init(false), 82dc5ba317SJoel E. Denny cl::desc("Print directive pattern matches.\n")); 83dc5ba317SJoel E. Denny 84dc5ba317SJoel E. Denny static cl::opt<bool> VerboseVerbose( 85dc5ba317SJoel E. Denny "vv", cl::init(false), 86dc5ba317SJoel E. Denny cl::desc("Print information helpful in diagnosing internal FileCheck\n" 87dc5ba317SJoel E. Denny "issues. Implies -v.\n")); 88346dfbe2SGeorge Karpenkov static const char * DumpInputEnv = "FILECHECK_DUMP_INPUT_ON_FAILURE"; 89346dfbe2SGeorge Karpenkov 90346dfbe2SGeorge Karpenkov static cl::opt<bool> DumpInputOnFailure( 91346dfbe2SGeorge Karpenkov "dump-input-on-failure", cl::init(std::getenv(DumpInputEnv)), 92346dfbe2SGeorge Karpenkov cl::desc("Dump original input to stderr before failing.\n" 93346dfbe2SGeorge Karpenkov "The value can be also controlled using\n" 94346dfbe2SGeorge Karpenkov "FILECHECK_DUMP_INPUT_ON_FAILURE environment variable.\n")); 95dc5ba317SJoel E. Denny 9613df4626SMatt Arsenault typedef cl::list<std::string>::const_iterator prefix_iterator; 9713df4626SMatt Arsenault 9813df4626SMatt Arsenault 9913df4626SMatt Arsenault 100726774cbSChandler Carruth 101726774cbSChandler Carruth 102726774cbSChandler Carruth 103c2735158SRui Ueyama 1042bd4f8b6SXinliang David Li static void DumpCommandLine(int argc, char **argv) { 1052bd4f8b6SXinliang David Li errs() << "FileCheck command line: "; 1062bd4f8b6SXinliang David Li for (int I = 0; I < argc; I++) 1072bd4f8b6SXinliang David Li errs() << " " << argv[I]; 1082bd4f8b6SXinliang David Li errs() << "\n"; 1092bd4f8b6SXinliang David Li } 1102bd4f8b6SXinliang David Li 111ee3c74fbSChris Lattner int main(int argc, char **argv) { 1123e66509fSJoel E. Denny // Enable use of ANSI color codes because FileCheck is using them to 1133e66509fSJoel E. Denny // highlight text. 1143e66509fSJoel E. Denny llvm::sys::Process::UseANSIEscapeCodes(true); 1153e66509fSJoel E. Denny 116197194b6SRui Ueyama InitLLVM X(argc, argv); 117*24994d77SJoel E. Denny cl::ParseCommandLineOptions(argc, argv, /*Overview*/ "", /*Errs*/ nullptr, 118*24994d77SJoel E. Denny "FILECHECK_OPTS"); 119ee3c74fbSChris Lattner 120ffa9d2e4SAditya Nandakumar FileCheckRequest Req; 121ffa9d2e4SAditya Nandakumar for (auto Prefix : CheckPrefixes) 122ffa9d2e4SAditya Nandakumar Req.CheckPrefixes.push_back(Prefix); 123ffa9d2e4SAditya Nandakumar 124ffa9d2e4SAditya Nandakumar for (auto CheckNot : ImplicitCheckNot) 125ffa9d2e4SAditya Nandakumar Req.ImplicitCheckNot.push_back(CheckNot); 126ffa9d2e4SAditya Nandakumar 127ffa9d2e4SAditya Nandakumar for (auto G : GlobalDefines) 128ffa9d2e4SAditya Nandakumar Req.GlobalDefines.push_back(G); 129ffa9d2e4SAditya Nandakumar 130ffa9d2e4SAditya Nandakumar Req.AllowEmptyInput = AllowEmptyInput; 131ffa9d2e4SAditya Nandakumar Req.EnableVarScope = EnableVarScope; 132ffa9d2e4SAditya Nandakumar Req.AllowDeprecatedDagOverlap = AllowDeprecatedDagOverlap; 133ffa9d2e4SAditya Nandakumar Req.Verbose = Verbose; 134ffa9d2e4SAditya Nandakumar Req.VerboseVerbose = VerboseVerbose; 135ffa9d2e4SAditya Nandakumar Req.NoCanonicalizeWhiteSpace = NoCanonicalizeWhiteSpace; 136ffa9d2e4SAditya Nandakumar Req.MatchFullLines = MatchFullLines; 137ffa9d2e4SAditya Nandakumar 138ffa9d2e4SAditya Nandakumar if (VerboseVerbose) 139ffa9d2e4SAditya Nandakumar Req.Verbose = true; 140ffa9d2e4SAditya Nandakumar 141ffa9d2e4SAditya Nandakumar FileCheck FC(Req); 142ffa9d2e4SAditya Nandakumar if (!FC.ValidateCheckPrefixes()) { 14313df4626SMatt Arsenault errs() << "Supplied check-prefix is invalid! Prefixes must be unique and " 14413df4626SMatt Arsenault "start with a letter and contain only alphanumeric characters, " 14513df4626SMatt Arsenault "hyphens and underscores\n"; 146c2735158SRui Ueyama return 2; 147c2735158SRui Ueyama } 148c2735158SRui Ueyama 149ffa9d2e4SAditya Nandakumar Regex PrefixRE = FC.buildCheckPrefixRegex(); 150726774cbSChandler Carruth std::string REError; 151726774cbSChandler Carruth if (!PrefixRE.isValid(REError)) { 152726774cbSChandler Carruth errs() << "Unable to combine check-prefix strings into a prefix regular " 153726774cbSChandler Carruth "expression! This is likely a bug in FileCheck's verification of " 154726774cbSChandler Carruth "the check-prefix strings. Regular expression parsing failed " 155726774cbSChandler Carruth "with the following error: " 156726774cbSChandler Carruth << REError << "\n"; 157726774cbSChandler Carruth return 2; 158726774cbSChandler Carruth } 15913df4626SMatt Arsenault 160dc5ba317SJoel E. Denny 161ee3c74fbSChris Lattner SourceMgr SM; 162ee3c74fbSChris Lattner 163ee3c74fbSChris Lattner // Read the expected strings from the check file. 16420247900SChandler Carruth ErrorOr<std::unique_ptr<MemoryBuffer>> CheckFileOrErr = 16520247900SChandler Carruth MemoryBuffer::getFileOrSTDIN(CheckFilename); 16620247900SChandler Carruth if (std::error_code EC = CheckFileOrErr.getError()) { 16720247900SChandler Carruth errs() << "Could not open check file '" << CheckFilename 16820247900SChandler Carruth << "': " << EC.message() << '\n'; 16920247900SChandler Carruth return 2; 17020247900SChandler Carruth } 17120247900SChandler Carruth MemoryBuffer &CheckFile = *CheckFileOrErr.get(); 17220247900SChandler Carruth 17320247900SChandler Carruth SmallString<4096> CheckFileBuffer; 174ffa9d2e4SAditya Nandakumar StringRef CheckFileText = FC.CanonicalizeFile(CheckFile, CheckFileBuffer); 17520247900SChandler Carruth 17620247900SChandler Carruth SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer( 17720247900SChandler Carruth CheckFileText, CheckFile.getBufferIdentifier()), 17820247900SChandler Carruth SMLoc()); 17920247900SChandler Carruth 180ffa9d2e4SAditya Nandakumar std::vector<FileCheckString> CheckStrings; 181ffa9d2e4SAditya Nandakumar if (FC.ReadCheckFile(SM, CheckFileText, PrefixRE, CheckStrings)) 182ee3c74fbSChris Lattner return 2; 183ee3c74fbSChris Lattner 184ee3c74fbSChris Lattner // Open the file to check and add it to SourceMgr. 18520247900SChandler Carruth ErrorOr<std::unique_ptr<MemoryBuffer>> InputFileOrErr = 186adf21f2aSRafael Espindola MemoryBuffer::getFileOrSTDIN(InputFilename); 18720247900SChandler Carruth if (std::error_code EC = InputFileOrErr.getError()) { 188adf21f2aSRafael Espindola errs() << "Could not open input file '" << InputFilename 189adf21f2aSRafael Espindola << "': " << EC.message() << '\n'; 1908e1c6477SEli Bendersky return 2; 191ee3c74fbSChris Lattner } 19220247900SChandler Carruth MemoryBuffer &InputFile = *InputFileOrErr.get(); 1932c3e5cdfSChris Lattner 19420247900SChandler Carruth if (InputFile.getBufferSize() == 0 && !AllowEmptyInput) { 195b692bed7SChris Lattner errs() << "FileCheck error: '" << InputFilename << "' is empty.\n"; 1962bd4f8b6SXinliang David Li DumpCommandLine(argc, argv); 1978e1c6477SEli Bendersky return 2; 198b692bed7SChris Lattner } 199b692bed7SChris Lattner 20020247900SChandler Carruth SmallString<4096> InputFileBuffer; 201ffa9d2e4SAditya Nandakumar StringRef InputFileText = FC.CanonicalizeFile(InputFile, InputFileBuffer); 2022c3e5cdfSChris Lattner 203e8f2fb20SChandler Carruth SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer( 204e8f2fb20SChandler Carruth InputFileText, InputFile.getBufferIdentifier()), 205e8f2fb20SChandler Carruth SMLoc()); 206ee3c74fbSChris Lattner 207ffa9d2e4SAditya Nandakumar int ExitCode = 208ffa9d2e4SAditya Nandakumar FC.CheckInput(SM, InputFileText, CheckStrings) ? EXIT_SUCCESS : 1; 209346dfbe2SGeorge Karpenkov if (ExitCode == 1 && DumpInputOnFailure) 210346dfbe2SGeorge Karpenkov errs() << "Full input was:\n<<<<<<\n" << InputFileText << "\n>>>>>>\n"; 211346dfbe2SGeorge Karpenkov 212346dfbe2SGeorge Karpenkov return ExitCode; 213ee3c74fbSChris Lattner } 214