Home | History | Annotate | Line # | Download | only in FileCheck
      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