blob: b44ab025694bed770344b8a97a930c2b183fb2f1 [file] [log] [blame]
Olivier Deprezf4ef2d02021-04-20 13:36:24 +02001//==-- 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
24namespace llvm {
25
26/// Contains info about various FileCheck options.
27struct 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
44namespace Check {
45
46enum 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
68enum FileCheckKindModifier {
69 /// Modifies directive to perform literal match.
70 ModifierLiteral = 0,
71
72 // The number of modifier.
73 Size
74};
75
76class 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
82public:
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.
110struct 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 /// All match result types whose names end with "Excluded" are for excluded
122 /// patterns, and all others are for expected patterns.
123 ///
124 /// There might be more than one match result for a single pattern. For
125 /// example, there might be several discarded matches
126 /// (MatchFoundButDiscarded) before either a good match
127 /// (MatchFoundAndExpected) or a failure to match (MatchNoneButExpected),
128 /// and there might be a fuzzy match (MatchFuzzy) after the latter.
129 enum MatchType {
130 /// Indicates a good match for an expected pattern.
131 MatchFoundAndExpected,
132 /// Indicates a match for an excluded pattern.
133 MatchFoundButExcluded,
134 /// Indicates a match for an expected pattern, but the match is on the
135 /// wrong line.
136 MatchFoundButWrongLine,
137 /// Indicates a discarded match for an expected pattern.
138 MatchFoundButDiscarded,
139 /// Indicates no match for an excluded pattern.
140 MatchNoneAndExcluded,
141 /// Indicates no match for an expected pattern, but this might follow good
142 /// matches when multiple matches are expected for the pattern, or it might
143 /// follow discarded matches for the pattern.
144 MatchNoneButExpected,
145 /// Indicates a fuzzy match that serves as a suggestion for the next
146 /// intended match for an expected pattern with too few or no good matches.
147 MatchFuzzy,
148 } MatchTy;
149 /// The search range if MatchTy is MatchNoneAndExcluded or
150 /// MatchNoneButExpected, or the match range otherwise.
151 unsigned InputStartLine;
152 unsigned InputStartCol;
153 unsigned InputEndLine;
154 unsigned InputEndCol;
155 /// A note to replace the one normally indicated by MatchTy, or the empty
156 /// string if none.
157 std::string Note;
158 FileCheckDiag(const SourceMgr &SM, const Check::FileCheckType &CheckTy,
159 SMLoc CheckLoc, MatchType MatchTy, SMRange InputRange,
160 StringRef Note = "");
161};
162
163class FileCheckPatternContext;
164struct FileCheckString;
165
166/// FileCheck class takes the request and exposes various methods that
167/// use information from the request.
168class FileCheck {
169 FileCheckRequest Req;
170 std::unique_ptr<FileCheckPatternContext> PatternContext;
171 // C++17 TODO: make this a plain std::vector.
172 std::unique_ptr<std::vector<FileCheckString>> CheckStrings;
173
174public:
175 explicit FileCheck(FileCheckRequest Req);
176 ~FileCheck();
177
178 // Combines the check prefixes into a single regex so that we can efficiently
179 // scan for any of the set.
180 //
181 // The semantics are that the longest-match wins which matches our regex
182 // library.
183 Regex buildCheckPrefixRegex();
184
185 /// Reads the check file from \p Buffer and records the expected strings it
186 /// contains. Errors are reported against \p SM.
187 ///
188 /// Only expected strings whose prefix is one of those listed in \p PrefixRE
189 /// are recorded. \returns true in case of an error, false otherwise.
190 ///
191 /// If \p ImpPatBufferIDRange, then the range (inclusive start, exclusive end)
192 /// of IDs for source buffers added to \p SM for implicit patterns are
193 /// recorded in it. The range is empty if there are none.
194 bool
195 readCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
196 std::pair<unsigned, unsigned> *ImpPatBufferIDRange = nullptr);
197
198 bool ValidateCheckPrefixes();
199
200 /// Canonicalizes whitespaces in the file. Line endings are replaced with
201 /// UNIX-style '\n'.
202 StringRef CanonicalizeFile(MemoryBuffer &MB,
203 SmallVectorImpl<char> &OutputBuffer);
204
205 /// Checks the input to FileCheck provided in the \p Buffer against the
206 /// expected strings read from the check file and record diagnostics emitted
207 /// in \p Diags. Errors are recorded against \p SM.
208 ///
209 /// \returns false if the input fails to satisfy the checks.
210 bool checkInput(SourceMgr &SM, StringRef Buffer,
211 std::vector<FileCheckDiag> *Diags = nullptr);
212};
213
214} // namespace llvm
215
216#endif