xref: /freebsd/contrib/llvm-project/llvm/lib/FileCheck/FileCheckImpl.h (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
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_FILECHECK_FILECHECKIMPL_H
16 #define LLVM_LIB_FILECHECK_FILECHECKIMPL_H
17 
18 #include "llvm/ADT/APInt.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/FileCheck/FileCheck.h"
22 #include "llvm/Support/Error.h"
23 #include "llvm/Support/SourceMgr.h"
24 #include <map>
25 #include <optional>
26 #include <string>
27 #include <vector>
28 
29 namespace llvm {
30 
31 //===----------------------------------------------------------------------===//
32 // Numeric substitution handling code.
33 //===----------------------------------------------------------------------===//
34 
35 class ExpressionValue;
36 
37 /// Type representing the format an expression value should be textualized into
38 /// for matching. Used to represent both explicit format specifiers as well as
39 /// implicit format from using numeric variables.
40 struct ExpressionFormat {
41   enum class Kind {
42     /// Denote absence of format. Used for implicit format of literals and
43     /// empty expressions.
44     NoFormat,
45     /// Value is an unsigned integer and should be printed as a decimal number.
46     Unsigned,
47     /// Value is a signed integer and should be printed as a decimal number.
48     Signed,
49     /// Value should be printed as an uppercase hex number.
50     HexUpper,
51     /// Value should be printed as a lowercase hex number.
52     HexLower
53   };
54 
55 private:
56   Kind Value;
57   unsigned Precision = 0;
58   /// printf-like "alternate form" selected.
59   bool AlternateForm = false;
60 
61 public:
62   /// Evaluates a format to true if it can be used in a match.
63   explicit operator bool() const { return Value != Kind::NoFormat; }
64 
65   /// Define format equality: formats are equal if neither is NoFormat and
66   /// their kinds and precision are the same.
67   bool operator==(const ExpressionFormat &Other) const {
68     return Value != Kind::NoFormat && Value == Other.Value &&
69            Precision == Other.Precision && AlternateForm == Other.AlternateForm;
70   }
71 
72   bool operator!=(const ExpressionFormat &Other) const {
73     return !(*this == Other);
74   }
75 
76   bool operator==(Kind OtherValue) const { return Value == OtherValue; }
77 
78   bool operator!=(Kind OtherValue) const { return !(*this == OtherValue); }
79 
80   /// \returns the format specifier corresponding to this format as a string.
81   StringRef toString() const;
82 
83   ExpressionFormat() : Value(Kind::NoFormat){};
84   explicit ExpressionFormat(Kind Value) : Value(Value), Precision(0){};
85   explicit ExpressionFormat(Kind Value, unsigned Precision)
86       : Value(Value), Precision(Precision){};
87   explicit ExpressionFormat(Kind Value, unsigned Precision, bool AlternateForm)
88       : Value(Value), Precision(Precision), AlternateForm(AlternateForm){};
89 
90   /// \returns a wildcard regular expression string that matches any value in
91   /// the format represented by this instance and no other value, or an error
92   /// if the format is NoFormat.
93   Expected<std::string> getWildcardRegex() const;
94 
95   /// \returns the string representation of \p Value in the format represented
96   /// by this instance, or an error if conversion to this format failed or the
97   /// format is NoFormat.
98   Expected<std::string> getMatchingString(ExpressionValue Value) const;
99 
100   /// \returns the value corresponding to string representation \p StrVal
101   /// according to the matching format represented by this instance or an error
102   /// with diagnostic against \p SM if \p StrVal does not correspond to a valid
103   /// and representable value.
104   Expected<ExpressionValue> valueFromStringRepr(StringRef StrVal,
105                                                 const SourceMgr &SM) const;
106 };
107 
108 /// Class to represent an overflow error that might result when manipulating a
109 /// value.
110 class OverflowError : public ErrorInfo<OverflowError> {
111 public:
112   static char ID;
113 
114   std::error_code convertToErrorCode() const override {
115     return std::make_error_code(std::errc::value_too_large);
116   }
117 
118   void log(raw_ostream &OS) const override { OS << "overflow error"; }
119 };
120 
121 /// Class representing a numeric value.
122 class ExpressionValue {
123 private:
124   APInt Value;
125 
126 public:
127   // Store signed and unsigned 64-bit integers in a signed 65-bit APInt.
128   template <class T>
129   explicit ExpressionValue(T Val) : Value(65, Val, /*isSigned=*/Val < 0) {}
130 
131   APInt getAPIntValue() const { return Value; }
132 };
133 
134 /// Performs operation and \returns its result or an error in case of failure,
135 /// such as if an overflow occurs.
136 Expected<ExpressionValue> operator+(const ExpressionValue &Lhs,
137                                     const ExpressionValue &Rhs);
138 Expected<ExpressionValue> operator-(const ExpressionValue &Lhs,
139                                     const ExpressionValue &Rhs);
140 Expected<ExpressionValue> operator*(const ExpressionValue &Lhs,
141                                     const ExpressionValue &Rhs);
142 Expected<ExpressionValue> operator/(const ExpressionValue &Lhs,
143                                     const ExpressionValue &Rhs);
144 Expected<ExpressionValue> max(const ExpressionValue &Lhs,
145                               const ExpressionValue &Rhs);
146 Expected<ExpressionValue> min(const ExpressionValue &Lhs,
147                               const ExpressionValue &Rhs);
148 
149 /// Base class representing the AST of a given expression.
150 class ExpressionAST {
151 private:
152   StringRef ExpressionStr;
153 
154 public:
155   ExpressionAST(StringRef ExpressionStr) : ExpressionStr(ExpressionStr) {}
156 
157   virtual ~ExpressionAST() = default;
158 
159   StringRef getExpressionStr() const { return ExpressionStr; }
160 
161   /// Evaluates and \returns the value of the expression represented by this
162   /// AST or an error if evaluation fails.
163   virtual Expected<ExpressionValue> eval() const = 0;
164 
165   /// \returns either the implicit format of this AST, a diagnostic against
166   /// \p SM if implicit formats of the AST's components conflict, or NoFormat
167   /// if the AST has no implicit format (e.g. AST is made up of a single
168   /// literal).
169   virtual Expected<ExpressionFormat>
170   getImplicitFormat(const SourceMgr &SM) const {
171     return ExpressionFormat();
172   }
173 };
174 
175 /// Class representing an unsigned literal in the AST of an expression.
176 class ExpressionLiteral : public ExpressionAST {
177 private:
178   /// Actual value of the literal.
179   ExpressionValue Value;
180 
181 public:
182   template <class T>
183   explicit ExpressionLiteral(StringRef ExpressionStr, T Val)
184       : ExpressionAST(ExpressionStr), Value(Val) {}
185 
186   /// \returns the literal's value.
187   Expected<ExpressionValue> eval() const override { return Value; }
188 };
189 
190 /// Class to represent an undefined variable error, which quotes that
191 /// variable's name when printed.
192 class UndefVarError : public ErrorInfo<UndefVarError> {
193 private:
194   StringRef VarName;
195 
196 public:
197   static char ID;
198 
199   UndefVarError(StringRef VarName) : VarName(VarName) {}
200 
201   StringRef getVarName() const { return VarName; }
202 
203   std::error_code convertToErrorCode() const override {
204     return inconvertibleErrorCode();
205   }
206 
207   /// Print name of variable associated with this error.
208   void log(raw_ostream &OS) const override {
209     OS << "undefined variable: " << VarName;
210   }
211 };
212 
213 /// Class representing an expression and its matching format.
214 class Expression {
215 private:
216   /// Pointer to AST of the expression.
217   std::unique_ptr<ExpressionAST> AST;
218 
219   /// Format to use (e.g. hex upper case letters) when matching the value.
220   ExpressionFormat Format;
221 
222 public:
223   /// Generic constructor for an expression represented by the given \p AST and
224   /// whose matching format is \p Format.
225   Expression(std::unique_ptr<ExpressionAST> AST, ExpressionFormat Format)
226       : AST(std::move(AST)), Format(Format) {}
227 
228   /// \returns pointer to AST of the expression. Pointer is guaranteed to be
229   /// valid as long as this object is.
230   ExpressionAST *getAST() const { return AST.get(); }
231 
232   ExpressionFormat getFormat() const { return Format; }
233 };
234 
235 /// Class representing a numeric variable and its associated current value.
236 class NumericVariable {
237 private:
238   /// Name of the numeric variable.
239   StringRef Name;
240 
241   /// Format to use for expressions using this variable without an explicit
242   /// format.
243   ExpressionFormat ImplicitFormat;
244 
245   /// Value of numeric variable, if defined, or std::nullopt otherwise.
246   std::optional<ExpressionValue> Value;
247 
248   /// The input buffer's string from which Value was parsed, or std::nullopt.
249   /// See comments on getStringValue for a discussion of the std::nullopt case.
250   std::optional<StringRef> StrValue;
251 
252   /// Line number where this variable is defined, or std::nullopt if defined
253   /// before input is parsed. Used to determine whether a variable is defined on
254   /// the same line as a given use.
255   std::optional<size_t> DefLineNumber;
256 
257 public:
258   /// Constructor for a variable \p Name with implicit format \p ImplicitFormat
259   /// defined at line \p DefLineNumber or defined before input is parsed if
260   /// \p DefLineNumber is std::nullopt.
261   explicit NumericVariable(StringRef Name, ExpressionFormat ImplicitFormat,
262                            std::optional<size_t> DefLineNumber = std::nullopt)
263       : Name(Name), ImplicitFormat(ImplicitFormat),
264         DefLineNumber(DefLineNumber) {}
265 
266   /// \returns name of this numeric variable.
267   StringRef getName() const { return Name; }
268 
269   /// \returns implicit format of this numeric variable.
270   ExpressionFormat getImplicitFormat() const { return ImplicitFormat; }
271 
272   /// \returns this variable's value.
273   std::optional<ExpressionValue> getValue() const { return Value; }
274 
275   /// \returns the input buffer's string from which this variable's value was
276   /// parsed, or std::nullopt if the value is not yet defined or was not parsed
277   /// from the input buffer.  For example, the value of @LINE is not parsed from
278   /// the input buffer, and some numeric variables are parsed from the command
279   /// line instead.
280   std::optional<StringRef> getStringValue() const { return StrValue; }
281 
282   /// Sets value of this numeric variable to \p NewValue, and sets the input
283   /// buffer string from which it was parsed to \p NewStrValue.  See comments on
284   /// getStringValue for a discussion of when the latter can be std::nullopt.
285   void setValue(ExpressionValue NewValue,
286                 std::optional<StringRef> NewStrValue = std::nullopt) {
287     Value = NewValue;
288     StrValue = NewStrValue;
289   }
290 
291   /// Clears value of this numeric variable, regardless of whether it is
292   /// currently defined or not.
293   void clearValue() {
294     Value = std::nullopt;
295     StrValue = std::nullopt;
296   }
297 
298   /// \returns the line number where this variable is defined, if any, or
299   /// std::nullopt if defined before input is parsed.
300   std::optional<size_t> getDefLineNumber() const { return DefLineNumber; }
301 };
302 
303 /// Class representing the use of a numeric variable in the AST of an
304 /// expression.
305 class NumericVariableUse : public ExpressionAST {
306 private:
307   /// Pointer to the class instance for the variable this use is about.
308   NumericVariable *Variable;
309 
310 public:
311   NumericVariableUse(StringRef Name, NumericVariable *Variable)
312       : ExpressionAST(Name), Variable(Variable) {}
313   /// \returns the value of the variable referenced by this instance.
314   Expected<ExpressionValue> eval() const override;
315 
316   /// \returns implicit format of this numeric variable.
317   Expected<ExpressionFormat>
318   getImplicitFormat(const SourceMgr &SM) const override {
319     return Variable->getImplicitFormat();
320   }
321 };
322 
323 /// Type of functions evaluating a given binary operation.
324 using binop_eval_t = Expected<ExpressionValue> (*)(const ExpressionValue &,
325                                                    const ExpressionValue &);
326 
327 /// Class representing a single binary operation in the AST of an expression.
328 class BinaryOperation : public ExpressionAST {
329 private:
330   /// Left operand.
331   std::unique_ptr<ExpressionAST> LeftOperand;
332 
333   /// Right operand.
334   std::unique_ptr<ExpressionAST> RightOperand;
335 
336   /// Pointer to function that can evaluate this binary operation.
337   binop_eval_t EvalBinop;
338 
339 public:
340   BinaryOperation(StringRef ExpressionStr, binop_eval_t EvalBinop,
341                   std::unique_ptr<ExpressionAST> LeftOp,
342                   std::unique_ptr<ExpressionAST> RightOp)
343       : ExpressionAST(ExpressionStr), EvalBinop(EvalBinop) {
344     LeftOperand = std::move(LeftOp);
345     RightOperand = std::move(RightOp);
346   }
347 
348   /// Evaluates the value of the binary operation represented by this AST,
349   /// using EvalBinop on the result of recursively evaluating the operands.
350   /// \returns the expression value or an error if an undefined numeric
351   /// variable is used in one of the operands.
352   Expected<ExpressionValue> eval() const override;
353 
354   /// \returns the implicit format of this AST, if any, a diagnostic against
355   /// \p SM if the implicit formats of the AST's components conflict, or no
356   /// format if the AST has no implicit format (e.g. AST is made of a single
357   /// literal).
358   Expected<ExpressionFormat>
359   getImplicitFormat(const SourceMgr &SM) const override;
360 };
361 
362 class FileCheckPatternContext;
363 
364 /// Class representing a substitution to perform in the RegExStr string.
365 class Substitution {
366 protected:
367   /// Pointer to a class instance holding, among other things, the table with
368   /// the values of live string variables at the start of any given CHECK line.
369   /// Used for substituting string variables with the text they were defined
370   /// as. Expressions are linked to the numeric variables they use at
371   /// parse time and directly access the value of the numeric variable to
372   /// evaluate their value.
373   FileCheckPatternContext *Context;
374 
375   /// The string that needs to be substituted for something else. For a
376   /// string variable this is its name, otherwise this is the whole expression.
377   StringRef FromStr;
378 
379   // Index in RegExStr of where to do the substitution.
380   size_t InsertIdx;
381 
382 public:
383   Substitution(FileCheckPatternContext *Context, StringRef VarName,
384                size_t InsertIdx)
385       : Context(Context), FromStr(VarName), InsertIdx(InsertIdx) {}
386 
387   virtual ~Substitution() = default;
388 
389   /// \returns the string to be substituted for something else.
390   StringRef getFromString() const { return FromStr; }
391 
392   /// \returns the index where the substitution is to be performed in RegExStr.
393   size_t getIndex() const { return InsertIdx; }
394 
395   /// \returns a string containing the result of the substitution represented
396   /// by this class instance or an error if substitution failed.
397   virtual Expected<std::string> getResult() const = 0;
398 };
399 
400 class StringSubstitution : public Substitution {
401 public:
402   StringSubstitution(FileCheckPatternContext *Context, StringRef VarName,
403                      size_t InsertIdx)
404       : Substitution(Context, VarName, InsertIdx) {}
405 
406   /// \returns the text that the string variable in this substitution matched
407   /// when defined, or an error if the variable is undefined.
408   Expected<std::string> getResult() const override;
409 };
410 
411 class NumericSubstitution : public Substitution {
412 private:
413   /// Pointer to the class representing the expression whose value is to be
414   /// substituted.
415   std::unique_ptr<Expression> ExpressionPointer;
416 
417 public:
418   NumericSubstitution(FileCheckPatternContext *Context, StringRef ExpressionStr,
419                       std::unique_ptr<Expression> ExpressionPointer,
420                       size_t InsertIdx)
421       : Substitution(Context, ExpressionStr, InsertIdx),
422         ExpressionPointer(std::move(ExpressionPointer)) {}
423 
424   /// \returns a string containing the result of evaluating the expression in
425   /// this substitution, or an error if evaluation failed.
426   Expected<std::string> getResult() const override;
427 };
428 
429 //===----------------------------------------------------------------------===//
430 // Pattern handling code.
431 //===----------------------------------------------------------------------===//
432 
433 /// Class holding the Pattern global state, shared by all patterns: tables
434 /// holding values of variables and whether they are defined or not at any
435 /// given time in the matching process.
436 class FileCheckPatternContext {
437   friend class Pattern;
438 
439 private:
440   /// When matching a given pattern, this holds the value of all the string
441   /// variables defined in previous patterns. In a pattern, only the last
442   /// definition for a given variable is recorded in this table.
443   /// Back-references are used for uses after any the other definition.
444   StringMap<StringRef> GlobalVariableTable;
445 
446   /// Map of all string variables defined so far. Used at parse time to detect
447   /// a name conflict between a numeric variable and a string variable when
448   /// the former is defined on a later line than the latter.
449   StringMap<bool> DefinedVariableTable;
450 
451   /// When matching a given pattern, this holds the pointers to the classes
452   /// representing the numeric variables defined in previous patterns. When
453   /// matching a pattern all definitions for that pattern are recorded in the
454   /// NumericVariableDefs table in the Pattern instance of that pattern.
455   StringMap<NumericVariable *> GlobalNumericVariableTable;
456 
457   /// Pointer to the class instance representing the @LINE pseudo variable for
458   /// easily updating its value.
459   NumericVariable *LineVariable = nullptr;
460 
461   /// Vector holding pointers to all parsed numeric variables. Used to
462   /// automatically free them once they are guaranteed to no longer be used.
463   std::vector<std::unique_ptr<NumericVariable>> NumericVariables;
464 
465   /// Vector holding pointers to all parsed expressions. Used to automatically
466   /// free the expressions once they are guaranteed to no longer be used.
467   std::vector<std::unique_ptr<Expression>> Expressions;
468 
469   /// Vector holding pointers to all substitutions. Used to automatically free
470   /// them once they are guaranteed to no longer be used.
471   std::vector<std::unique_ptr<Substitution>> Substitutions;
472 
473 public:
474   /// \returns the value of string variable \p VarName or an error if no such
475   /// variable has been defined.
476   Expected<StringRef> getPatternVarValue(StringRef VarName);
477 
478   /// Defines string and numeric variables from definitions given on the
479   /// command line, passed as a vector of [#]VAR=VAL strings in
480   /// \p CmdlineDefines. \returns an error list containing diagnostics against
481   /// \p SM for all definition parsing failures, if any, or Success otherwise.
482   Error defineCmdlineVariables(ArrayRef<StringRef> CmdlineDefines,
483                                SourceMgr &SM);
484 
485   /// Create @LINE pseudo variable. Value is set when pattern are being
486   /// matched.
487   void createLineVariable();
488 
489   /// Undefines local variables (variables whose name does not start with a '$'
490   /// sign), i.e. removes them from GlobalVariableTable and from
491   /// GlobalNumericVariableTable and also clears the value of numeric
492   /// variables.
493   void clearLocalVars();
494 
495 private:
496   /// Makes a new numeric variable and registers it for destruction when the
497   /// context is destroyed.
498   template <class... Types> NumericVariable *makeNumericVariable(Types... args);
499 
500   /// Makes a new string substitution and registers it for destruction when the
501   /// context is destroyed.
502   Substitution *makeStringSubstitution(StringRef VarName, size_t InsertIdx);
503 
504   /// Makes a new numeric substitution and registers it for destruction when
505   /// the context is destroyed.
506   Substitution *makeNumericSubstitution(StringRef ExpressionStr,
507                                         std::unique_ptr<Expression> Expression,
508                                         size_t InsertIdx);
509 };
510 
511 /// Class to represent an error holding a diagnostic with location information
512 /// used when printing it.
513 class ErrorDiagnostic : public ErrorInfo<ErrorDiagnostic> {
514 private:
515   SMDiagnostic Diagnostic;
516   SMRange Range;
517 
518 public:
519   static char ID;
520 
521   ErrorDiagnostic(SMDiagnostic &&Diag, SMRange Range)
522       : Diagnostic(Diag), Range(Range) {}
523 
524   std::error_code convertToErrorCode() const override {
525     return inconvertibleErrorCode();
526   }
527 
528   /// Print diagnostic associated with this error when printing the error.
529   void log(raw_ostream &OS) const override { Diagnostic.print(nullptr, OS); }
530 
531   StringRef getMessage() const { return Diagnostic.getMessage(); }
532   SMRange getRange() const { return Range; }
533 
534   static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg,
535                    SMRange Range = std::nullopt) {
536     return make_error<ErrorDiagnostic>(
537         SM.GetMessage(Loc, SourceMgr::DK_Error, ErrMsg), Range);
538   }
539 
540   static Error get(const SourceMgr &SM, StringRef Buffer, const Twine &ErrMsg) {
541     SMLoc Start = SMLoc::getFromPointer(Buffer.data());
542     SMLoc End = SMLoc::getFromPointer(Buffer.data() + Buffer.size());
543     return get(SM, Start, ErrMsg, SMRange(Start, End));
544   }
545 };
546 
547 class NotFoundError : public ErrorInfo<NotFoundError> {
548 public:
549   static char ID;
550 
551   std::error_code convertToErrorCode() const override {
552     return inconvertibleErrorCode();
553   }
554 
555   /// Print diagnostic associated with this error when printing the error.
556   void log(raw_ostream &OS) const override {
557     OS << "String not found in input";
558   }
559 };
560 
561 /// An error that has already been reported.
562 ///
563 /// This class is designed to support a function whose callers may need to know
564 /// whether the function encountered and reported an error but never need to
565 /// know the nature of that error.  For example, the function has a return type
566 /// of \c Error and always returns either \c ErrorReported or \c ErrorSuccess.
567 /// That interface is similar to that of a function returning bool to indicate
568 /// an error except, in the former case, (1) there is no confusion over polarity
569 /// and (2) the caller must either check the result or explicitly ignore it with
570 /// a call like \c consumeError.
571 class ErrorReported final : public ErrorInfo<ErrorReported> {
572 public:
573   static char ID;
574 
575   std::error_code convertToErrorCode() const override {
576     return inconvertibleErrorCode();
577   }
578 
579   /// Print diagnostic associated with this error when printing the error.
580   void log(raw_ostream &OS) const override {
581     OS << "error previously reported";
582   }
583 
584   static inline Error reportedOrSuccess(bool HasErrorReported) {
585     if (HasErrorReported)
586       return make_error<ErrorReported>();
587     return Error::success();
588   }
589 };
590 
591 class Pattern {
592   SMLoc PatternLoc;
593 
594   /// A fixed string to match as the pattern or empty if this pattern requires
595   /// a regex match.
596   StringRef FixedStr;
597 
598   /// A regex string to match as the pattern or empty if this pattern requires
599   /// a fixed string to match.
600   std::string RegExStr;
601 
602   /// Entries in this vector represent a substitution of a string variable or
603   /// an expression in the RegExStr regex at match time. For example, in the
604   /// case of a CHECK directive with the pattern "foo[[bar]]baz[[#N+1]]",
605   /// RegExStr will contain "foobaz" and we'll get two entries in this vector
606   /// that tells us to insert the value of string variable "bar" at offset 3
607   /// and the value of expression "N+1" at offset 6.
608   std::vector<Substitution *> Substitutions;
609 
610   /// Maps names of string variables defined in a pattern to the number of
611   /// their parenthesis group in RegExStr capturing their last definition.
612   ///
613   /// E.g. for the pattern "foo[[bar:.*]]baz([[bar]][[QUUX]][[bar:.*]])",
614   /// RegExStr will be "foo(.*)baz(\1<quux value>(.*))" where <quux value> is
615   /// the value captured for QUUX on the earlier line where it was defined, and
616   /// VariableDefs will map "bar" to the third parenthesis group which captures
617   /// the second definition of "bar".
618   ///
619   /// Note: uses std::map rather than StringMap to be able to get the key when
620   /// iterating over values.
621   std::map<StringRef, unsigned> VariableDefs;
622 
623   /// Structure representing the definition of a numeric variable in a pattern.
624   /// It holds the pointer to the class instance holding the value and matching
625   /// format of the numeric variable whose value is being defined and the
626   /// number of the parenthesis group in RegExStr to capture that value.
627   struct NumericVariableMatch {
628     /// Pointer to class instance holding the value and matching format of the
629     /// numeric variable being defined.
630     NumericVariable *DefinedNumericVariable;
631 
632     /// Number of the parenthesis group in RegExStr that captures the value of
633     /// this numeric variable definition.
634     unsigned CaptureParenGroup;
635   };
636 
637   /// Holds the number of the parenthesis group in RegExStr and pointer to the
638   /// corresponding NumericVariable class instance of all numeric variable
639   /// definitions. Used to set the matched value of all those variables.
640   StringMap<NumericVariableMatch> NumericVariableDefs;
641 
642   /// Pointer to a class instance holding the global state shared by all
643   /// patterns:
644   /// - separate tables with the values of live string and numeric variables
645   ///   respectively at the start of any given CHECK line;
646   /// - table holding whether a string variable has been defined at any given
647   ///   point during the parsing phase.
648   FileCheckPatternContext *Context;
649 
650   Check::FileCheckType CheckTy;
651 
652   /// Line number for this CHECK pattern or std::nullopt if it is an implicit
653   /// pattern. Used to determine whether a variable definition is made on an
654   /// earlier line to the one with this CHECK.
655   std::optional<size_t> LineNumber;
656 
657   /// Ignore case while matching if set to true.
658   bool IgnoreCase = false;
659 
660 public:
661   Pattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,
662           std::optional<size_t> Line = std::nullopt)
663       : Context(Context), CheckTy(Ty), LineNumber(Line) {}
664 
665   /// \returns the location in source code.
666   SMLoc getLoc() const { return PatternLoc; }
667 
668   /// \returns the pointer to the global state for all patterns in this
669   /// FileCheck instance.
670   FileCheckPatternContext *getContext() const { return Context; }
671 
672   /// \returns whether \p C is a valid first character for a variable name.
673   static bool isValidVarNameStart(char C);
674 
675   /// Parsing information about a variable.
676   struct VariableProperties {
677     StringRef Name;
678     bool IsPseudo;
679   };
680 
681   /// Parses the string at the start of \p Str for a variable name. \returns
682   /// a VariableProperties structure holding the variable name and whether it
683   /// is the name of a pseudo variable, or an error holding a diagnostic
684   /// against \p SM if parsing fail. If parsing was successful, also strips
685   /// \p Str from the variable name.
686   static Expected<VariableProperties> parseVariable(StringRef &Str,
687                                                     const SourceMgr &SM);
688   /// Parses \p Expr for a numeric substitution block at line \p LineNumber,
689   /// or before input is parsed if \p LineNumber is None. Parameter
690   /// \p IsLegacyLineExpr indicates whether \p Expr should be a legacy @LINE
691   /// expression and \p Context points to the class instance holding the live
692   /// string and numeric variables. \returns a pointer to the class instance
693   /// representing the expression whose value must be substitued, or an error
694   /// holding a diagnostic against \p SM if parsing fails. If substitution was
695   /// successful, sets \p DefinedNumericVariable to point to the class
696   /// representing the numeric variable defined in this numeric substitution
697   /// block, or std::nullopt if this block does not define any variable.
698   static Expected<std::unique_ptr<Expression>> parseNumericSubstitutionBlock(
699       StringRef Expr, std::optional<NumericVariable *> &DefinedNumericVariable,
700       bool IsLegacyLineExpr, std::optional<size_t> LineNumber,
701       FileCheckPatternContext *Context, const SourceMgr &SM);
702   /// Parses the pattern in \p PatternStr and initializes this Pattern instance
703   /// accordingly.
704   ///
705   /// \p Prefix provides which prefix is being matched, \p Req describes the
706   /// global options that influence the parsing such as whitespace
707   /// canonicalization, \p SM provides the SourceMgr used for error reports.
708   /// \returns true in case of an error, false otherwise.
709   bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM,
710                     const FileCheckRequest &Req);
711   struct Match {
712     size_t Pos;
713     size_t Len;
714   };
715   struct MatchResult {
716     std::optional<Match> TheMatch;
717     Error TheError;
718     MatchResult(size_t MatchPos, size_t MatchLen, Error E)
719         : TheMatch(Match{MatchPos, MatchLen}), TheError(std::move(E)) {}
720     MatchResult(Match M, Error E) : TheMatch(M), TheError(std::move(E)) {}
721     MatchResult(Error E) : TheError(std::move(E)) {}
722   };
723   /// Matches the pattern string against the input buffer \p Buffer.
724   ///
725   /// \returns either (1) an error resulting in no match or (2) a match possibly
726   /// with an error encountered while processing the match.
727   ///
728   /// The GlobalVariableTable StringMap in the FileCheckPatternContext class
729   /// instance provides the current values of FileCheck string variables and is
730   /// updated if this match defines new values. Likewise, the
731   /// GlobalNumericVariableTable StringMap in the same class provides the
732   /// current values of FileCheck numeric variables and is updated if this
733   /// match defines new numeric values.
734   MatchResult match(StringRef Buffer, const SourceMgr &SM) const;
735   /// Prints the value of successful substitutions.
736   void printSubstitutions(const SourceMgr &SM, StringRef Buffer,
737                           SMRange MatchRange, FileCheckDiag::MatchType MatchTy,
738                           std::vector<FileCheckDiag> *Diags) const;
739   void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer,
740                        std::vector<FileCheckDiag> *Diags) const;
741 
742   bool hasVariable() const {
743     return !(Substitutions.empty() && VariableDefs.empty());
744   }
745   void printVariableDefs(const SourceMgr &SM, FileCheckDiag::MatchType MatchTy,
746                          std::vector<FileCheckDiag> *Diags) const;
747 
748   Check::FileCheckType getCheckTy() const { return CheckTy; }
749 
750   int getCount() const { return CheckTy.getCount(); }
751 
752 private:
753   bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
754   void AddBackrefToRegEx(unsigned BackrefNum);
755   /// Computes an arbitrary estimate for the quality of matching this pattern
756   /// at the start of \p Buffer; a distance of zero should correspond to a
757   /// perfect match.
758   unsigned computeMatchDistance(StringRef Buffer) const;
759   /// Finds the closing sequence of a regex variable usage or definition.
760   ///
761   /// \p Str has to point in the beginning of the definition (right after the
762   /// opening sequence). \p SM holds the SourceMgr used for error reporting.
763   ///  \returns the offset of the closing sequence within Str, or npos if it
764   /// was not found.
765   static size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);
766 
767   /// Parses \p Expr for the name of a numeric variable to be defined at line
768   /// \p LineNumber, or before input is parsed if \p LineNumber is None.
769   /// \returns a pointer to the class instance representing that variable,
770   /// creating it if needed, or an error holding a diagnostic against \p SM
771   /// should defining such a variable be invalid.
772   static Expected<NumericVariable *> parseNumericVariableDefinition(
773       StringRef &Expr, FileCheckPatternContext *Context,
774       std::optional<size_t> LineNumber, ExpressionFormat ImplicitFormat,
775       const SourceMgr &SM);
776   /// Parses \p Name as a (pseudo if \p IsPseudo is true) numeric variable use
777   /// at line \p LineNumber, or before input is parsed if \p LineNumber is
778   /// None. Parameter \p Context points to the class instance holding the live
779   /// string and numeric variables. \returns the pointer to the class instance
780   /// representing that variable if successful, or an error holding a
781   /// diagnostic against \p SM otherwise.
782   static Expected<std::unique_ptr<NumericVariableUse>> parseNumericVariableUse(
783       StringRef Name, bool IsPseudo, std::optional<size_t> LineNumber,
784       FileCheckPatternContext *Context, const SourceMgr &SM);
785   enum class AllowedOperand { LineVar, LegacyLiteral, Any };
786   /// Parses \p Expr for use of a numeric operand at line \p LineNumber, or
787   /// before input is parsed if \p LineNumber is None. Accepts literal values,
788   /// numeric variables and function calls, depending on the value of \p AO.
789   /// \p MaybeInvalidConstraint indicates whether the text being parsed could
790   /// be an invalid constraint. \p Context points to the class instance holding
791   /// the live string and numeric variables. \returns the class representing
792   /// that operand in the AST of the expression or an error holding a
793   /// diagnostic against \p SM otherwise. If \p Expr starts with a "(" this
794   /// function will attempt to parse a parenthesized expression.
795   static Expected<std::unique_ptr<ExpressionAST>>
796   parseNumericOperand(StringRef &Expr, AllowedOperand AO, bool ConstraintParsed,
797                       std::optional<size_t> LineNumber,
798                       FileCheckPatternContext *Context, const SourceMgr &SM);
799   /// Parses and updates \p RemainingExpr for a binary operation at line
800   /// \p LineNumber, or before input is parsed if \p LineNumber is None. The
801   /// left operand of this binary operation is given in \p LeftOp and \p Expr
802   /// holds the string for the full expression, including the left operand.
803   /// Parameter \p IsLegacyLineExpr indicates whether we are parsing a legacy
804   /// @LINE expression. Parameter \p Context points to the class instance
805   /// holding the live string and numeric variables. \returns the class
806   /// representing the binary operation in the AST of the expression, or an
807   /// error holding a diagnostic against \p SM otherwise.
808   static Expected<std::unique_ptr<ExpressionAST>>
809   parseBinop(StringRef Expr, StringRef &RemainingExpr,
810              std::unique_ptr<ExpressionAST> LeftOp, bool IsLegacyLineExpr,
811              std::optional<size_t> LineNumber, FileCheckPatternContext *Context,
812              const SourceMgr &SM);
813 
814   /// Parses a parenthesized expression inside \p Expr at line \p LineNumber, or
815   /// before input is parsed if \p LineNumber is None. \p Expr must start with
816   /// a '('. Accepts both literal values and numeric variables. Parameter \p
817   /// Context points to the class instance holding the live string and numeric
818   /// variables. \returns the class representing that operand in the AST of the
819   /// expression or an error holding a diagnostic against \p SM otherwise.
820   static Expected<std::unique_ptr<ExpressionAST>>
821   parseParenExpr(StringRef &Expr, std::optional<size_t> LineNumber,
822                  FileCheckPatternContext *Context, const SourceMgr &SM);
823 
824   /// Parses \p Expr for an argument list belonging to a call to function \p
825   /// FuncName at line \p LineNumber, or before input is parsed if \p LineNumber
826   /// is None. Parameter \p FuncLoc is the source location used for diagnostics.
827   /// Parameter \p Context points to the class instance holding the live string
828   /// and numeric variables. \returns the class representing that call in the
829   /// AST of the expression or an error holding a diagnostic against \p SM
830   /// otherwise.
831   static Expected<std::unique_ptr<ExpressionAST>>
832   parseCallExpr(StringRef &Expr, StringRef FuncName,
833                 std::optional<size_t> LineNumber,
834                 FileCheckPatternContext *Context, const SourceMgr &SM);
835 };
836 
837 //===----------------------------------------------------------------------===//
838 // Check Strings.
839 //===----------------------------------------------------------------------===//
840 
841 /// A check that we found in the input file.
842 struct FileCheckString {
843   /// The pattern to match.
844   Pattern Pat;
845 
846   /// Which prefix name this check matched.
847   StringRef Prefix;
848 
849   /// The location in the match file that the check string was specified.
850   SMLoc Loc;
851 
852   /// All of the strings that are disallowed from occurring between this match
853   /// string and the previous one (or start of file).
854   std::vector<Pattern> DagNotStrings;
855 
856   FileCheckString(const Pattern &P, StringRef S, SMLoc L)
857       : Pat(P), Prefix(S), Loc(L) {}
858 
859   /// Matches check string and its "not strings" and/or "dag strings".
860   size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,
861                size_t &MatchLen, FileCheckRequest &Req,
862                std::vector<FileCheckDiag> *Diags) const;
863 
864   /// Verifies that there is a single line in the given \p Buffer. Errors are
865   /// reported against \p SM.
866   bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
867   /// Verifies that there is no newline in the given \p Buffer. Errors are
868   /// reported against \p SM.
869   bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
870   /// Verifies that none of the strings in \p NotStrings are found in the given
871   /// \p Buffer. Errors are reported against \p SM and diagnostics recorded in
872   /// \p Diags according to the verbosity level set in \p Req.
873   bool CheckNot(const SourceMgr &SM, StringRef Buffer,
874                 const std::vector<const Pattern *> &NotStrings,
875                 const FileCheckRequest &Req,
876                 std::vector<FileCheckDiag> *Diags) const;
877   /// Matches "dag strings" and their mixed "not strings".
878   size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
879                   std::vector<const Pattern *> &NotStrings,
880                   const FileCheckRequest &Req,
881                   std::vector<FileCheckDiag> *Diags) const;
882 };
883 
884 } // namespace llvm
885 
886 #endif
887