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