1 //==-- llvm/Support/FileCheck.h ---------------------------*- C++ -*-==// 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 /// \file This file has some utilities to use FileCheck as an API 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_SUPPORT_FILECHECK_H 15 #define LLVM_SUPPORT_FILECHECK_H 16 17 #include "llvm/ADT/StringMap.h" 18 #include "llvm/Support/MemoryBuffer.h" 19 #include "llvm/Support/Regex.h" 20 #include "llvm/Support/SourceMgr.h" 21 #include <vector> 22 #include <map> 23 24 namespace llvm { 25 26 /// Contains info about various FileCheck options. 27 struct FileCheckRequest { 28 std::vector<std::string> CheckPrefixes; 29 bool NoCanonicalizeWhiteSpace = false; 30 std::vector<std::string> ImplicitCheckNot; 31 std::vector<std::string> GlobalDefines; 32 bool AllowEmptyInput = false; 33 bool MatchFullLines = false; 34 bool EnableVarScope = false; 35 bool AllowDeprecatedDagOverlap = false; 36 bool Verbose = false; 37 bool VerboseVerbose = false; 38 }; 39 40 41 //===----------------------------------------------------------------------===// 42 // Pattern Handling Code. 43 //===----------------------------------------------------------------------===// 44 45 namespace Check { 46 47 enum FileCheckKind { 48 CheckNone = 0, 49 CheckPlain, 50 CheckNext, 51 CheckSame, 52 CheckNot, 53 CheckDAG, 54 CheckLabel, 55 CheckEmpty, 56 57 /// Indicates the pattern only matches the end of file. This is used for 58 /// trailing CHECK-NOTs. 59 CheckEOF, 60 61 /// Marks when parsing found a -NOT check combined with another CHECK suffix. 62 CheckBadNot, 63 64 /// Marks when parsing found a -COUNT directive with invalid count value. 65 CheckBadCount 66 }; 67 68 class FileCheckType { 69 FileCheckKind Kind; 70 int Count; ///< optional Count for some checks 71 72 public: Kind(Kind)73 FileCheckType(FileCheckKind Kind = CheckNone) : Kind(Kind), Count(1) {} 74 FileCheckType(const FileCheckType &) = default; 75 FileCheckKind()76 operator FileCheckKind() const { return Kind; } 77 getCount()78 int getCount() const { return Count; } 79 FileCheckType &setCount(int C); 80 81 std::string getDescription(StringRef Prefix) const; 82 }; 83 } 84 85 struct FileCheckDiag; 86 87 class FileCheckPattern { 88 SMLoc PatternLoc; 89 90 /// A fixed string to match as the pattern or empty if this pattern requires 91 /// a regex match. 92 StringRef FixedStr; 93 94 /// A regex string to match as the pattern or empty if this pattern requires 95 /// a fixed string to match. 96 std::string RegExStr; 97 98 /// Entries in this vector map to uses of a variable in the pattern, e.g. 99 /// "foo[[bar]]baz". In this case, the RegExStr will contain "foobaz" and 100 /// we'll get an entry in this vector that tells us to insert the value of 101 /// bar at offset 3. 102 std::vector<std::pair<StringRef, unsigned>> VariableUses; 103 104 /// Maps definitions of variables to their parenthesized capture numbers. 105 /// 106 /// E.g. for the pattern "foo[[bar:.*]]baz", VariableDefs will map "bar" to 107 /// 1. 108 std::map<StringRef, unsigned> VariableDefs; 109 110 Check::FileCheckType CheckTy; 111 112 /// Contains the number of line this pattern is in. 113 unsigned LineNumber; 114 115 public: FileCheckPattern(Check::FileCheckType Ty)116 explicit FileCheckPattern(Check::FileCheckType Ty) 117 : CheckTy(Ty) {} 118 119 /// Returns the location in source code. getLoc()120 SMLoc getLoc() const { return PatternLoc; } 121 122 bool ParsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, 123 unsigned LineNumber, const FileCheckRequest &Req); 124 size_t Match(StringRef Buffer, size_t &MatchLen, 125 StringMap<StringRef> &VariableTable) const; 126 void PrintVariableUses(const SourceMgr &SM, StringRef Buffer, 127 const StringMap<StringRef> &VariableTable, 128 SMRange MatchRange = None) const; 129 void PrintFuzzyMatch(const SourceMgr &SM, StringRef Buffer, 130 const StringMap<StringRef> &VariableTable, 131 std::vector<FileCheckDiag> *Diags) const; 132 hasVariable()133 bool hasVariable() const { 134 return !(VariableUses.empty() && VariableDefs.empty()); 135 } 136 getCheckTy()137 Check::FileCheckType getCheckTy() const { return CheckTy; } 138 getCount()139 int getCount() const { return CheckTy.getCount(); } 140 141 private: 142 bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM); 143 void AddBackrefToRegEx(unsigned BackrefNum); 144 unsigned 145 ComputeMatchDistance(StringRef Buffer, 146 const StringMap<StringRef> &VariableTable) const; 147 bool EvaluateExpression(StringRef Expr, std::string &Value) const; 148 size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM); 149 }; 150 151 //===----------------------------------------------------------------------===// 152 /// Summary of a FileCheck diagnostic. 153 //===----------------------------------------------------------------------===// 154 155 struct FileCheckDiag { 156 /// What is the FileCheck directive for this diagnostic? 157 Check::FileCheckType CheckTy; 158 /// Where is the FileCheck directive for this diagnostic? 159 unsigned CheckLine, CheckCol; 160 /// What type of match result does this diagnostic describe? 161 /// 162 /// A directive's supplied pattern is said to be either expected or excluded 163 /// depending on whether the pattern must have or must not have a match in 164 /// order for the directive to succeed. For example, a CHECK directive's 165 /// pattern is expected, and a CHECK-NOT directive's pattern is excluded. 166 /// All match result types whose names end with "Excluded" are for excluded 167 /// patterns, and all others are for expected patterns. 168 /// 169 /// There might be more than one match result for a single pattern. For 170 /// example, there might be several discarded matches 171 /// (MatchFoundButDiscarded) before either a good match 172 /// (MatchFoundAndExpected) or a failure to match (MatchNoneButExpected), 173 /// and there might be a fuzzy match (MatchFuzzy) after the latter. 174 enum MatchType { 175 /// Indicates a good match for an expected pattern. 176 MatchFoundAndExpected, 177 /// Indicates a match for an excluded pattern. 178 MatchFoundButExcluded, 179 /// Indicates a match for an expected pattern, but the match is on the 180 /// wrong line. 181 MatchFoundButWrongLine, 182 /// Indicates a discarded match for an expected pattern. 183 MatchFoundButDiscarded, 184 /// Indicates no match for an excluded pattern. 185 MatchNoneAndExcluded, 186 /// Indicates no match for an expected pattern, but this might follow good 187 /// matches when multiple matches are expected for the pattern, or it might 188 /// follow discarded matches for the pattern. 189 MatchNoneButExpected, 190 /// Indicates a fuzzy match that serves as a suggestion for the next 191 /// intended match for an expected pattern with too few or no good matches. 192 MatchFuzzy, 193 } MatchTy; 194 /// The search range if MatchTy is MatchNoneAndExcluded or 195 /// MatchNoneButExpected, or the match range otherwise. 196 unsigned InputStartLine; 197 unsigned InputStartCol; 198 unsigned InputEndLine; 199 unsigned InputEndCol; 200 FileCheckDiag(const SourceMgr &SM, const Check::FileCheckType &CheckTy, 201 SMLoc CheckLoc, MatchType MatchTy, SMRange InputRange); 202 }; 203 204 //===----------------------------------------------------------------------===// 205 // Check Strings. 206 //===----------------------------------------------------------------------===// 207 208 /// A check that we found in the input file. 209 struct FileCheckString { 210 /// The pattern to match. 211 FileCheckPattern Pat; 212 213 /// Which prefix name this check matched. 214 StringRef Prefix; 215 216 /// The location in the match file that the check string was specified. 217 SMLoc Loc; 218 219 /// All of the strings that are disallowed from occurring between this match 220 /// string and the previous one (or start of file). 221 std::vector<FileCheckPattern> DagNotStrings; 222 FileCheckStringFileCheckString223 FileCheckString(const FileCheckPattern &P, StringRef S, SMLoc L) 224 : Pat(P), Prefix(S), Loc(L) {} 225 226 size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, 227 size_t &MatchLen, StringMap<StringRef> &VariableTable, 228 FileCheckRequest &Req, std::vector<FileCheckDiag> *Diags) const; 229 230 bool CheckNext(const SourceMgr &SM, StringRef Buffer) const; 231 bool CheckSame(const SourceMgr &SM, StringRef Buffer) const; 232 bool CheckNot(const SourceMgr &SM, StringRef Buffer, 233 const std::vector<const FileCheckPattern *> &NotStrings, 234 StringMap<StringRef> &VariableTable, 235 const FileCheckRequest &Req, 236 std::vector<FileCheckDiag> *Diags) const; 237 size_t CheckDag(const SourceMgr &SM, StringRef Buffer, 238 std::vector<const FileCheckPattern *> &NotStrings, 239 StringMap<StringRef> &VariableTable, 240 const FileCheckRequest &Req, 241 std::vector<FileCheckDiag> *Diags) const; 242 }; 243 244 /// FileCheck class takes the request and exposes various methods that 245 /// use information from the request. 246 class FileCheck { 247 FileCheckRequest Req; 248 249 public: FileCheck(FileCheckRequest Req)250 FileCheck(FileCheckRequest Req) : Req(Req) {} 251 252 // Combines the check prefixes into a single regex so that we can efficiently 253 // scan for any of the set. 254 // 255 // The semantics are that the longest-match wins which matches our regex 256 // library. 257 Regex buildCheckPrefixRegex(); 258 259 /// Read the check file, which specifies the sequence of expected strings. 260 /// 261 /// The strings are added to the CheckStrings vector. Returns true in case of 262 /// an error, false otherwise. 263 bool ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE, 264 std::vector<FileCheckString> &CheckStrings); 265 266 bool ValidateCheckPrefixes(); 267 268 /// Canonicalize whitespaces in the file. Line endings are replaced with 269 /// UNIX-style '\n'. 270 StringRef CanonicalizeFile(MemoryBuffer &MB, 271 SmallVectorImpl<char> &OutputBuffer); 272 273 /// Check the input to FileCheck provided in the \p Buffer against the \p 274 /// CheckStrings read from the check file. 275 /// 276 /// Returns false if the input fails to satisfy the checks. 277 bool CheckInput(SourceMgr &SM, StringRef Buffer, 278 ArrayRef<FileCheckString> CheckStrings, 279 std::vector<FileCheckDiag> *Diags = nullptr); 280 }; 281 } // namespace llvm 282 #endif 283