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