mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-18 18:42:46 +02:00
[FileCheck] Fix --dump-input implicit pattern location
Currently, `--dump-input` implies that all `--implicit-check-not` patterns appear on line 1 by printing annotations like: ``` 1: foo bar baz not:1 !~~ error: no match expected ``` This patch changes that to: ``` 1: foo bar baz not:imp1 !~~ error: no match expected ``` `imp1` indicates the first `--implicit-check-not` pattern. Reviewed By: thopre Differential Revision: https://reviews.llvm.org/D77605
This commit is contained in:
parent
f066782da1
commit
00108cdc64
@ -88,7 +88,7 @@ struct FileCheckDiag {
|
|||||||
/// What is the FileCheck directive for this diagnostic?
|
/// What is the FileCheck directive for this diagnostic?
|
||||||
Check::FileCheckType CheckTy;
|
Check::FileCheckType CheckTy;
|
||||||
/// Where is the FileCheck directive for this diagnostic?
|
/// Where is the FileCheck directive for this diagnostic?
|
||||||
unsigned CheckLine, CheckCol;
|
SMLoc CheckLoc;
|
||||||
/// What type of match result does this diagnostic describe?
|
/// What type of match result does this diagnostic describe?
|
||||||
///
|
///
|
||||||
/// A directive's supplied pattern is said to be either expected or excluded
|
/// A directive's supplied pattern is said to be either expected or excluded
|
||||||
@ -160,7 +160,13 @@ public:
|
|||||||
///
|
///
|
||||||
/// Only expected strings whose prefix is one of those listed in \p PrefixRE
|
/// Only expected strings whose prefix is one of those listed in \p PrefixRE
|
||||||
/// are recorded. \returns true in case of an error, false otherwise.
|
/// are recorded. \returns true in case of an error, false otherwise.
|
||||||
bool readCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE);
|
///
|
||||||
|
/// If \p ImpPatBufferIDRange, then the range (inclusive start, exclusive end)
|
||||||
|
/// of IDs for source buffers added to \p SM for implicit patterns are
|
||||||
|
/// recorded in it. The range is empty if there are none.
|
||||||
|
bool
|
||||||
|
readCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
|
||||||
|
std::pair<unsigned, unsigned> *ImpPatBufferIDRange = nullptr);
|
||||||
|
|
||||||
bool ValidateCheckPrefixes();
|
bool ValidateCheckPrefixes();
|
||||||
|
|
||||||
|
@ -1069,16 +1069,13 @@ FileCheckDiag::FileCheckDiag(const SourceMgr &SM,
|
|||||||
const Check::FileCheckType &CheckTy,
|
const Check::FileCheckType &CheckTy,
|
||||||
SMLoc CheckLoc, MatchType MatchTy,
|
SMLoc CheckLoc, MatchType MatchTy,
|
||||||
SMRange InputRange)
|
SMRange InputRange)
|
||||||
: CheckTy(CheckTy), MatchTy(MatchTy) {
|
: CheckTy(CheckTy), CheckLoc(CheckLoc), MatchTy(MatchTy) {
|
||||||
auto Start = SM.getLineAndColumn(InputRange.Start);
|
auto Start = SM.getLineAndColumn(InputRange.Start);
|
||||||
auto End = SM.getLineAndColumn(InputRange.End);
|
auto End = SM.getLineAndColumn(InputRange.End);
|
||||||
InputStartLine = Start.first;
|
InputStartLine = Start.first;
|
||||||
InputStartCol = Start.second;
|
InputStartCol = Start.second;
|
||||||
InputEndLine = End.first;
|
InputEndLine = End.first;
|
||||||
InputEndCol = End.second;
|
InputEndCol = End.second;
|
||||||
Start = SM.getLineAndColumn(CheckLoc);
|
|
||||||
CheckLine = Start.first;
|
|
||||||
CheckCol = Start.second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsPartOfWord(char c) {
|
static bool IsPartOfWord(char c) {
|
||||||
@ -1269,8 +1266,12 @@ FileCheck::FileCheck(FileCheckRequest Req)
|
|||||||
|
|
||||||
FileCheck::~FileCheck() = default;
|
FileCheck::~FileCheck() = default;
|
||||||
|
|
||||||
bool FileCheck::readCheckFile(SourceMgr &SM, StringRef Buffer,
|
bool FileCheck::readCheckFile(
|
||||||
Regex &PrefixRE) {
|
SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
|
||||||
|
std::pair<unsigned, unsigned> *ImpPatBufferIDRange) {
|
||||||
|
if (ImpPatBufferIDRange)
|
||||||
|
ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0;
|
||||||
|
|
||||||
Error DefineError =
|
Error DefineError =
|
||||||
PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM);
|
PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM);
|
||||||
if (DefineError) {
|
if (DefineError) {
|
||||||
@ -1291,7 +1292,17 @@ bool FileCheck::readCheckFile(SourceMgr &SM, StringRef Buffer,
|
|||||||
|
|
||||||
StringRef PatternInBuffer =
|
StringRef PatternInBuffer =
|
||||||
CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
|
CmdLine->getBuffer().substr(Prefix.size(), PatternString.size());
|
||||||
SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
|
unsigned BufferID = SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc());
|
||||||
|
if (ImpPatBufferIDRange) {
|
||||||
|
if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) {
|
||||||
|
ImpPatBufferIDRange->first = BufferID;
|
||||||
|
ImpPatBufferIDRange->second = BufferID + 1;
|
||||||
|
} else {
|
||||||
|
assert(BufferID == ImpPatBufferIDRange->second &&
|
||||||
|
"expected consecutive source buffer IDs");
|
||||||
|
++ImpPatBufferIDRange->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImplicitNegativeChecks.push_back(
|
ImplicitNegativeChecks.push_back(
|
||||||
Pattern(Check::CheckNot, PatternContext.get()));
|
Pattern(Check::CheckNot, PatternContext.get()));
|
||||||
|
@ -494,3 +494,64 @@
|
|||||||
; LAB-NEXT: label:3'0 ~~~
|
; LAB-NEXT: label:3'0 ~~~
|
||||||
; LAB-NEXT: >>>>>>
|
; LAB-NEXT: >>>>>>
|
||||||
; LAB-NOT: {{.}}
|
; LAB-NOT: {{.}}
|
||||||
|
|
||||||
|
;--------------------------------------------------
|
||||||
|
; --implicit-check-not
|
||||||
|
;
|
||||||
|
; The first two --implicit-check-not patterns have no match (success). The
|
||||||
|
; third has an unexpected match (error). To check per-input-line annotation
|
||||||
|
; sorting, all of those plus the CHECK directives have annotations on the same
|
||||||
|
; input line.
|
||||||
|
;--------------------------------------------------
|
||||||
|
|
||||||
|
; RUN: echo 'hello world again!' > %t.in
|
||||||
|
|
||||||
|
; RUN: echo 'CHECK: hel' > %t.chk
|
||||||
|
; RUN: echo 'CHECK: wor' >> %t.chk
|
||||||
|
; RUN: echo 'CHECK: !' >> %t.chk
|
||||||
|
|
||||||
|
; RUN: %ProtectFileCheckOutput \
|
||||||
|
; RUN: not FileCheck -dump-input=always -input-file=%t.in %t.chk 2>&1 \
|
||||||
|
; RUN: --implicit-check-not='goodbye' \
|
||||||
|
; RUN: --implicit-check-not='world' \
|
||||||
|
; RUN: --implicit-check-not='again' \
|
||||||
|
; RUN: | FileCheck -match-full-lines %s -check-prefix=IMPNOT \
|
||||||
|
; RUN: -implicit-check-not='remark:'
|
||||||
|
; RUN: %ProtectFileCheckOutput \
|
||||||
|
; RUN: not FileCheck -dump-input=always -input-file=%t.in %t.chk -v 2>&1 \
|
||||||
|
; RUN: --implicit-check-not='goodbye' \
|
||||||
|
; RUN: --implicit-check-not='world' \
|
||||||
|
; RUN: --implicit-check-not='again' \
|
||||||
|
; RUN: | FileCheck -match-full-lines %s -check-prefixes=IMPNOT,IMPNOT-V \
|
||||||
|
; RUN: -implicit-check-not='remark:'
|
||||||
|
; RUN: %ProtectFileCheckOutput \
|
||||||
|
; RUN: not FileCheck -dump-input=always -input-file=%t.in %t.chk -vv 2>&1 \
|
||||||
|
; RUN: --implicit-check-not='goodbye' \
|
||||||
|
; RUN: --implicit-check-not='world' \
|
||||||
|
; RUN: --implicit-check-not='again' \
|
||||||
|
; RUN: | FileCheck -match-full-lines %s \
|
||||||
|
; RUN: -check-prefixes=IMPNOT,IMPNOT-V,IMPNOT-VV \
|
||||||
|
; RUN: -implicit-check-not='remark:'
|
||||||
|
|
||||||
|
; Verbose diagnostics are suppressed but not errors.
|
||||||
|
; IMPNOT:{{.*}}error:{{.*}}
|
||||||
|
|
||||||
|
; FIXME: All occurrences of imp1, imp2, and imp3 are sorting after the first
|
||||||
|
; directive. They should instead be sorted by when they execute.
|
||||||
|
|
||||||
|
; IMPNOT:<<<<<<
|
||||||
|
; IMPNOT-NEXT: 1: hello world again!
|
||||||
|
; IMPNOT-V-NEXT:check:1 ^~~
|
||||||
|
; IMPNOT-VV-NEXT:not:imp1 X
|
||||||
|
; IMPNOT-VV-NEXT:not:imp2 X
|
||||||
|
; IMPNOT-VV-NEXT:not:imp3 X
|
||||||
|
; IMPNOT-VV-NEXT:not:imp1 X~~
|
||||||
|
; IMPNOT-VV-NEXT:not:imp2 X~~
|
||||||
|
; IMPNOT-VV-NEXT:not:imp3 X~~
|
||||||
|
; IMPNOT-VV-NEXT:not:imp1 X~~~~~~~
|
||||||
|
; IMPNOT-VV-NEXT:not:imp2 X~~~~~~~
|
||||||
|
; IMPNOT-NEXT:not:imp3 !~~~~ error: no match expected
|
||||||
|
; IMPNOT-V-NEXT:check:2 ^~~
|
||||||
|
; IMPNOT-V-NEXT:check:3 ^
|
||||||
|
; IMPNOT-NEXT:>>>>>>
|
||||||
|
; IMPNOT-NOT:{{.}}
|
||||||
|
@ -193,14 +193,15 @@ static void DumpInputAnnotationHelp(raw_ostream &OS) {
|
|||||||
// Labels for annotation lines.
|
// Labels for annotation lines.
|
||||||
OS << " - ";
|
OS << " - ";
|
||||||
WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "T:L";
|
WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "T:L";
|
||||||
OS << " labels the only match result for a pattern of type T from "
|
OS << " labels the only match result for either (1) a pattern of type T"
|
||||||
<< "line L of\n"
|
<< " from\n"
|
||||||
<< " the check file\n";
|
<< " line L of the check file if L is an integer or (2) the"
|
||||||
|
<< " I-th implicit\n"
|
||||||
|
<< " pattern if L is \"imp\" followed by an integer "
|
||||||
|
<< "I (index origin one)\n";
|
||||||
OS << " - ";
|
OS << " - ";
|
||||||
WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "T:L'N";
|
WithColor(OS, raw_ostream::SAVEDCOLOR, true) << "T:L'N";
|
||||||
OS << " labels the Nth match result for a pattern of type T from line "
|
OS << " labels the Nth match result for such a pattern\n";
|
||||||
<< "L of\n"
|
|
||||||
<< " the check file\n";
|
|
||||||
|
|
||||||
// Markers on annotation lines.
|
// Markers on annotation lines.
|
||||||
OS << " - ";
|
OS << " - ";
|
||||||
@ -293,9 +294,12 @@ std::string GetCheckTypeAbbreviation(Check::FileCheckType Ty) {
|
|||||||
llvm_unreachable("unknown FileCheckType");
|
llvm_unreachable("unknown FileCheckType");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BuildInputAnnotations(const std::vector<FileCheckDiag> &Diags,
|
static void
|
||||||
std::vector<InputAnnotation> &Annotations,
|
BuildInputAnnotations(const SourceMgr &SM, unsigned CheckFileBufferID,
|
||||||
unsigned &LabelWidth) {
|
const std::pair<unsigned, unsigned> &ImpPatBufferIDRange,
|
||||||
|
const std::vector<FileCheckDiag> &Diags,
|
||||||
|
std::vector<InputAnnotation> &Annotations,
|
||||||
|
unsigned &LabelWidth) {
|
||||||
// How many diagnostics has the current check seen so far?
|
// How many diagnostics has the current check seen so far?
|
||||||
unsigned CheckDiagCount = 0;
|
unsigned CheckDiagCount = 0;
|
||||||
// What's the widest label?
|
// What's the widest label?
|
||||||
@ -305,14 +309,24 @@ static void BuildInputAnnotations(const std::vector<FileCheckDiag> &Diags,
|
|||||||
InputAnnotation A;
|
InputAnnotation A;
|
||||||
|
|
||||||
// Build label, which uniquely identifies this check result.
|
// Build label, which uniquely identifies this check result.
|
||||||
A.CheckLine = DiagItr->CheckLine;
|
unsigned CheckBufferID = SM.FindBufferContainingLoc(DiagItr->CheckLoc);
|
||||||
|
auto CheckLineAndCol =
|
||||||
|
SM.getLineAndColumn(DiagItr->CheckLoc, CheckBufferID);
|
||||||
|
A.CheckLine = CheckLineAndCol.first;
|
||||||
llvm::raw_string_ostream Label(A.Label);
|
llvm::raw_string_ostream Label(A.Label);
|
||||||
Label << GetCheckTypeAbbreviation(DiagItr->CheckTy) << ":"
|
Label << GetCheckTypeAbbreviation(DiagItr->CheckTy) << ":";
|
||||||
<< DiagItr->CheckLine;
|
if (CheckBufferID == CheckFileBufferID)
|
||||||
|
Label << CheckLineAndCol.first;
|
||||||
|
else if (ImpPatBufferIDRange.first <= CheckBufferID &&
|
||||||
|
CheckBufferID < ImpPatBufferIDRange.second)
|
||||||
|
Label << "imp" << (CheckBufferID - ImpPatBufferIDRange.first + 1);
|
||||||
|
else
|
||||||
|
llvm_unreachable("expected diagnostic's check location to be either in "
|
||||||
|
"the check file or for an implicit pattern");
|
||||||
A.CheckDiagIndex = UINT_MAX;
|
A.CheckDiagIndex = UINT_MAX;
|
||||||
auto DiagNext = std::next(DiagItr);
|
auto DiagNext = std::next(DiagItr);
|
||||||
if (DiagNext != DiagEnd && DiagItr->CheckTy == DiagNext->CheckTy &&
|
if (DiagNext != DiagEnd && DiagItr->CheckTy == DiagNext->CheckTy &&
|
||||||
DiagItr->CheckLine == DiagNext->CheckLine)
|
DiagItr->CheckLoc == DiagNext->CheckLoc)
|
||||||
A.CheckDiagIndex = CheckDiagCount++;
|
A.CheckDiagIndex = CheckDiagCount++;
|
||||||
else if (CheckDiagCount) {
|
else if (CheckDiagCount) {
|
||||||
A.CheckDiagIndex = CheckDiagCount;
|
A.CheckDiagIndex = CheckDiagCount;
|
||||||
@ -606,11 +620,13 @@ int main(int argc, char **argv) {
|
|||||||
SmallString<4096> CheckFileBuffer;
|
SmallString<4096> CheckFileBuffer;
|
||||||
StringRef CheckFileText = FC.CanonicalizeFile(CheckFile, CheckFileBuffer);
|
StringRef CheckFileText = FC.CanonicalizeFile(CheckFile, CheckFileBuffer);
|
||||||
|
|
||||||
SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
|
unsigned CheckFileBufferID =
|
||||||
CheckFileText, CheckFile.getBufferIdentifier()),
|
SM.AddNewSourceBuffer(MemoryBuffer::getMemBuffer(
|
||||||
SMLoc());
|
CheckFileText, CheckFile.getBufferIdentifier()),
|
||||||
|
SMLoc());
|
||||||
|
|
||||||
if (FC.readCheckFile(SM, CheckFileText, PrefixRE))
|
std::pair<unsigned, unsigned> ImpPatBufferIDRange;
|
||||||
|
if (FC.readCheckFile(SM, CheckFileText, PrefixRE, &ImpPatBufferIDRange))
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
// Open the file to check and add it to SourceMgr.
|
// Open the file to check and add it to SourceMgr.
|
||||||
@ -658,7 +674,8 @@ int main(int argc, char **argv) {
|
|||||||
<< "\n";
|
<< "\n";
|
||||||
std::vector<InputAnnotation> Annotations;
|
std::vector<InputAnnotation> Annotations;
|
||||||
unsigned LabelWidth;
|
unsigned LabelWidth;
|
||||||
BuildInputAnnotations(Diags, Annotations, LabelWidth);
|
BuildInputAnnotations(SM, CheckFileBufferID, ImpPatBufferIDRange, Diags,
|
||||||
|
Annotations, LabelWidth);
|
||||||
DumpAnnotatedInput(errs(), Req, InputFileText, Annotations, LabelWidth);
|
DumpAnnotatedInput(errs(), Req, InputFileText, Annotations, LabelWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user