1
0
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:
Joel E. Denny 2020-04-16 14:53:44 -04:00
parent f066782da1
commit 00108cdc64
4 changed files with 122 additions and 27 deletions

View File

@ -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();

View File

@ -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()));

View File

@ -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:{{.}}

View File

@ -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);
} }