1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
| //==-- llvm/Support/FileCheck.h ---------------------------*- C++ -*-==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file This file has some utilities to use FileCheck as an API
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_FILECHECK_H
#define LLVM_SUPPORT_FILECHECK_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/SourceMgr.h"
#include <string>
#include <vector>
namespace llvm {
/// Contains info about various FileCheck options.
struct FileCheckRequest {
std::vector<std::string> CheckPrefixes;
bool NoCanonicalizeWhiteSpace = false;
std::vector<std::string> ImplicitCheckNot;
std::vector<std::string> GlobalDefines;
bool AllowEmptyInput = false;
bool MatchFullLines = false;
bool IgnoreCase = false;
bool EnableVarScope = false;
bool AllowDeprecatedDagOverlap = false;
bool Verbose = false;
bool VerboseVerbose = false;
};
//===----------------------------------------------------------------------===//
// Summary of a FileCheck diagnostic.
//===----------------------------------------------------------------------===//
namespace Check {
enum FileCheckKind {
CheckNone = 0,
CheckPlain,
CheckNext,
CheckSame,
CheckNot,
CheckDAG,
CheckLabel,
CheckEmpty,
/// Indicates the pattern only matches the end of file. This is used for
/// trailing CHECK-NOTs.
CheckEOF,
/// Marks when parsing found a -NOT check combined with another CHECK suffix.
CheckBadNot,
/// Marks when parsing found a -COUNT directive with invalid count value.
CheckBadCount
};
class FileCheckType {
FileCheckKind Kind;
int Count; ///< optional Count for some checks
public:
FileCheckType(FileCheckKind Kind = CheckNone) : Kind(Kind), Count(1) {}
FileCheckType(const FileCheckType &) = default;
operator FileCheckKind() const { return Kind; }
int getCount() const { return Count; }
FileCheckType &setCount(int C);
// \returns a description of \p Prefix.
std::string getDescription(StringRef Prefix) const;
};
} // namespace Check
struct FileCheckDiag {
/// What is the FileCheck directive for this diagnostic?
Check::FileCheckType CheckTy;
/// Where is the FileCheck directive for this diagnostic?
unsigned CheckLine, CheckCol;
/// What type of match result does this diagnostic describe?
///
/// A directive's supplied pattern is said to be either expected or excluded
/// depending on whether the pattern must have or must not have a match in
/// order for the directive to succeed. For example, a CHECK directive's
/// pattern is expected, and a CHECK-NOT directive's pattern is excluded.
/// All match result types whose names end with "Excluded" are for excluded
/// patterns, and all others are for expected patterns.
///
/// There might be more than one match result for a single pattern. For
/// example, there might be several discarded matches
/// (MatchFoundButDiscarded) before either a good match
/// (MatchFoundAndExpected) or a failure to match (MatchNoneButExpected),
/// and there might be a fuzzy match (MatchFuzzy) after the latter.
enum MatchType {
/// Indicates a good match for an expected pattern.
MatchFoundAndExpected,
/// Indicates a match for an excluded pattern.
MatchFoundButExcluded,
/// Indicates a match for an expected pattern, but the match is on the
/// wrong line.
MatchFoundButWrongLine,
/// Indicates a discarded match for an expected pattern.
MatchFoundButDiscarded,
/// Indicates no match for an excluded pattern.
MatchNoneAndExcluded,
/// Indicates no match for an expected pattern, but this might follow good
/// matches when multiple matches are expected for the pattern, or it might
/// follow discarded matches for the pattern.
MatchNoneButExpected,
/// Indicates a fuzzy match that serves as a suggestion for the next
/// intended match for an expected pattern with too few or no good matches.
MatchFuzzy,
} MatchTy;
/// The search range if MatchTy is MatchNoneAndExcluded or
/// MatchNoneButExpected, or the match range otherwise.
unsigned InputStartLine;
unsigned InputStartCol;
unsigned InputEndLine;
unsigned InputEndCol;
FileCheckDiag(const SourceMgr &SM, const Check::FileCheckType &CheckTy,
SMLoc CheckLoc, MatchType MatchTy, SMRange InputRange);
};
class FileCheckPatternContext;
struct FileCheckString;
/// FileCheck class takes the request and exposes various methods that
/// use information from the request.
class FileCheck {
FileCheckRequest Req;
std::unique_ptr<FileCheckPatternContext> PatternContext;
// C++17 TODO: make this a plain std::vector.
std::unique_ptr<std::vector<FileCheckString>> CheckStrings;
public:
explicit FileCheck(FileCheckRequest Req);
~FileCheck();
// Combines the check prefixes into a single regex so that we can efficiently
// scan for any of the set.
//
// The semantics are that the longest-match wins which matches our regex
// library.
Regex buildCheckPrefixRegex();
/// Reads the check file from \p Buffer and records the expected strings it
/// contains. Errors are reported against \p SM.
///
/// Only expected strings whose prefix is one of those listed in \p PrefixRE
/// are recorded. \returns true in case of an error, false otherwise.
bool readCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE);
bool ValidateCheckPrefixes();
/// Canonicalizes whitespaces in the file. Line endings are replaced with
/// UNIX-style '\n'.
StringRef CanonicalizeFile(MemoryBuffer &MB,
SmallVectorImpl<char> &OutputBuffer);
/// Checks the input to FileCheck provided in the \p Buffer against the
/// expected strings read from the check file and record diagnostics emitted
/// in \p Diags. Errors are recorded against \p SM.
///
/// \returns false if the input fails to satisfy the checks.
bool checkInput(SourceMgr &SM, StringRef Buffer,
std::vector<FileCheckDiag> *Diags = nullptr);
};
} // namespace llvm
#endif
|