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); 118 119 FileCheckRequest Req; 120 for (auto Prefix : CheckPrefixes) 121 Req.CheckPrefixes.push_back(Prefix); 122 123 for (auto CheckNot : ImplicitCheckNot) 124 Req.ImplicitCheckNot.push_back(CheckNot); 125 126 for (auto G : GlobalDefines) 127 Req.GlobalDefines.push_back(G); 128 129 Req.AllowEmptyInput = AllowEmptyInput; 130 Req.EnableVarScope = EnableVarScope; 131 Req.AllowDeprecatedDagOverlap = AllowDeprecatedDagOverlap; 132 Req.Verbose = Verbose; 133 Req.VerboseVerbose = VerboseVerbose; 134 Req.NoCanonicalizeWhiteSpace = NoCanonicalizeWhiteSpace; 135 Req.MatchFullLines = MatchFullLines; 136 137 if (VerboseVerbose) 138 Req.Verbose = true; 139 140 FileCheck FC(Req); 141 if (!FC.ValidateCheckPrefixes()) { 142 errs() << "Supplied check-prefix is invalid! Prefixes must be unique and " 143 "start with a letter and contain only alphanumeric characters, " 144 "hyphens and underscores\n"; 145 return 2; 146 } 147 148 Regex PrefixRE = FC.buildCheckPrefixRegex(); 149 std::string REError; 150 if (!PrefixRE.isValid(REError)) { 151 errs() << "Unable to combine check-prefix strings into a prefix regular " 152 "expression! This is likely a bug in FileCheck's verification of " 153 "the check-prefix strings. Regular expression parsing failed " 154 "with the following error: " 155 << REError << "\n"; 156 return 2; 157 } 158 159 160 SourceMgr SM; 161 162 // Read the expected strings from the check file. 163 ErrorOr<std::unique_ptr<MemoryBuffer>> CheckFileOrErr = 164 MemoryBuffer::getFileOrSTDIN(CheckFilename); 165 if (std::error_code EC = CheckFileOrErr.getError()) { 166 errs() << "Could not open check file '" << CheckFilename 167 << "': " << EC.message() << '\n'; 168 return 2; 169 } 170 MemoryBuffer &CheckFile = *CheckFileOrErr.get(); 171 172 SmallString<4096> CheckFileBuffer; 173 StringRef CheckFileText = FC.CanonicalizeFile(CheckFile, CheckFileBuffer); 174 175 SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer( 176 CheckFileText, CheckFile.getBufferIdentifier()), 177 SMLoc()); 178 179 std::vector<FileCheckString> CheckStrings; 180 if (FC.ReadCheckFile(SM, CheckFileText, PrefixRE, CheckStrings)) 181 return 2; 182 183 // Open the file to check and add it to SourceMgr. 184 ErrorOr<std::unique_ptr<MemoryBuffer>> InputFileOrErr = 185 MemoryBuffer::getFileOrSTDIN(InputFilename); 186 if (std::error_code EC = InputFileOrErr.getError()) { 187 errs() << "Could not open input file '" << InputFilename 188 << "': " << EC.message() << '\n'; 189 return 2; 190 } 191 MemoryBuffer &InputFile = *InputFileOrErr.get(); 192 193 if (InputFile.getBufferSize() == 0 && !AllowEmptyInput) { 194 errs() << "FileCheck error: '" << InputFilename << "' is empty.\n"; 195 DumpCommandLine(argc, argv); 196 return 2; 197 } 198 199 SmallString<4096> InputFileBuffer; 200 StringRef InputFileText = FC.CanonicalizeFile(InputFile, InputFileBuffer); 201 202 SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer( 203 InputFileText, InputFile.getBufferIdentifier()), 204 SMLoc()); 205 206 int ExitCode = 207 FC.CheckInput(SM, InputFileText, CheckStrings) ? EXIT_SUCCESS : 1; 208 if (ExitCode == 1 && DumpInputOnFailure) 209 errs() << "Full input was:\n<<<<<<\n" << InputFileText << "\n>>>>>>\n"; 210 211 return ExitCode; 212 } 213