forked from OSchip/llvm-project
[FileCheck] Implement --ignore-case option.
The FileCheck utility is enhanced to support a `--ignore-case` option. This is useful in cases where the output of Unix tools differs in case (e.g. case not specified by Posix). Reviewers: Bigcheese, jakehehrlich, rupprecht, espindola, alexshap, jhenderson, MaskRay Differential Revision: https://reviews.llvm.org/D68146 llvm-svn: 374339
This commit is contained in:
parent
a3ca7acb4f
commit
dfd2b6f07f
|
@ -71,6 +71,11 @@ and from the command line.
|
||||||
The :option:`--strict-whitespace` argument disables this behavior. End-of-line
|
The :option:`--strict-whitespace` argument disables this behavior. End-of-line
|
||||||
sequences are canonicalized to UNIX-style ``\n`` in all modes.
|
sequences are canonicalized to UNIX-style ``\n`` in all modes.
|
||||||
|
|
||||||
|
.. option:: --ignore-case
|
||||||
|
|
||||||
|
By default, FileCheck uses case-sensitive matching. This option causes
|
||||||
|
FileCheck to use case-insensitive matching.
|
||||||
|
|
||||||
.. option:: --implicit-check-not check-pattern
|
.. option:: --implicit-check-not check-pattern
|
||||||
|
|
||||||
Adds implicit negative checks for the specified patterns between positive
|
Adds implicit negative checks for the specified patterns between positive
|
||||||
|
|
|
@ -30,6 +30,7 @@ struct FileCheckRequest {
|
||||||
std::vector<std::string> GlobalDefines;
|
std::vector<std::string> GlobalDefines;
|
||||||
bool AllowEmptyInput = false;
|
bool AllowEmptyInput = false;
|
||||||
bool MatchFullLines = false;
|
bool MatchFullLines = false;
|
||||||
|
bool IgnoreCase = false;
|
||||||
bool EnableVarScope = false;
|
bool EnableVarScope = false;
|
||||||
bool AllowDeprecatedDagOverlap = false;
|
bool AllowDeprecatedDagOverlap = false;
|
||||||
bool Verbose = false;
|
bool Verbose = false;
|
||||||
|
|
|
@ -320,6 +320,7 @@ bool FileCheckPattern::parsePattern(StringRef PatternStr, StringRef Prefix,
|
||||||
SourceMgr &SM,
|
SourceMgr &SM,
|
||||||
const FileCheckRequest &Req) {
|
const FileCheckRequest &Req) {
|
||||||
bool MatchFullLinesHere = Req.MatchFullLines && CheckTy != Check::CheckNot;
|
bool MatchFullLinesHere = Req.MatchFullLines && CheckTy != Check::CheckNot;
|
||||||
|
IgnoreCase = Req.IgnoreCase;
|
||||||
|
|
||||||
PatternLoc = SMLoc::getFromPointer(PatternStr.data());
|
PatternLoc = SMLoc::getFromPointer(PatternStr.data());
|
||||||
|
|
||||||
|
@ -619,7 +620,8 @@ Expected<size_t> FileCheckPattern::match(StringRef Buffer, size_t &MatchLen,
|
||||||
// If this is a fixed string pattern, just match it now.
|
// If this is a fixed string pattern, just match it now.
|
||||||
if (!FixedStr.empty()) {
|
if (!FixedStr.empty()) {
|
||||||
MatchLen = FixedStr.size();
|
MatchLen = FixedStr.size();
|
||||||
size_t Pos = Buffer.find(FixedStr);
|
size_t Pos = IgnoreCase ? Buffer.find_lower(FixedStr)
|
||||||
|
: Buffer.find(FixedStr);
|
||||||
if (Pos == StringRef::npos)
|
if (Pos == StringRef::npos)
|
||||||
return make_error<FileCheckNotFoundError>();
|
return make_error<FileCheckNotFoundError>();
|
||||||
return Pos;
|
return Pos;
|
||||||
|
@ -657,7 +659,10 @@ Expected<size_t> FileCheckPattern::match(StringRef Buffer, size_t &MatchLen,
|
||||||
}
|
}
|
||||||
|
|
||||||
SmallVector<StringRef, 4> MatchInfo;
|
SmallVector<StringRef, 4> MatchInfo;
|
||||||
if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
|
unsigned int Flags = Regex::Newline;
|
||||||
|
if (IgnoreCase)
|
||||||
|
Flags |= Regex::IgnoreCase;
|
||||||
|
if (!Regex(RegExToMatch, Flags).match(Buffer, &MatchInfo))
|
||||||
return make_error<FileCheckNotFoundError>();
|
return make_error<FileCheckNotFoundError>();
|
||||||
|
|
||||||
// Successful regex match.
|
// Successful regex match.
|
||||||
|
|
|
@ -428,6 +428,9 @@ class FileCheckPattern {
|
||||||
/// line to the one with this CHECK.
|
/// line to the one with this CHECK.
|
||||||
Optional<size_t> LineNumber;
|
Optional<size_t> LineNumber;
|
||||||
|
|
||||||
|
/// Ignore case while matching if set to true.
|
||||||
|
bool IgnoreCase = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileCheckPattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,
|
FileCheckPattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,
|
||||||
Optional<size_t> Line = None)
|
Optional<size_t> Line = None)
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
## Check that a full line is matched case insensitively.
|
||||||
|
# RUN: FileCheck --ignore-case --match-full-lines --check-prefix=FULL --input-file=%s %s
|
||||||
|
|
||||||
|
## Check that a regular expression matches case insensitively.
|
||||||
|
# RUN: FileCheck --ignore-case --check-prefix=REGEX --input-file=%s %s
|
||||||
|
|
||||||
|
## Check that a pattern from command line matches case insensitively.
|
||||||
|
# RUN: FileCheck --ignore-case --check-prefix=PAT --DPATTERN="THIS is the" --input-file=%s %s
|
||||||
|
|
||||||
|
## Check that COUNT and NEXT work case insensitively.
|
||||||
|
# RUN: FileCheck --ignore-case --check-prefix=CNT --input-file=%s %s
|
||||||
|
|
||||||
|
## Check that match on same line works case insensitively.
|
||||||
|
# RUN: FileCheck --ignore-case --check-prefix=LINE --input-file=%s %s
|
||||||
|
|
||||||
|
## Check that option --implicit-not works case insensitively.
|
||||||
|
# RUN: sed '/^#/d' %s | FileCheck --implicit-check-not=sTrInG %s
|
||||||
|
# RUN: sed '/^#/d' %s | not FileCheck --ignore-case --implicit-check-not=sTrInG %s 2>&1 | FileCheck --check-prefix=ERROR %s
|
||||||
|
|
||||||
|
this is the STRING to be matched
|
||||||
|
|
||||||
|
# FULL: tHis iS The String TO be matched
|
||||||
|
# REGEX: s{{TRing}}
|
||||||
|
# PAT: [[PATTERN]] string
|
||||||
|
|
||||||
|
Loop 1
|
||||||
|
lOop 2
|
||||||
|
loOp 3
|
||||||
|
looP 4
|
||||||
|
loop 5
|
||||||
|
LOOP 6
|
||||||
|
BREAK
|
||||||
|
|
||||||
|
# CNT-COUNT-6: LOop {{[0-9]}}
|
||||||
|
# CNT-NOT: loop
|
||||||
|
# CNT-NEXT: break
|
||||||
|
|
||||||
|
One Line To Match
|
||||||
|
|
||||||
|
# LINE: {{o}}ne line
|
||||||
|
# LINE-SAME: {{t}}o match
|
||||||
|
|
||||||
|
# ERROR: command line:1:{{[0-9]+]}}: error: CHECK-NOT: excluded string found in input
|
||||||
|
# ERROR-NEXT: -implicit-check-not='sTrInG'
|
||||||
|
# ERROR: note: found here
|
|
@ -48,6 +48,10 @@ static cl::opt<bool> NoCanonicalizeWhiteSpace(
|
||||||
"strict-whitespace",
|
"strict-whitespace",
|
||||||
cl::desc("Do not treat all horizontal whitespace as equivalent"));
|
cl::desc("Do not treat all horizontal whitespace as equivalent"));
|
||||||
|
|
||||||
|
static cl::opt<bool> IgnoreCase(
|
||||||
|
"ignore-case",
|
||||||
|
cl::desc("Use case-insensitive matching"));
|
||||||
|
|
||||||
static cl::list<std::string> ImplicitCheckNot(
|
static cl::list<std::string> ImplicitCheckNot(
|
||||||
"implicit-check-not",
|
"implicit-check-not",
|
||||||
cl::desc("Add an implicit negative check with this pattern to every\n"
|
cl::desc("Add an implicit negative check with this pattern to every\n"
|
||||||
|
@ -555,6 +559,7 @@ int main(int argc, char **argv) {
|
||||||
Req.VerboseVerbose = VerboseVerbose;
|
Req.VerboseVerbose = VerboseVerbose;
|
||||||
Req.NoCanonicalizeWhiteSpace = NoCanonicalizeWhiteSpace;
|
Req.NoCanonicalizeWhiteSpace = NoCanonicalizeWhiteSpace;
|
||||||
Req.MatchFullLines = MatchFullLines;
|
Req.MatchFullLines = MatchFullLines;
|
||||||
|
Req.IgnoreCase = IgnoreCase;
|
||||||
|
|
||||||
if (VerboseVerbose)
|
if (VerboseVerbose)
|
||||||
Req.Verbose = true;
|
Req.Verbose = true;
|
||||||
|
|
Loading…
Reference in New Issue