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
24namespace llvm {
25class MemoryBuffer;
26class SourceMgr;
27template <typename T> class SmallVectorImpl;
28
29/// Contains info about various FileCheck options.
30struct 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
47namespace Check {
48
49enum 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
72enum FileCheckKindModifier {
73 /// Modifies directive to perform literal match.
74 ModifierLiteral = 0,
75
76 // The number of modifier.
77 Size
78};
79
80class 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
86public:
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.
113struct 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
175class FileCheckPatternContext;
176struct FileCheckString;
177
178/// FileCheck class takes the request and exposes various methods that
179/// use information from the request.
180class 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
186public:
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