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