• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- FileCheckImpl.h - Private FileCheck Interface ------------*- 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 // This file defines the private interfaces of FileCheck. Its purpose is to
10 // allow unit testing of FileCheck and to separate the interface from the
11 // implementation. It is only meant to be used by FileCheck.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_LIB_SUPPORT_FILECHECKIMPL_H
16 #define LLVM_LIB_SUPPORT_FILECHECKIMPL_H
17 
18 #include "llvm/ADT/Optional.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Support/Error.h"
22 #include "llvm/Support/SourceMgr.h"
23 #include <map>
24 #include <string>
25 #include <vector>
26 
27 namespace llvm {
28 
29 //===----------------------------------------------------------------------===//
30 // Numeric substitution handling code.
31 //===----------------------------------------------------------------------===//
32 
33 /// Base class representing the AST of a given expression.
34 class ExpressionAST {
35 public:
36   virtual ~ExpressionAST() = default;
37 
38   /// Evaluates and \returns the value of the expression represented by this
39   /// AST or an error if evaluation fails.
40   virtual Expected<uint64_t> eval() const = 0;
41 };
42 
43 /// Class representing an unsigned literal in the AST of an expression.
44 class ExpressionLiteral : public ExpressionAST {
45 private:
46   /// Actual value of the literal.
47   uint64_t Value;
48 
49 public:
50   /// Constructs a literal with the specified value.
ExpressionLiteral(uint64_t Val)51   ExpressionLiteral(uint64_t Val) : Value(Val) {}
52 
53   /// \returns the literal's value.
eval()54   Expected<uint64_t> eval() const override { return Value; }
55 };
56 
57 /// Class to represent an undefined variable error, which quotes that
58 /// variable's name when printed.
59 class UndefVarError : public ErrorInfo<UndefVarError> {
60 private:
61   StringRef VarName;
62 
63 public:
64   static char ID;
65 
UndefVarError(StringRef VarName)66   UndefVarError(StringRef VarName) : VarName(VarName) {}
67 
getVarName()68   StringRef getVarName() const { return VarName; }
69 
convertToErrorCode()70   std::error_code convertToErrorCode() const override {
71     return inconvertibleErrorCode();
72   }
73 
74   /// Print name of variable associated with this error.
log(raw_ostream & OS)75   void log(raw_ostream &OS) const override {
76     OS << "\"";
77     OS.write_escaped(VarName) << "\"";
78   }
79 };
80 
81 /// Class representing a numeric variable and its associated current value.
82 class NumericVariable {
83 private:
84   /// Name of the numeric variable.
85   StringRef Name;
86 
87   /// Value of numeric variable, if defined, or None otherwise.
88   Optional<uint64_t> Value;
89 
90   /// Line number where this variable is defined, or None if defined before
91   /// input is parsed. Used to determine whether a variable is defined on the
92   /// same line as a given use.
93   Optional<size_t> DefLineNumber;
94 
95 public:
96   /// Constructor for a variable \p Name defined at line \p DefLineNumber or
97   /// defined before input is parsed if \p DefLineNumber is None.
98   explicit NumericVariable(StringRef Name,
99                            Optional<size_t> DefLineNumber = None)
Name(Name)100       : Name(Name), DefLineNumber(DefLineNumber) {}
101 
102   /// \returns name of this numeric variable.
getName()103   StringRef getName() const { return Name; }
104 
105   /// \returns this variable's value.
getValue()106   Optional<uint64_t> getValue() const { return Value; }
107 
108   /// Sets value of this numeric variable to \p NewValue.
setValue(uint64_t NewValue)109   void setValue(uint64_t NewValue) { Value = NewValue; }
110 
111   /// Clears value of this numeric variable, regardless of whether it is
112   /// currently defined or not.
clearValue()113   void clearValue() { Value = None; }
114 
115   /// \returns the line number where this variable is defined, if any, or None
116   /// if defined before input is parsed.
getDefLineNumber()117   Optional<size_t> getDefLineNumber() const { return DefLineNumber; }
118 };
119 
120 /// Class representing the use of a numeric variable in the AST of an
121 /// expression.
122 class NumericVariableUse : public ExpressionAST {
123 private:
124   /// Name of the numeric variable.
125   StringRef Name;
126 
127   /// Pointer to the class instance for the variable this use is about.
128   NumericVariable *Variable;
129 
130 public:
NumericVariableUse(StringRef Name,NumericVariable * Variable)131   NumericVariableUse(StringRef Name, NumericVariable *Variable)
132       : Name(Name), Variable(Variable) {}
133 
134   /// \returns the value of the variable referenced by this instance.
135   Expected<uint64_t> eval() const override;
136 };
137 
138 /// Type of functions evaluating a given binary operation.
139 using binop_eval_t = uint64_t (*)(uint64_t, uint64_t);
140 
141 /// Class representing a single binary operation in the AST of an expression.
142 class BinaryOperation : public ExpressionAST {
143 private:
144   /// Left operand.
145   std::unique_ptr<ExpressionAST> LeftOperand;
146 
147   /// Right operand.
148   std::unique_ptr<ExpressionAST> RightOperand;
149 
150   /// Pointer to function that can evaluate this binary operation.
151   binop_eval_t EvalBinop;
152 
153 public:
BinaryOperation(binop_eval_t EvalBinop,std::unique_ptr<ExpressionAST> LeftOp,std::unique_ptr<ExpressionAST> RightOp)154   BinaryOperation(binop_eval_t EvalBinop, std::unique_ptr<ExpressionAST> LeftOp,
155                   std::unique_ptr<ExpressionAST> RightOp)
156       : EvalBinop(EvalBinop) {
157     LeftOperand = std::move(LeftOp);
158     RightOperand = std::move(RightOp);
159   }
160 
161   /// Evaluates the value of the binary operation represented by this AST,
162   /// using EvalBinop on the result of recursively evaluating the operands.
163   /// \returns the expression value or an error if an undefined numeric
164   /// variable is used in one of the operands.
165   Expected<uint64_t> eval() const override;
166 };
167 
168 class FileCheckPatternContext;
169 
170 /// Class representing a substitution to perform in the RegExStr string.
171 class Substitution {
172 protected:
173   /// Pointer to a class instance holding, among other things, the table with
174   /// the values of live string variables at the start of any given CHECK line.
175   /// Used for substituting string variables with the text they were defined
176   /// as. Expressions are linked to the numeric variables they use at
177   /// parse time and directly access the value of the numeric variable to
178   /// evaluate their value.
179   FileCheckPatternContext *Context;
180 
181   /// The string that needs to be substituted for something else. For a
182   /// string variable this is its name, otherwise this is the whole expression.
183   StringRef FromStr;
184 
185   // Index in RegExStr of where to do the substitution.
186   size_t InsertIdx;
187 
188 public:
Substitution(FileCheckPatternContext * Context,StringRef VarName,size_t InsertIdx)189   Substitution(FileCheckPatternContext *Context, StringRef VarName,
190                size_t InsertIdx)
191       : Context(Context), FromStr(VarName), InsertIdx(InsertIdx) {}
192 
193   virtual ~Substitution() = default;
194 
195   /// \returns the string to be substituted for something else.
getFromString()196   StringRef getFromString() const { return FromStr; }
197 
198   /// \returns the index where the substitution is to be performed in RegExStr.
getIndex()199   size_t getIndex() const { return InsertIdx; }
200 
201   /// \returns a string containing the result of the substitution represented
202   /// by this class instance or an error if substitution failed.
203   virtual Expected<std::string> getResult() const = 0;
204 };
205 
206 class StringSubstitution : public Substitution {
207 public:
StringSubstitution(FileCheckPatternContext * Context,StringRef VarName,size_t InsertIdx)208   StringSubstitution(FileCheckPatternContext *Context, StringRef VarName,
209                      size_t InsertIdx)
210       : Substitution(Context, VarName, InsertIdx) {}
211 
212   /// \returns the text that the string variable in this substitution matched
213   /// when defined, or an error if the variable is undefined.
214   Expected<std::string> getResult() const override;
215 };
216 
217 class NumericSubstitution : public Substitution {
218 private:
219   /// Pointer to the class representing the expression whose value is to be
220   /// substituted.
221   std::unique_ptr<ExpressionAST> ExpressionASTPointer;
222 
223 public:
NumericSubstitution(FileCheckPatternContext * Context,StringRef Expr,std::unique_ptr<ExpressionAST> ExprAST,size_t InsertIdx)224   NumericSubstitution(FileCheckPatternContext *Context, StringRef Expr,
225                       std::unique_ptr<ExpressionAST> ExprAST, size_t InsertIdx)
226       : Substitution(Context, Expr, InsertIdx) {
227     ExpressionASTPointer = std::move(ExprAST);
228   }
229 
230   /// \returns a string containing the result of evaluating the expression in
231   /// this substitution, or an error if evaluation failed.
232   Expected<std::string> getResult() const override;
233 };
234 
235 //===----------------------------------------------------------------------===//
236 // Pattern handling code.
237 //===----------------------------------------------------------------------===//
238 
239 struct FileCheckDiag;
240 
241 /// Class holding the Pattern global state, shared by all patterns: tables
242 /// holding values of variables and whether they are defined or not at any
243 /// given time in the matching process.
244 class FileCheckPatternContext {
245   friend class Pattern;
246 
247 private:
248   /// When matching a given pattern, this holds the value of all the string
249   /// variables defined in previous patterns. In a pattern, only the last
250   /// definition for a given variable is recorded in this table.
251   /// Back-references are used for uses after any the other definition.
252   StringMap<StringRef> GlobalVariableTable;
253 
254   /// Map of all string variables defined so far. Used at parse time to detect
255   /// a name conflict between a numeric variable and a string variable when
256   /// the former is defined on a later line than the latter.
257   StringMap<bool> DefinedVariableTable;
258 
259   /// When matching a given pattern, this holds the pointers to the classes
260   /// representing the numeric variables defined in previous patterns. When
261   /// matching a pattern all definitions for that pattern are recorded in the
262   /// NumericVariableDefs table in the Pattern instance of that pattern.
263   StringMap<NumericVariable *> GlobalNumericVariableTable;
264 
265   /// Pointer to the class instance representing the @LINE pseudo variable for
266   /// easily updating its value.
267   NumericVariable *LineVariable = nullptr;
268 
269   /// Vector holding pointers to all parsed numeric variables. Used to
270   /// automatically free them once they are guaranteed to no longer be used.
271   std::vector<std::unique_ptr<NumericVariable>> NumericVariables;
272 
273   /// Vector holding pointers to all substitutions. Used to automatically free
274   /// them once they are guaranteed to no longer be used.
275   std::vector<std::unique_ptr<Substitution>> Substitutions;
276 
277 public:
278   /// \returns the value of string variable \p VarName or an error if no such
279   /// variable has been defined.
280   Expected<StringRef> getPatternVarValue(StringRef VarName);
281 
282   /// Defines string and numeric variables from definitions given on the
283   /// command line, passed as a vector of [#]VAR=VAL strings in
284   /// \p CmdlineDefines. \returns an error list containing diagnostics against
285   /// \p SM for all definition parsing failures, if any, or Success otherwise.
286   Error defineCmdlineVariables(std::vector<std::string> &CmdlineDefines,
287                                SourceMgr &SM);
288 
289   /// Create @LINE pseudo variable. Value is set when pattern are being
290   /// matched.
291   void createLineVariable();
292 
293   /// Undefines local variables (variables whose name does not start with a '$'
294   /// sign), i.e. removes them from GlobalVariableTable and from
295   /// GlobalNumericVariableTable and also clears the value of numeric
296   /// variables.
297   void clearLocalVars();
298 
299 private:
300   /// Makes a new numeric variable and registers it for destruction when the
301   /// context is destroyed.
302   template <class... Types> NumericVariable *makeNumericVariable(Types... args);
303 
304   /// Makes a new string substitution and registers it for destruction when the
305   /// context is destroyed.
306   Substitution *makeStringSubstitution(StringRef VarName, size_t InsertIdx);
307 
308   /// Makes a new numeric substitution and registers it for destruction when
309   /// the context is destroyed.
310   Substitution *
311   makeNumericSubstitution(StringRef ExpressionStr,
312                           std::unique_ptr<ExpressionAST> ExpressionAST,
313                           size_t InsertIdx);
314 };
315 
316 /// Class to represent an error holding a diagnostic with location information
317 /// used when printing it.
318 class ErrorDiagnostic : public ErrorInfo<ErrorDiagnostic> {
319 private:
320   SMDiagnostic Diagnostic;
321 
322 public:
323   static char ID;
324 
ErrorDiagnostic(SMDiagnostic && Diag)325   ErrorDiagnostic(SMDiagnostic &&Diag) : Diagnostic(Diag) {}
326 
convertToErrorCode()327   std::error_code convertToErrorCode() const override {
328     return inconvertibleErrorCode();
329   }
330 
331   /// Print diagnostic associated with this error when printing the error.
log(raw_ostream & OS)332   void log(raw_ostream &OS) const override { Diagnostic.print(nullptr, OS); }
333 
get(const SourceMgr & SM,SMLoc Loc,const Twine & ErrMsg)334   static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg) {
335     return make_error<ErrorDiagnostic>(
336         SM.GetMessage(Loc, SourceMgr::DK_Error, ErrMsg));
337   }
338 
get(const SourceMgr & SM,StringRef Buffer,const Twine & ErrMsg)339   static Error get(const SourceMgr &SM, StringRef Buffer, const Twine &ErrMsg) {
340     return get(SM, SMLoc::getFromPointer(Buffer.data()), ErrMsg);
341   }
342 };
343 
344 class NotFoundError : public ErrorInfo<NotFoundError> {
345 public:
346   static char ID;
347 
convertToErrorCode()348   std::error_code convertToErrorCode() const override {
349     return inconvertibleErrorCode();
350   }
351 
352   /// Print diagnostic associated with this error when printing the error.
log(raw_ostream & OS)353   void log(raw_ostream &OS) const override {
354     OS << "String not found in input";
355   }
356 };
357 
358 class Pattern {
359   SMLoc PatternLoc;
360 
361   /// A fixed string to match as the pattern or empty if this pattern requires
362   /// a regex match.
363   StringRef FixedStr;
364 
365   /// A regex string to match as the pattern or empty if this pattern requires
366   /// a fixed string to match.
367   std::string RegExStr;
368 
369   /// Entries in this vector represent a substitution of a string variable or
370   /// an expression in the RegExStr regex at match time. For example, in the
371   /// case of a CHECK directive with the pattern "foo[[bar]]baz[[#N+1]]",
372   /// RegExStr will contain "foobaz" and we'll get two entries in this vector
373   /// that tells us to insert the value of string variable "bar" at offset 3
374   /// and the value of expression "N+1" at offset 6.
375   std::vector<Substitution *> Substitutions;
376 
377   /// Maps names of string variables defined in a pattern to the number of
378   /// their parenthesis group in RegExStr capturing their last definition.
379   ///
380   /// E.g. for the pattern "foo[[bar:.*]]baz([[bar]][[QUUX]][[bar:.*]])",
381   /// RegExStr will be "foo(.*)baz(\1<quux value>(.*))" where <quux value> is
382   /// the value captured for QUUX on the earlier line where it was defined, and
383   /// VariableDefs will map "bar" to the third parenthesis group which captures
384   /// the second definition of "bar".
385   ///
386   /// Note: uses std::map rather than StringMap to be able to get the key when
387   /// iterating over values.
388   std::map<StringRef, unsigned> VariableDefs;
389 
390   /// Structure representing the definition of a numeric variable in a pattern.
391   /// It holds the pointer to the class representing the numeric variable whose
392   /// value is being defined and the number of the parenthesis group in
393   /// RegExStr to capture that value.
394   struct NumericVariableMatch {
395     /// Pointer to class representing the numeric variable whose value is being
396     /// defined.
397     NumericVariable *DefinedNumericVariable;
398 
399     /// Number of the parenthesis group in RegExStr that captures the value of
400     /// this numeric variable definition.
401     unsigned CaptureParenGroup;
402   };
403 
404   /// Holds the number of the parenthesis group in RegExStr and pointer to the
405   /// corresponding NumericVariable class instance of all numeric variable
406   /// definitions. Used to set the matched value of all those variables.
407   StringMap<NumericVariableMatch> NumericVariableDefs;
408 
409   /// Pointer to a class instance holding the global state shared by all
410   /// patterns:
411   /// - separate tables with the values of live string and numeric variables
412   ///   respectively at the start of any given CHECK line;
413   /// - table holding whether a string variable has been defined at any given
414   ///   point during the parsing phase.
415   FileCheckPatternContext *Context;
416 
417   Check::FileCheckType CheckTy;
418 
419   /// Line number for this CHECK pattern or None if it is an implicit pattern.
420   /// Used to determine whether a variable definition is made on an earlier
421   /// line to the one with this CHECK.
422   Optional<size_t> LineNumber;
423 
424   /// Ignore case while matching if set to true.
425   bool IgnoreCase = false;
426 
427 public:
428   Pattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,
429           Optional<size_t> Line = None)
Context(Context)430       : Context(Context), CheckTy(Ty), LineNumber(Line) {}
431 
432   /// \returns the location in source code.
getLoc()433   SMLoc getLoc() const { return PatternLoc; }
434 
435   /// \returns the pointer to the global state for all patterns in this
436   /// FileCheck instance.
getContext()437   FileCheckPatternContext *getContext() const { return Context; }
438 
439   /// \returns whether \p C is a valid first character for a variable name.
440   static bool isValidVarNameStart(char C);
441 
442   /// Parsing information about a variable.
443   struct VariableProperties {
444     StringRef Name;
445     bool IsPseudo;
446   };
447 
448   /// Parses the string at the start of \p Str for a variable name. \returns
449   /// a VariableProperties structure holding the variable name and whether it
450   /// is the name of a pseudo variable, or an error holding a diagnostic
451   /// against \p SM if parsing fail. If parsing was successful, also strips
452   /// \p Str from the variable name.
453   static Expected<VariableProperties> parseVariable(StringRef &Str,
454                                                     const SourceMgr &SM);
455   /// Parses \p Expr for a numeric substitution block at line \p LineNumber,
456   /// or before input is parsed if \p LineNumber is None. Parameter
457   /// \p IsLegacyLineExpr indicates whether \p Expr should be a legacy @LINE
458   /// expression and \p Context points to the class instance holding the live
459   /// string and numeric variables. \returns a pointer to the class instance
460   /// representing the AST of the expression whose value must be substitued, or
461   /// an error holding a diagnostic against \p SM if parsing fails. If
462   /// substitution was successful, sets \p DefinedNumericVariable to point to
463   /// the class representing the numeric variable defined in this numeric
464   /// substitution block, or None if this block does not define any variable.
465   static Expected<std::unique_ptr<ExpressionAST>> parseNumericSubstitutionBlock(
466       StringRef Expr, Optional<NumericVariable *> &DefinedNumericVariable,
467       bool IsLegacyLineExpr, Optional<size_t> LineNumber,
468       FileCheckPatternContext *Context, const SourceMgr &SM);
469   /// Parses the pattern in \p PatternStr and initializes this Pattern instance
470   /// accordingly.
471   ///
472   /// \p Prefix provides which prefix is being matched, \p Req describes the
473   /// global options that influence the parsing such as whitespace
474   /// canonicalization, \p SM provides the SourceMgr used for error reports.
475   /// \returns true in case of an error, false otherwise.
476   bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM,
477                     const FileCheckRequest &Req);
478   /// Matches the pattern string against the input buffer \p Buffer
479   ///
480   /// \returns the position that is matched or an error indicating why matching
481   /// failed. If there is a match, updates \p MatchLen with the size of the
482   /// matched string.
483   ///
484   /// The GlobalVariableTable StringMap in the FileCheckPatternContext class
485   /// instance provides the current values of FileCheck string variables and is
486   /// updated if this match defines new values. Likewise, the
487   /// GlobalNumericVariableTable StringMap in the same class provides the
488   /// current values of FileCheck numeric variables and is updated if this
489   /// match defines new numeric values.
490   Expected<size_t> match(StringRef Buffer, size_t &MatchLen,
491                          const SourceMgr &SM) const;
492   /// Prints the value of successful substitutions or the name of the undefined
493   /// string or numeric variables preventing a successful substitution.
494   void printSubstitutions(const SourceMgr &SM, StringRef Buffer,
495                           SMRange MatchRange = None) const;
496   void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer,
497                        std::vector<FileCheckDiag> *Diags) const;
498 
hasVariable()499   bool hasVariable() const {
500     return !(Substitutions.empty() && VariableDefs.empty());
501   }
502 
getCheckTy()503   Check::FileCheckType getCheckTy() const { return CheckTy; }
504 
getCount()505   int getCount() const { return CheckTy.getCount(); }
506 
507 private:
508   bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
509   void AddBackrefToRegEx(unsigned BackrefNum);
510   /// Computes an arbitrary estimate for the quality of matching this pattern
511   /// at the start of \p Buffer; a distance of zero should correspond to a
512   /// perfect match.
513   unsigned computeMatchDistance(StringRef Buffer) const;
514   /// Finds the closing sequence of a regex variable usage or definition.
515   ///
516   /// \p Str has to point in the beginning of the definition (right after the
517   /// opening sequence). \p SM holds the SourceMgr used for error reporting.
518   ///  \returns the offset of the closing sequence within Str, or npos if it
519   /// was not found.
520   static size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);
521 
522   /// Parses \p Expr for the name of a numeric variable to be defined at line
523   /// \p LineNumber, or before input is parsed if \p LineNumber is None.
524   /// \returns a pointer to the class instance representing that variable,
525   /// creating it if needed, or an error holding a diagnostic against \p SM
526   /// should defining such a variable be invalid.
527   static Expected<NumericVariable *> parseNumericVariableDefinition(
528       StringRef &Expr, FileCheckPatternContext *Context,
529       Optional<size_t> LineNumber, const SourceMgr &SM);
530   /// Parses \p Name as a (pseudo if \p IsPseudo is true) numeric variable use
531   /// at line \p LineNumber, or before input is parsed if \p LineNumber is
532   /// None. Parameter \p Context points to the class instance holding the live
533   /// string and numeric variables. \returns the pointer to the class instance
534   /// representing that variable if successful, or an error holding a
535   /// diagnostic against \p SM otherwise.
536   static Expected<std::unique_ptr<NumericVariableUse>> parseNumericVariableUse(
537       StringRef Name, bool IsPseudo, Optional<size_t> LineNumber,
538       FileCheckPatternContext *Context, const SourceMgr &SM);
539   enum class AllowedOperand { LineVar, Literal, Any };
540   /// Parses \p Expr for use of a numeric operand at line \p LineNumber, or
541   /// before input is parsed if \p LineNumber is None. Accepts both literal
542   /// values and numeric variables, depending on the value of \p AO. Parameter
543   /// \p Context points to the class instance holding the live string and
544   /// numeric variables. \returns the class representing that operand in the
545   /// AST of the expression or an error holding a diagnostic against \p SM
546   /// otherwise.
547   static Expected<std::unique_ptr<ExpressionAST>>
548   parseNumericOperand(StringRef &Expr, AllowedOperand AO,
549                       Optional<size_t> LineNumber,
550                       FileCheckPatternContext *Context, const SourceMgr &SM);
551   /// Parses \p Expr for a binary operation at line \p LineNumber, or before
552   /// input is parsed if \p LineNumber is None. The left operand of this binary
553   /// operation is given in \p LeftOp and \p IsLegacyLineExpr indicates whether
554   /// we are parsing a legacy @LINE expression. Parameter \p Context points to
555   /// the class instance holding the live string and numeric variables.
556   /// \returns the class representing the binary operation in the AST of the
557   /// expression, or an error holding a diagnostic against \p SM otherwise.
558   static Expected<std::unique_ptr<ExpressionAST>>
559   parseBinop(StringRef &Expr, std::unique_ptr<ExpressionAST> LeftOp,
560              bool IsLegacyLineExpr, Optional<size_t> LineNumber,
561              FileCheckPatternContext *Context, const SourceMgr &SM);
562 };
563 
564 //===----------------------------------------------------------------------===//
565 // Check Strings.
566 //===----------------------------------------------------------------------===//
567 
568 /// A check that we found in the input file.
569 struct FileCheckString {
570   /// The pattern to match.
571   Pattern Pat;
572 
573   /// Which prefix name this check matched.
574   StringRef Prefix;
575 
576   /// The location in the match file that the check string was specified.
577   SMLoc Loc;
578 
579   /// All of the strings that are disallowed from occurring between this match
580   /// string and the previous one (or start of file).
581   std::vector<Pattern> DagNotStrings;
582 
FileCheckStringFileCheckString583   FileCheckString(const Pattern &P, StringRef S, SMLoc L)
584       : Pat(P), Prefix(S), Loc(L) {}
585 
586   /// Matches check string and its "not strings" and/or "dag strings".
587   size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,
588                size_t &MatchLen, FileCheckRequest &Req,
589                std::vector<FileCheckDiag> *Diags) const;
590 
591   /// Verifies that there is a single line in the given \p Buffer. Errors are
592   /// reported against \p SM.
593   bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
594   /// Verifies that there is no newline in the given \p Buffer. Errors are
595   /// reported against \p SM.
596   bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
597   /// Verifies that none of the strings in \p NotStrings are found in the given
598   /// \p Buffer. Errors are reported against \p SM and diagnostics recorded in
599   /// \p Diags according to the verbosity level set in \p Req.
600   bool CheckNot(const SourceMgr &SM, StringRef Buffer,
601                 const std::vector<const Pattern *> &NotStrings,
602                 const FileCheckRequest &Req,
603                 std::vector<FileCheckDiag> *Diags) const;
604   /// Matches "dag strings" and their mixed "not strings".
605   size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
606                   std::vector<const Pattern *> &NotStrings,
607                   const FileCheckRequest &Req,
608                   std::vector<FileCheckDiag> *Diags) const;
609 };
610 
611 } // namespace llvm
612 
613 #endif
614