Skip to content

Commit ffa9d2e

Browse files
author
Aditya Nandakumar
committed
Refactor FileCheck to make it usable as an API
https://reviews.llvm.org/D50283 reviewed by bogner This patch refactors FileCheck's implementation into support so it can be used from C++ in other places (Unit tests). llvm-svn: 339192
1 parent b9cc1fc commit ffa9d2e

File tree

4 files changed

+1571
-1442
lines changed

4 files changed

+1571
-1442
lines changed

llvm/include/llvm/Support/FileCheck.h

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
//==-- llvm/Support/FileCheck.h ---------------------------*- C++ -*-==//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
/// \file This file has some utilities to use FileCheck as an API
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_SUPPORT_FILECHECK_H
15+
#define LLVM_SUPPORT_FILECHECK_H
16+
17+
#include "llvm/ADT/StringMap.h"
18+
#include "llvm/Support/MemoryBuffer.h"
19+
#include "llvm/Support/Regex.h"
20+
#include "llvm/Support/SourceMgr.h"
21+
#include <vector>
22+
#include <map>
23+
24+
namespace llvm {
25+
26+
/// Contains info about various FileCheck options.
27+
struct FileCheckRequest {
28+
std::vector<std::string> CheckPrefixes;
29+
bool NoCanonicalizeWhiteSpace = false;
30+
std::vector<std::string> ImplicitCheckNot;
31+
std::vector<std::string> GlobalDefines;
32+
bool AllowEmptyInput = false;
33+
bool MatchFullLines = false;
34+
bool EnableVarScope = false;
35+
bool AllowDeprecatedDagOverlap = false;
36+
bool Verbose = false;
37+
bool VerboseVerbose = false;
38+
};
39+
40+
41+
//===----------------------------------------------------------------------===//
42+
// Pattern Handling Code.
43+
//===----------------------------------------------------------------------===//
44+
45+
namespace Check {
46+
enum FileCheckType {
47+
CheckNone = 0,
48+
CheckPlain,
49+
CheckNext,
50+
CheckSame,
51+
CheckNot,
52+
CheckDAG,
53+
CheckLabel,
54+
CheckEmpty,
55+
56+
/// Indicates the pattern only matches the end of file. This is used for
57+
/// trailing CHECK-NOTs.
58+
CheckEOF,
59+
60+
/// Marks when parsing found a -NOT check combined with another CHECK suffix.
61+
CheckBadNot
62+
};
63+
}
64+
65+
class FileCheckPattern {
66+
SMLoc PatternLoc;
67+
68+
/// A fixed string to match as the pattern or empty if this pattern requires
69+
/// a regex match.
70+
StringRef FixedStr;
71+
72+
/// A regex string to match as the pattern or empty if this pattern requires
73+
/// a fixed string to match.
74+
std::string RegExStr;
75+
76+
/// Entries in this vector map to uses of a variable in the pattern, e.g.
77+
/// "foo[[bar]]baz". In this case, the RegExStr will contain "foobaz" and
78+
/// we'll get an entry in this vector that tells us to insert the value of
79+
/// bar at offset 3.
80+
std::vector<std::pair<StringRef, unsigned>> VariableUses;
81+
82+
/// Maps definitions of variables to their parenthesized capture numbers.
83+
///
84+
/// E.g. for the pattern "foo[[bar:.*]]baz", VariableDefs will map "bar" to
85+
/// 1.
86+
std::map<StringRef, unsigned> VariableDefs;
87+
88+
Check::FileCheckType CheckTy;
89+
90+
/// Contains the number of line this pattern is in.
91+
unsigned LineNumber;
92+
93+
public:
94+
explicit FileCheckPattern(Check::FileCheckType Ty)
95+
: CheckTy(Ty) {}
96+
97+
/// Returns the location in source code.
98+
SMLoc getLoc() const { return PatternLoc; }
99+
100+
bool ParsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM,
101+
unsigned LineNumber, const FileCheckRequest &Req);
102+
size_t Match(StringRef Buffer, size_t &MatchLen,
103+
StringMap<StringRef> &VariableTable) const;
104+
void PrintVariableUses(const SourceMgr &SM, StringRef Buffer,
105+
const StringMap<StringRef> &VariableTable,
106+
SMRange MatchRange = None) const;
107+
void PrintFuzzyMatch(const SourceMgr &SM, StringRef Buffer,
108+
const StringMap<StringRef> &VariableTable) const;
109+
110+
bool hasVariable() const {
111+
return !(VariableUses.empty() && VariableDefs.empty());
112+
}
113+
114+
Check::FileCheckType getCheckTy() const { return CheckTy; }
115+
116+
private:
117+
bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
118+
void AddBackrefToRegEx(unsigned BackrefNum);
119+
unsigned
120+
ComputeMatchDistance(StringRef Buffer,
121+
const StringMap<StringRef> &VariableTable) const;
122+
bool EvaluateExpression(StringRef Expr, std::string &Value) const;
123+
size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);
124+
};
125+
126+
//===----------------------------------------------------------------------===//
127+
// Check Strings.
128+
//===----------------------------------------------------------------------===//
129+
130+
/// A check that we found in the input file.
131+
struct FileCheckString {
132+
/// The pattern to match.
133+
FileCheckPattern Pat;
134+
135+
/// Which prefix name this check matched.
136+
StringRef Prefix;
137+
138+
/// The location in the match file that the check string was specified.
139+
SMLoc Loc;
140+
141+
/// All of the strings that are disallowed from occurring between this match
142+
/// string and the previous one (or start of file).
143+
std::vector<FileCheckPattern> DagNotStrings;
144+
145+
FileCheckString(const FileCheckPattern &P, StringRef S, SMLoc L)
146+
: Pat(P), Prefix(S), Loc(L) {}
147+
148+
size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,
149+
size_t &MatchLen, StringMap<StringRef> &VariableTable,
150+
FileCheckRequest &Req) const;
151+
152+
bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
153+
bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
154+
bool CheckNot(const SourceMgr &SM, StringRef Buffer,
155+
const std::vector<const FileCheckPattern *> &NotStrings,
156+
StringMap<StringRef> &VariableTable,
157+
const FileCheckRequest &Req) const;
158+
size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
159+
std::vector<const FileCheckPattern *> &NotStrings,
160+
StringMap<StringRef> &VariableTable,
161+
const FileCheckRequest &Req) const;
162+
};
163+
164+
/// FileCheck class takes the request and exposes various methods that
165+
/// use information from the request.
166+
class FileCheck {
167+
FileCheckRequest Req;
168+
169+
public:
170+
FileCheck(FileCheckRequest Req) : Req(Req) {}
171+
172+
// Combines the check prefixes into a single regex so that we can efficiently
173+
// scan for any of the set.
174+
//
175+
// The semantics are that the longest-match wins which matches our regex
176+
// library.
177+
Regex buildCheckPrefixRegex();
178+
179+
/// Read the check file, which specifies the sequence of expected strings.
180+
///
181+
/// The strings are added to the CheckStrings vector. Returns true in case of
182+
/// an error, false otherwise.
183+
bool ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
184+
std::vector<FileCheckString> &CheckStrings);
185+
186+
bool ValidateCheckPrefixes();
187+
188+
/// Canonicalize whitespaces in the file. Line endings are replaced with
189+
/// UNIX-style '\n'.
190+
StringRef CanonicalizeFile(MemoryBuffer &MB,
191+
SmallVectorImpl<char> &OutputBuffer);
192+
193+
/// Check the input to FileCheck provided in the \p Buffer against the \p
194+
/// CheckStrings read from the check file.
195+
///
196+
/// Returns false if the input fails to satisfy the checks.
197+
bool CheckInput(SourceMgr &SM, StringRef Buffer,
198+
ArrayRef<FileCheckString> CheckStrings);
199+
};
200+
} // namespace llvm
201+
#endif

llvm/lib/Support/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ add_llvm_library(LLVMSupport
7171
DJB.cpp
7272
Error.cpp
7373
ErrorHandling.cpp
74+
FileCheck.cpp
7475
FileUtilities.cpp
7576
FileOutputBuffer.cpp
7677
FoldingSet.cpp

0 commit comments

Comments
 (0)