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/raw_ostream.h" 22 #include "llvm/Support/FileCheck.h" 23 using namespace llvm; 24 25 static cl::opt<std::string> 26 CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required); 27 28 static cl::opt<std::string> 29 InputFilename("input-file", cl::desc("File to check (defaults to stdin)"), 30 cl::init("-"), cl::value_desc("filename")); 31 32 static cl::list<std::string> CheckPrefixes( 33 "check-prefix", 34 cl::desc("Prefix to use from check file (defaults to 'CHECK')")); 35 static cl::alias CheckPrefixesAlias( 36 "check-prefixes", cl::aliasopt(CheckPrefixes), cl::CommaSeparated, 37 cl::NotHidden, 38 cl::desc( 39 "Alias for -check-prefix permitting multiple comma separated values")); 40 41 static cl::opt<bool> NoCanonicalizeWhiteSpace( 42 "strict-whitespace", 43 cl::desc("Do not treat all horizontal whitespace as equivalent")); 44 45 static cl::list<std::string> ImplicitCheckNot( 46 "implicit-check-not", 47 cl::desc("Add an implicit negative check with this pattern to every\n" 48 "positive check. This can be used to ensure that no instances of\n" 49 "this pattern occur which are not matched by a positive pattern"), 50 cl::value_desc("pattern")); 51 52 static cl::list<std::string> GlobalDefines("D", cl::Prefix, 53 cl::desc("Define a variable to be used in capture patterns."), 54 cl::value_desc("VAR=VALUE")); 55 56 static cl::opt<bool> AllowEmptyInput( 57 "allow-empty", cl::init(false), 58 cl::desc("Allow the input file to be empty. This is useful when making\n" 59 "checks that some error message does not occur, for example.")); 60 61 static cl::opt<bool> MatchFullLines( 62 "match-full-lines", cl::init(false), 63 cl::desc("Require all positive matches to cover an entire input line.\n" 64 "Allows leading and trailing whitespace if --strict-whitespace\n" 65 "is not also passed.")); 66 67 static cl::opt<bool> EnableVarScope( 68 "enable-var-scope", cl::init(false), 69 cl::desc("Enables scope for regex variables. Variables with names that\n" 70 "do not start with '$' will be reset at the beginning of\n" 71 "each CHECK-LABEL block.")); 72 73 static cl::opt<bool> AllowDeprecatedDagOverlap( 74 "allow-deprecated-dag-overlap", cl::init(false), 75 cl::desc("Enable overlapping among matches in a group of consecutive\n" 76 "CHECK-DAG directives. This option is deprecated and is only\n" 77 "provided for convenience as old tests are migrated to the new\n" 78 "non-overlapping CHECK-DAG implementation.\n")); 79 80 static cl::opt<bool> Verbose("v", cl::init(false), 81 cl::desc("Print directive pattern matches.\n")); 82 83 static cl::opt<bool> VerboseVerbose( 84 "vv", cl::init(false), 85 cl::desc("Print information helpful in diagnosing internal FileCheck\n" 86 "issues. Implies -v.\n")); 87 static const char * DumpInputEnv = "FILECHECK_DUMP_INPUT_ON_FAILURE"; 88 89 static cl::opt<bool> DumpInputOnFailure( 90 "dump-input-on-failure", cl::init(std::getenv(DumpInputEnv)), 91 cl::desc("Dump original input to stderr before failing.\n" 92 "The value can be also controlled using\n" 93 "FILECHECK_DUMP_INPUT_ON_FAILURE environment variable.\n")); 94 95 typedef cl::list<std::string>::const_iterator prefix_iterator; 96 97 98 99 100 101 102 103 static void DumpCommandLine(int argc, char **argv) { 104 errs() << "FileCheck command line: "; 105 for (int I = 0; I < argc; I++) 106 errs() << " " << argv[I]; 107 errs() << "\n"; 108 } 109 110 int main(int argc, char **argv) { 111 InitLLVM X(argc, argv); 112 cl::ParseCommandLineOptions(argc, argv); 113 114 FileCheckRequest Req; 115 for (auto Prefix : CheckPrefixes) 116 Req.CheckPrefixes.push_back(Prefix); 117 118 for (auto CheckNot : ImplicitCheckNot) 119 Req.ImplicitCheckNot.push_back(CheckNot); 120 121 for (auto G : GlobalDefines) 122 Req.GlobalDefines.push_back(G); 123 124 Req.AllowEmptyInput = AllowEmptyInput; 125 Req.EnableVarScope = EnableVarScope; 126 Req.AllowDeprecatedDagOverlap = AllowDeprecatedDagOverlap; 127 Req.Verbose = Verbose; 128 Req.VerboseVerbose = VerboseVerbose; 129 Req.NoCanonicalizeWhiteSpace = NoCanonicalizeWhiteSpace; 130 Req.MatchFullLines = MatchFullLines; 131 132 if (VerboseVerbose) 133 Req.Verbose = true; 134 135 FileCheck FC(Req); 136 if (!FC.ValidateCheckPrefixes()) { 137 errs() << "Supplied check-prefix is invalid! Prefixes must be unique and " 138 "start with a letter and contain only alphanumeric characters, " 139 "hyphens and underscores\n"; 140 return 2; 141 } 142 143 Regex PrefixRE = FC.buildCheckPrefixRegex(); 144 std::string REError; 145 if (!PrefixRE.isValid(REError)) { 146 errs() << "Unable to combine check-prefix strings into a prefix regular " 147 "expression! This is likely a bug in FileCheck's verification of " 148 "the check-prefix strings. Regular expression parsing failed " 149 "with the following error: " 150 << REError << "\n"; 151 return 2; 152 } 153 154 155 SourceMgr SM; 156 157 // Read the expected strings from the check file. 158 ErrorOr<std::unique_ptr<MemoryBuffer>> CheckFileOrErr = 159 MemoryBuffer::getFileOrSTDIN(CheckFilename); 160 if (std::error_code EC = CheckFileOrErr.getError()) { 161 errs() << "Could not open check file '" << CheckFilename 162 << "': " << EC.message() << '\n'; 163 return 2; 164 } 165 MemoryBuffer &CheckFile = *CheckFileOrErr.get(); 166 167 SmallString<4096> CheckFileBuffer; 168 StringRef CheckFileText = FC.CanonicalizeFile(CheckFile, CheckFileBuffer); 169 170 SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer( 171 CheckFileText, CheckFile.getBufferIdentifier()), 172 SMLoc()); 173 174 std::vector<FileCheckString> CheckStrings; 175 if (FC.ReadCheckFile(SM, CheckFileText, PrefixRE, CheckStrings)) 176 return 2; 177 178 // Open the file to check and add it to SourceMgr. 179 ErrorOr<std::unique_ptr<MemoryBuffer>> InputFileOrErr = 180 MemoryBuffer::getFileOrSTDIN(InputFilename); 181 if (std::error_code EC = InputFileOrErr.getError()) { 182 errs() << "Could not open input file '" << InputFilename 183 << "': " << EC.message() << '\n'; 184 return 2; 185 } 186 MemoryBuffer &InputFile = *InputFileOrErr.get(); 187 188 if (InputFile.getBufferSize() == 0 && !AllowEmptyInput) { 189 errs() << "FileCheck error: '" << InputFilename << "' is empty.\n"; 190 DumpCommandLine(argc, argv); 191 return 2; 192 } 193 194 SmallString<4096> InputFileBuffer; 195 StringRef InputFileText = FC.CanonicalizeFile(InputFile, InputFileBuffer); 196 197 SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer( 198 InputFileText, InputFile.getBufferIdentifier()), 199 SMLoc()); 200 201 int ExitCode = 202 FC.CheckInput(SM, InputFileText, CheckStrings) ? EXIT_SUCCESS : 1; 203 if (ExitCode == 1 && DumpInputOnFailure) 204 errs() << "Full input was:\n<<<<<<\n" << InputFileText << "\n>>>>>>\n"; 205 206 return ExitCode; 207 } 208