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