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> ; |
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 | , |
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(position: FileCheckKindModifier::ModifierLiteral, val: 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 | |