1 //==-- llvm/FileCheck/FileCheck.h --------------------------------*- C++ -*-==// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// \file This file has some utilities to use FileCheck as an API 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_FILECHECK_FILECHECK_H 14 #define LLVM_FILECHECK_FILECHECK_H 15 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/Support/MemoryBuffer.h" 18 #include "llvm/Support/Regex.h" 19 #include "llvm/Support/SourceMgr.h" 20 #include <bitset> 21 #include <string> 22 #include <vector> 23 24 namespace llvm { 25 26 /// Contains info about various FileCheck options. 27 struct FileCheckRequest { 28 std::vector<StringRef> CheckPrefixes; 29 std::vector<StringRef> CommentPrefixes; 30 bool NoCanonicalizeWhiteSpace = false; 31 std::vector<StringRef> ImplicitCheckNot; 32 std::vector<StringRef> GlobalDefines; 33 bool AllowEmptyInput = false; 34 bool AllowUnusedPrefixes = false; 35 bool MatchFullLines = false; 36 bool IgnoreCase = false; 37 bool IsDefaultCheckPrefix = false; 38 bool EnableVarScope = false; 39 bool AllowDeprecatedDagOverlap = false; 40 bool Verbose = false; 41 bool VerboseVerbose = false; 42 }; 43 44 namespace Check { 45 46 enum FileCheckKind { 47 CheckNone = 0, 48 CheckPlain, 49 CheckNext, 50 CheckSame, 51 CheckNot, 52 CheckDAG, 53 CheckLabel, 54 CheckEmpty, 55 CheckComment, 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 enum FileCheckKindModifier { 69 /// Modifies directive to perform literal match. 70 ModifierLiteral = 0, 71 72 // The number of modifier. 73 Size 74 }; 75 76 class FileCheckType { 77 FileCheckKind Kind; 78 int Count; ///< optional Count for some checks 79 /// Modifers for the check directive. 80 std::bitset<FileCheckKindModifier::Size> Modifiers; 81 82 public: 83 FileCheckType(FileCheckKind Kind = CheckNone) 84 : Kind(Kind), Count(1), Modifiers() {} 85 FileCheckType(const FileCheckType &) = default; 86 FileCheckType &operator=(const FileCheckType &) = default; 87 88 operator FileCheckKind() const { return Kind; } 89 90 int getCount() const { return Count; } 91 FileCheckType &setCount(int C); 92 93 bool isLiteralMatch() const { 94 return Modifiers[FileCheckKindModifier::ModifierLiteral]; 95 } 96 FileCheckType &setLiteralMatch(bool Literal = true) { 97 Modifiers.set(FileCheckKindModifier::ModifierLiteral, Literal); 98 return *this; 99 } 100 101 // \returns a description of \p Prefix. 102 std::string getDescription(StringRef Prefix) const; 103 104 // \returns a description of \p Modifiers. 105 std::string getModifiersDescription() const; 106 }; 107 } // namespace Check 108 109 /// Summary of a FileCheck diagnostic. 110 struct FileCheckDiag { 111 /// What is the FileCheck directive for this diagnostic? 112 Check::FileCheckType CheckTy; 113 /// Where is the FileCheck directive for this diagnostic? 114 SMLoc CheckLoc; 115 /// What type of match result does this diagnostic describe? 116 /// 117 /// A directive's supplied pattern is said to be either expected or excluded 118 /// depending on whether the pattern must have or must not have a match in 119 /// order for the directive to succeed. For example, a CHECK directive's 120 /// pattern is expected, and a CHECK-NOT directive's pattern is excluded. 121 /// 122 /// There might be more than one match result for a single pattern. For 123 /// example, there might be several discarded matches 124 /// (MatchFoundButDiscarded) before either a good match 125 /// (MatchFoundAndExpected) or a failure to match (MatchNoneButExpected), 126 /// and there might be a fuzzy match (MatchFuzzy) after the latter. 127 enum MatchType { 128 /// Indicates a good match for an expected pattern. 129 MatchFoundAndExpected, 130 /// Indicates a match for an excluded pattern. 131 MatchFoundButExcluded, 132 /// Indicates a match for an expected pattern, but the match is on the 133 /// wrong line. 134 MatchFoundButWrongLine, 135 /// Indicates a discarded match for an expected pattern. 136 MatchFoundButDiscarded, 137 /// Indicates an error while processing a match after the match was found 138 /// for an expected or excluded pattern. The error is specified by \c Note, 139 /// to which it should be appropriate to prepend "error: " later. The full 140 /// match itself should be recorded in a preceding diagnostic of a different 141 /// \c MatchFound match type. 142 MatchFoundErrorNote, 143 /// Indicates no match for an excluded pattern. 144 MatchNoneAndExcluded, 145 /// Indicates no match for an expected pattern, but this might follow good 146 /// matches when multiple matches are expected for the pattern, or it might 147 /// follow discarded matches for the pattern. 148 MatchNoneButExpected, 149 /// Indicates no match due to an expected or excluded pattern that has 150 /// proven to be invalid at match time. The exact problems are usually 151 /// reported in subsequent diagnostics of the same match type but with 152 /// \c Note set. 153 MatchNoneForInvalidPattern, 154 /// Indicates a fuzzy match that serves as a suggestion for the next 155 /// intended match for an expected pattern with too few or no good matches. 156 MatchFuzzy, 157 } MatchTy; 158 /// The search range if MatchTy starts with MatchNone, or the match range 159 /// otherwise. 160 unsigned InputStartLine; 161 unsigned InputStartCol; 162 unsigned InputEndLine; 163 unsigned InputEndCol; 164 /// A note to replace the one normally indicated by MatchTy, or the empty 165 /// string if none. 166 std::string Note; 167 FileCheckDiag(const SourceMgr &SM, const Check::FileCheckType &CheckTy, 168 SMLoc CheckLoc, MatchType MatchTy, SMRange InputRange, 169 StringRef Note = ""); 170 }; 171 172 class FileCheckPatternContext; 173 struct FileCheckString; 174 175 /// FileCheck class takes the request and exposes various methods that 176 /// use information from the request. 177 class FileCheck { 178 FileCheckRequest Req; 179 std::unique_ptr<FileCheckPatternContext> PatternContext; 180 // C++17 TODO: make this a plain std::vector. 181 std::unique_ptr<std::vector<FileCheckString>> CheckStrings; 182 183 public: 184 explicit FileCheck(FileCheckRequest Req); 185 ~FileCheck(); 186 187 // Combines the check prefixes into a single regex so that we can efficiently 188 // scan for any of the set. 189 // 190 // The semantics are that the longest-match wins which matches our regex 191 // library. 192 Regex buildCheckPrefixRegex(); 193 194 /// Reads the check file from \p Buffer and records the expected strings it 195 /// contains. Errors are reported against \p SM. 196 /// 197 /// Only expected strings whose prefix is one of those listed in \p PrefixRE 198 /// are recorded. \returns true in case of an error, false otherwise. 199 /// 200 /// If \p ImpPatBufferIDRange, then the range (inclusive start, exclusive end) 201 /// of IDs for source buffers added to \p SM for implicit patterns are 202 /// recorded in it. The range is empty if there are none. 203 bool 204 readCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE, 205 std::pair<unsigned, unsigned> *ImpPatBufferIDRange = nullptr); 206 207 bool ValidateCheckPrefixes(); 208 209 /// Canonicalizes whitespaces in the file. Line endings are replaced with 210 /// UNIX-style '\n'. 211 StringRef CanonicalizeFile(MemoryBuffer &MB, 212 SmallVectorImpl<char> &OutputBuffer); 213 214 /// Checks the input to FileCheck provided in the \p Buffer against the 215 /// expected strings read from the check file and record diagnostics emitted 216 /// in \p Diags. Errors are recorded against \p SM. 217 /// 218 /// \returns false if the input fails to satisfy the checks. 219 bool checkInput(SourceMgr &SM, StringRef Buffer, 220 std::vector<FileCheckDiag> *Diags = nullptr); 221 }; 222 223 } // namespace llvm 224 225 #endif 226