[llvm] [FileCheck]: Fix diagnostics for NOT prefixes (PR #78412)
Vinayak Dev via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 19 03:32:39 PST 2024
https://github.com/vinayakdsci updated https://github.com/llvm/llvm-project/pull/78412
>From 373b5707c5d5736f57cf7c27fed56f2dc11dbd0e Mon Sep 17 00:00:00 2001
From: Vinayak Dev <vinayakdev.sci at gmail.com>
Date: Mon, 15 Jan 2024 22:40:44 +0530
Subject: [PATCH] [FileCheck]: Fix diagnostics for NOT prefixes
---
llvm/lib/FileCheck/FileCheck.cpp | 48 +++++++------
llvm/lib/FileCheck/FileCheckImpl.h | 20 ++++--
llvm/test/FileCheck/check-ignore-case.txt | 2 +-
.../FileCheck/check-not-custom-prefix.txt | 69 +++++++++++++++++++
.../test/FileCheck/dump-input/annotations.txt | 2 +-
llvm/test/FileCheck/implicit-check-not.txt | 14 ++--
6 files changed, 119 insertions(+), 36 deletions(-)
create mode 100644 llvm/test/FileCheck/check-not-custom-prefix.txt
diff --git a/llvm/lib/FileCheck/FileCheck.cpp b/llvm/lib/FileCheck/FileCheck.cpp
index b728c14d288aa5..94e85ef1ee4260 100644
--- a/llvm/lib/FileCheck/FileCheck.cpp
+++ b/llvm/lib/FileCheck/FileCheck.cpp
@@ -1784,7 +1784,7 @@ bool FileCheck::readCheckFile(
PatternContext->createLineVariable();
- std::vector<Pattern> ImplicitNegativeChecks;
+ std::vector<FileCheckString::DagNotPrefixInfo> ImplicitNegativeChecks;
for (StringRef PatternString : Req.ImplicitCheckNot) {
// Create a buffer with fake command line content in order to display the
// command line option responsible for the specific implicit CHECK-NOT.
@@ -1807,14 +1807,15 @@ bool FileCheck::readCheckFile(
}
}
- ImplicitNegativeChecks.push_back(
- Pattern(Check::CheckNot, PatternContext.get()));
- ImplicitNegativeChecks.back().parsePattern(PatternInBuffer,
- "IMPLICIT-CHECK", SM, Req);
+ ImplicitNegativeChecks.emplace_back(
+ Pattern(Check::CheckNot, PatternContext.get()),
+ StringRef("IMPLICIT-CHECK"));
+ ImplicitNegativeChecks.back().DagNotPat.parsePattern(
+ PatternInBuffer, "IMPLICIT-CHECK", SM, Req);
}
- std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks;
-
+ std::vector<FileCheckString::DagNotPrefixInfo> DagNotMatches =
+ ImplicitNegativeChecks;
// LineNumber keeps track of the line on which CheckPrefix instances are
// found.
unsigned LineNumber = 1;
@@ -1926,7 +1927,7 @@ bool FileCheck::readCheckFile(
// Handle CHECK-DAG/-NOT.
if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) {
- DagNotMatches.push_back(P);
+ DagNotMatches.emplace_back(P, UsedPrefix);
continue;
}
@@ -2165,7 +2166,7 @@ size_t FileCheckString::Check(const SourceMgr &SM, StringRef Buffer,
FileCheckRequest &Req,
std::vector<FileCheckDiag> *Diags) const {
size_t LastPos = 0;
- std::vector<const Pattern *> NotStrings;
+ std::vector<const DagNotPrefixInfo *> NotStrings;
// IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL
// bounds; we have not processed variable definitions within the bounded block
@@ -2303,16 +2304,18 @@ bool FileCheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const {
}
bool FileCheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
- const std::vector<const Pattern *> &NotStrings,
+ const std::vector<const DagNotPrefixInfo *> &NotStrings,
const FileCheckRequest &Req,
std::vector<FileCheckDiag> *Diags) const {
bool DirectiveFail = false;
- for (const Pattern *Pat : NotStrings) {
- assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!");
- Pattern::MatchResult MatchResult = Pat->match(Buffer, SM);
- if (Error Err = reportMatchResult(/*ExpectedMatch=*/false, SM, Prefix,
- Pat->getLoc(), *Pat, 1, Buffer,
- std::move(MatchResult), Req, Diags)) {
+ for (auto NotInfo : NotStrings) {
+ assert((NotInfo->DagNotPat.getCheckTy() == Check::CheckNot) &&
+ "Expect CHECK-NOT!");
+ Pattern::MatchResult MatchResult = NotInfo->DagNotPat.match(Buffer, SM);
+ if (Error Err =
+ reportMatchResult(/*ExpectedMatch=*/false, SM, NotInfo->DagNotPrefix,
+ NotInfo->DagNotPat.getLoc(), NotInfo->DagNotPat, 1,
+ Buffer, std::move(MatchResult), Req, Diags)) {
cantFail(handleErrors(std::move(Err), [&](const ErrorReported &E) {}));
DirectiveFail = true;
continue;
@@ -2322,7 +2325,7 @@ bool FileCheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
}
size_t FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
- std::vector<const Pattern *> &NotStrings,
+ std::vector<const DagNotPrefixInfo *> &NotStrings,
const FileCheckRequest &Req,
std::vector<FileCheckDiag> *Diags) const {
if (DagNotStrings.empty())
@@ -2344,13 +2347,14 @@ size_t FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
// group, so we don't use a range-based for loop here.
for (auto PatItr = DagNotStrings.begin(), PatEnd = DagNotStrings.end();
PatItr != PatEnd; ++PatItr) {
- const Pattern &Pat = *PatItr;
+ const Pattern &Pat = PatItr->DagNotPat;
+ const StringRef DNPrefix = PatItr->DagNotPrefix;
assert((Pat.getCheckTy() == Check::CheckDAG ||
Pat.getCheckTy() == Check::CheckNot) &&
"Invalid CHECK-DAG or CHECK-NOT!");
if (Pat.getCheckTy() == Check::CheckNot) {
- NotStrings.push_back(&Pat);
+ NotStrings.push_back(&*PatItr);
continue;
}
@@ -2367,7 +2371,7 @@ size_t FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
// With a group of CHECK-DAGs, a single mismatching means the match on
// that group of CHECK-DAGs fails immediately.
if (MatchResult.TheError || Req.VerboseVerbose) {
- if (Error Err = reportMatchResult(/*ExpectedMatch=*/true, SM, Prefix,
+ if (Error Err = reportMatchResult(/*ExpectedMatch=*/true, SM, DNPrefix,
Pat.getLoc(), Pat, 1, MatchBuffer,
std::move(MatchResult), Req, Diags)) {
cantFail(
@@ -2430,13 +2434,13 @@ size_t FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
}
if (!Req.VerboseVerbose)
cantFail(printMatch(
- /*ExpectedMatch=*/true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer,
+ /*ExpectedMatch=*/true, SM, DNPrefix, Pat.getLoc(), Pat, 1, Buffer,
Pattern::MatchResult(MatchPos, MatchLen, Error::success()), Req,
Diags));
// Handle the end of a CHECK-DAG group.
if (std::next(PatItr) == PatEnd ||
- std::next(PatItr)->getCheckTy() == Check::CheckNot) {
+ std::next(PatItr)->DagNotPat.getCheckTy() == Check::CheckNot) {
if (!NotStrings.empty()) {
// If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to
// CHECK-DAG, verify that there are no 'not' strings occurred in that
diff --git a/llvm/lib/FileCheck/FileCheckImpl.h b/llvm/lib/FileCheck/FileCheckImpl.h
index c15461684ea392..c772eddd8ecd5e 100644
--- a/llvm/lib/FileCheck/FileCheckImpl.h
+++ b/llvm/lib/FileCheck/FileCheckImpl.h
@@ -823,9 +823,19 @@ struct FileCheckString {
/// The location in the match file that the check string was specified.
SMLoc Loc;
- /// All of the strings that are disallowed from occurring between this match
- /// string and the previous one (or start of file).
- std::vector<Pattern> DagNotStrings;
+ /// Hold the information about the DAG/NOT strings in the program, which are
+ /// not explicitly stored otherwise. This allows for better and more accurate
+ /// diagnostic messages.
+ struct DagNotPrefixInfo {
+ Pattern DagNotPat;
+ StringRef DagNotPrefix;
+
+ DagNotPrefixInfo(const Pattern &P, StringRef S)
+ : DagNotPat(P), DagNotPrefix(S) {}
+ };
+
+ /// Hold the DAG/NOT strings occurring in the input file.
+ std::vector<DagNotPrefixInfo> DagNotStrings;
FileCheckString(const Pattern &P, StringRef S, SMLoc L)
: Pat(P), Prefix(S), Loc(L) {}
@@ -845,12 +855,12 @@ struct FileCheckString {
/// \p Buffer. Errors are reported against \p SM and diagnostics recorded in
/// \p Diags according to the verbosity level set in \p Req.
bool CheckNot(const SourceMgr &SM, StringRef Buffer,
- const std::vector<const Pattern *> &NotStrings,
+ const std::vector<const DagNotPrefixInfo *> &NotStrings,
const FileCheckRequest &Req,
std::vector<FileCheckDiag> *Diags) const;
/// Matches "dag strings" and their mixed "not strings".
size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
- std::vector<const Pattern *> &NotStrings,
+ std::vector<const DagNotPrefixInfo *> &NotStrings,
const FileCheckRequest &Req,
std::vector<FileCheckDiag> *Diags) const;
};
diff --git a/llvm/test/FileCheck/check-ignore-case.txt b/llvm/test/FileCheck/check-ignore-case.txt
index c3b4d97ab5e417..47999ff2935157 100644
--- a/llvm/test/FileCheck/check-ignore-case.txt
+++ b/llvm/test/FileCheck/check-ignore-case.txt
@@ -43,6 +43,6 @@ 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: command line:1:{{[0-9]+}}: error: IMPLICIT-CHECK-NOT: excluded string found in input
# ERROR-NEXT: -implicit-check-not='sTrInG'
# ERROR: note: found here
diff --git a/llvm/test/FileCheck/check-not-custom-prefix.txt b/llvm/test/FileCheck/check-not-custom-prefix.txt
new file mode 100644
index 00000000000000..ddd8a7109ded9e
--- /dev/null
+++ b/llvm/test/FileCheck/check-not-custom-prefix.txt
@@ -0,0 +1,69 @@
+; Test two trailing NOT strings
+; RUN: rm -f %t && \
+; RUN: echo "LEADING: placeholder1" >>%t && echo "MIDDLE-NOT: placeholder2" >>%t && echo "TRAILING-NOT: placeholder3" >>%t && \
+; RUN: %ProtectFileCheckOutput not FileCheck --strict-whitespace --check-prefixes LEADING,MIDDLE,TRAILING --dump-input=never --input-file %t %t 2>&1 | \
+; RUN: FileCheck --check-prefix TEST1 %s
+
+; Test NOT string occurring in between two allowable strings
+; RUN: rm -f %t && \
+; RUN: echo "LEADING: placeholder1" >>%t && echo "MIDDLE-NOT: placeholder2" >>%t && echo "TRAILING: placeholder3" >>%t && \
+; RUN: %ProtectFileCheckOutput not FileCheck --strict-whitespace --check-prefixes LEADING,MIDDLE,TRAILING --dump-input=never --input-file %t %t 2>&1 | \
+; RUN: FileCheck --check-prefix TEST2 %s
+
+; Test first prefix found being the NOT string
+; RUN: rm -f %t && \
+; RUN: echo "LEADING-NOT: placeholder1" >>%t && echo "MIDDLE: placeholder2" >>%t && echo "TRAILING: placeholder3" >>%t && \
+; RUN: %ProtectFileCheckOutput not FileCheck --strict-whitespace --check-prefixes LEADING,MIDDLE,TRAILING --dump-input=never --input-file %t %t 2>&1 | \
+; RUN: FileCheck --check-prefix TEST3 %s
+
+; Test all given prefixes being NOT strings
+; RUN: rm -f %t && \
+; RUN: echo "LEADING-NOT: placeholder1" >>%t && echo "MIDDLE-NOT: placeholder2" >>%t && echo "TRAILING-NOT: placeholder3" >>%t && \
+; RUN: %ProtectFileCheckOutput not FileCheck --strict-whitespace --check-prefixes LEADING,MIDDLE,TRAILING --dump-input=never --input-file %t %t 2>&1 | \
+; RUN: FileCheck --check-prefix TEST4 %s
+
+; TEST1: error: MIDDLE-NOT: excluded string found in input
+; TEST1-NEXT: MIDDLE-NOT: placeholder2
+; TEST1-NEXT: {{^}} ^{{$}}
+; TEST1-NEXT: note: found here
+; TEST1-NEXT: MIDDLE-NOT: placeholder2
+; TEST1-NEXT: {{^}} ^~~~~~~~~~~~{{$}}
+; TEST1-NEXT: error: TRAILING-NOT: excluded string found in input
+; TEST1-NEXT: TRAILING-NOT: placeholder3
+; TEST1-NEXT: {{^}} ^{{$}}
+; TEST1-NEXT: note: found here
+; TEST1-NEXT: TRAILING-NOT: placeholder3
+; TEST1-NEXT: {{^}} ^~~~~~~~~~~~{{$}}
+
+; TEST2: error: MIDDLE-NOT: excluded string found in input
+; TEST2-NEXT: MIDDLE-NOT: placeholder2
+; TEST2-NEXT: {{^}} ^{{$}}
+; TEST2-NEXT: note: found here
+; TEST2-NEXT: MIDDLE-NOT: placeholder2
+; TEST2-NEXT: {{^}} ^~~~~~~~~~~~{{$}}
+
+; TEST3: error: LEADING-NOT: excluded string found in input
+; TEST3-NEXT: LEADING-NOT: placeholder1
+; TEST3-NEXT: {{^}} ^{{$}}
+; TEST3-NEXT: note: found here
+; TEST3-NEXT: LEADING-NOT: placeholder1
+; TEST3-NEXT: {{^}} ^~~~~~~~~~~~{{$}}
+
+; TEST4: error: LEADING-NOT: excluded string found in input
+; TEST4-NEXT: LEADING-NOT: placeholder1
+; TEST4-NEXT: {{^}} ^{{$}}
+; TEST4-NEXT: note: found here
+; TEST4-NEXT: LEADING-NOT: placeholder1
+; TEST4-NEXT: {{^}} ^~~~~~~~~~~~{{$}}
+; TEST4-NEXT: error: MIDDLE-NOT: excluded string found in input
+; TEST4-NEXT: MIDDLE-NOT: placeholder2
+; TEST4-NEXT: {{^}} ^{{$}}
+; TEST4-NEXT: note: found here
+; TEST4-NEXT: MIDDLE-NOT: placeholder2
+; TEST4-NEXT: {{^}} ^~~~~~~~~~~~{{$}}
+; TEST4-NEXT: error: TRAILING-NOT: excluded string found in input
+; TEST4-NEXT: TRAILING-NOT: placeholder3
+; TEST4-NEXT: {{^}} ^{{$}}
+; TEST4-NEXT: note: found here
+; TEST4-NEXT: TRAILING-NOT: placeholder3
+; TEST4-NEXT: {{^}} ^~~~~~~~~~~~{{$}}
diff --git a/llvm/test/FileCheck/dump-input/annotations.txt b/llvm/test/FileCheck/dump-input/annotations.txt
index 45bf54698bca00..367ea3377e6aeb 100644
--- a/llvm/test/FileCheck/dump-input/annotations.txt
+++ b/llvm/test/FileCheck/dump-input/annotations.txt
@@ -650,7 +650,7 @@
; RUN: -implicit-check-not='{{remark:|error:}}'
; Verbose diagnostics are suppressed but not errors.
-; IMPNOT:{{.*}}command line:1:22: error: CHECK-NOT: excluded string found in input
+; IMPNOT:{{.*}}command line:1:22: error: IMPLICIT-CHECK-NOT: excluded string found in input
; IMPNOT:<<<<<<
; IMPNOT-NEXT: 1: hello world again!
diff --git a/llvm/test/FileCheck/implicit-check-not.txt b/llvm/test/FileCheck/implicit-check-not.txt
index 95dd9fa782df8f..eaca0d37fcb291 100644
--- a/llvm/test/FileCheck/implicit-check-not.txt
+++ b/llvm/test/FileCheck/implicit-check-not.txt
@@ -21,26 +21,26 @@
warning: aaa
; CHECK-PASS: warning: aaa
-; CHECK-ERROR1: command line:1:22: error: CHECK-FAIL1-NOT: excluded string found in input
+; CHECK-ERROR1: command line:1:22: error: IMPLICIT-CHECK-NOT: excluded string found in input
; CHECK-ERROR1-NEXT: -implicit-check-not='warning:'
; CHECK-ERROR1: note: found here
; CHECK-FAIL2: warning: aaa
; CHECK-FAIL3: warning: aaa
-; CHECK-ERROR4: command line:1:22: error: CHECK-FAIL1-NOT: excluded string found in input
+; CHECK-ERROR4: command line:1:22: error: IMPLICIT-CHECK-NOT: excluded string found in input
; CHECK-ERROR4-NEXT: {{-implicit-check-not='\{\{aaa\|bbb\|ccc\}\}'}}
; CHECK-ERROR4: note: found here
-; CHECK-ERROR5: command line:1:22: error: CHECK-FAIL1-NOT: excluded string found in input
+; CHECK-ERROR5: command line:1:22: error: IMPLICIT-CHECK-NOT: excluded string found in input
; CHECK-ERROR5-NEXT: -implicit-check-not='aaa'
; CHECK-ERROR5: note: found here
warning: bbb
; CHECK-PASS: warning: bbb
; CHECK-FAIL1: warning: bbb
-; CHECK-ERROR2: command line:1:22: error: CHECK-FAIL2-NOT: excluded string found in input
+; CHECK-ERROR2: command line:1:22: error: IMPLICIT-CHECK-NOT: excluded string found in input
; CHECK-ERROR2-NEXT: -implicit-check-not='warning:'
; CHECK-ERROR2: note: found here
; CHECK-FAIL3: warning: bbb
-; CHECK-ERROR6: command line:1:22: error: CHECK-FAIL2-NOT: excluded string found in input
+; CHECK-ERROR6: command line:1:22: error: IMPLICIT-CHECK-NOT: excluded string found in input
; CHECK-ERROR6-NEXT: -implicit-check-not='bbb'
; CHECK-ERROR6: note: found here
@@ -48,9 +48,9 @@ warning: ccc
; CHECK-PASS: warning: ccc
; CHECK-FAIL1: warning: ccc
; CHECK-FAIL2: warning: ccc
-; CHECK-ERROR3: command line:1:22: error: CHECK-FAIL3-NOT: excluded string found in input
+; CHECK-ERROR3: command line:1:22: error: IMPLICIT-CHECK-NOT: excluded string found in input
; CHECK-ERROR3-NEXT: -implicit-check-not='warning:'
; CHECK-ERROR3: note: found here
-; CHECK-ERROR7: command line:1:22: error: CHECK-FAIL3-NOT: excluded string found in input
+; CHECK-ERROR7: command line:1:22: error: IMPLICIT-CHECK-NOT: excluded string found in input
; CHECK-ERROR7-NEXT: -implicit-check-not='ccc'
; CHECK-ERROR7: note: found here
More information about the llvm-commits
mailing list