switch to llvm7
OBS-URL: https://build.opensuse.org/package/show/devel:tools:statica/klee?expand=0&rev=60
This commit is contained in:
parent
13fb9cc2f2
commit
220a78369b
367
FileCheck.cpp
367
FileCheck.cpp
@ -21,14 +21,14 @@
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/InitLLVM.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/PrettyStackTrace.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
@ -83,6 +83,28 @@ static cl::opt<bool> EnableVarScope(
|
||||
"do not start with '$' will be reset at the beginning of\n"
|
||||
"each CHECK-LABEL block."));
|
||||
|
||||
static cl::opt<bool> AllowDeprecatedDagOverlap(
|
||||
"allow-deprecated-dag-overlap", cl::init(false),
|
||||
cl::desc("Enable overlapping among matches in a group of consecutive\n"
|
||||
"CHECK-DAG directives. This option is deprecated and is only\n"
|
||||
"provided for convenience as old tests are migrated to the new\n"
|
||||
"non-overlapping CHECK-DAG implementation.\n"));
|
||||
|
||||
static cl::opt<bool> Verbose("v", cl::init(false),
|
||||
cl::desc("Print directive pattern matches.\n"));
|
||||
|
||||
static cl::opt<bool> VerboseVerbose(
|
||||
"vv", cl::init(false),
|
||||
cl::desc("Print information helpful in diagnosing internal FileCheck\n"
|
||||
"issues. Implies -v.\n"));
|
||||
static const char * DumpInputEnv = "FILECHECK_DUMP_INPUT_ON_FAILURE";
|
||||
|
||||
static cl::opt<bool> DumpInputOnFailure(
|
||||
"dump-input-on-failure", cl::init(std::getenv(DumpInputEnv)),
|
||||
cl::desc("Dump original input to stderr before failing.\n"
|
||||
"The value can be also controlled using\n"
|
||||
"FILECHECK_DUMP_INPUT_ON_FAILURE environment variable.\n"));
|
||||
|
||||
typedef cl::list<std::string>::const_iterator prefix_iterator;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -98,6 +120,7 @@ enum CheckType {
|
||||
CheckNot,
|
||||
CheckDAG,
|
||||
CheckLabel,
|
||||
CheckEmpty,
|
||||
|
||||
/// Indicates the pattern only matches the end of file. This is used for
|
||||
/// trailing CHECK-NOTs.
|
||||
@ -146,8 +169,11 @@ public:
|
||||
unsigned LineNumber);
|
||||
size_t Match(StringRef Buffer, size_t &MatchLen,
|
||||
StringMap<StringRef> &VariableTable) const;
|
||||
void PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
|
||||
const StringMap<StringRef> &VariableTable) const;
|
||||
void PrintVariableUses(const SourceMgr &SM, StringRef Buffer,
|
||||
const StringMap<StringRef> &VariableTable,
|
||||
SMRange MatchRange = None) const;
|
||||
void PrintFuzzyMatch(const SourceMgr &SM, StringRef Buffer,
|
||||
const StringMap<StringRef> &VariableTable) const;
|
||||
|
||||
bool hasVariable() const {
|
||||
return !(VariableUses.empty() && VariableDefs.empty());
|
||||
@ -185,12 +211,25 @@ bool Pattern::ParsePattern(StringRef PatternStr, StringRef Prefix,
|
||||
PatternStr = PatternStr.substr(0, PatternStr.size() - 1);
|
||||
|
||||
// Check that there is something on the line.
|
||||
if (PatternStr.empty()) {
|
||||
if (PatternStr.empty() && CheckTy != Check::CheckEmpty) {
|
||||
SM.PrintMessage(PatternLoc, SourceMgr::DK_Error,
|
||||
"found empty check string with prefix '" + Prefix + ":'");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!PatternStr.empty() && CheckTy == Check::CheckEmpty) {
|
||||
SM.PrintMessage(
|
||||
PatternLoc, SourceMgr::DK_Error,
|
||||
"found non-empty check string for empty check with prefix '" + Prefix +
|
||||
":'");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (CheckTy == Check::CheckEmpty) {
|
||||
RegExStr = "(\n$)";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check to see if this is a fixed string, or if it has regex pieces.
|
||||
if (!MatchFullLinesHere &&
|
||||
(PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos &&
|
||||
@ -463,8 +502,12 @@ size_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
|
||||
VariableTable[VariableDef.first] = MatchInfo[VariableDef.second];
|
||||
}
|
||||
|
||||
MatchLen = FullMatch.size();
|
||||
return FullMatch.data() - Buffer.data();
|
||||
// Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after
|
||||
// the required preceding newline, which is consumed by the pattern in the
|
||||
// case of CHECK-EMPTY but not CHECK-NEXT.
|
||||
size_t MatchStartSkip = CheckTy == Check::CheckEmpty;
|
||||
MatchLen = FullMatch.size() - MatchStartSkip;
|
||||
return FullMatch.data() - Buffer.data() + MatchStartSkip;
|
||||
}
|
||||
|
||||
|
||||
@ -490,11 +533,9 @@ Pattern::ComputeMatchDistance(StringRef Buffer,
|
||||
return BufferPrefix.edit_distance(ExampleString);
|
||||
}
|
||||
|
||||
/// Prints additional information about a failure to match involving this
|
||||
/// pattern.
|
||||
void Pattern::PrintFailureInfo(
|
||||
const SourceMgr &SM, StringRef Buffer,
|
||||
const StringMap<StringRef> &VariableTable) const {
|
||||
void Pattern::PrintVariableUses(const SourceMgr &SM, StringRef Buffer,
|
||||
const StringMap<StringRef> &VariableTable,
|
||||
SMRange MatchRange) const {
|
||||
// If this was a regular expression using variables, print the current
|
||||
// variable values.
|
||||
if (!VariableUses.empty()) {
|
||||
@ -526,11 +567,19 @@ void Pattern::PrintFailureInfo(
|
||||
}
|
||||
}
|
||||
|
||||
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
|
||||
OS.str());
|
||||
if (MatchRange.isValid())
|
||||
SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, OS.str(),
|
||||
{MatchRange});
|
||||
else
|
||||
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
|
||||
SourceMgr::DK_Note, OS.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Pattern::PrintFuzzyMatch(
|
||||
const SourceMgr &SM, StringRef Buffer,
|
||||
const StringMap<StringRef> &VariableTable) const {
|
||||
// Attempt to find the closest/best fuzzy match. Usually an error happens
|
||||
// because some string in the output didn't exactly match. In these cases, we
|
||||
// would like to show the user a best guess at what "should have" matched, to
|
||||
@ -710,6 +759,9 @@ static size_t CheckTypeSize(Check::CheckType Ty) {
|
||||
case Check::CheckLabel:
|
||||
return sizeof("-LABEL:") - 1;
|
||||
|
||||
case Check::CheckEmpty:
|
||||
return sizeof("-EMPTY:") - 1;
|
||||
|
||||
case Check::CheckEOF:
|
||||
llvm_unreachable("Should not be using EOF size");
|
||||
}
|
||||
@ -717,7 +769,37 @@ static size_t CheckTypeSize(Check::CheckType Ty) {
|
||||
llvm_unreachable("Bad check type");
|
||||
}
|
||||
|
||||
// Get a description of the type.
|
||||
static std::string CheckTypeName(StringRef Prefix, Check::CheckType Ty) {
|
||||
switch (Ty) {
|
||||
case Check::CheckNone:
|
||||
return "invalid";
|
||||
case Check::CheckPlain:
|
||||
return Prefix;
|
||||
case Check::CheckNext:
|
||||
return Prefix.str() + "-NEXT";
|
||||
case Check::CheckSame:
|
||||
return Prefix.str() + "-SAME";
|
||||
case Check::CheckNot:
|
||||
return Prefix.str() + "-NOT";
|
||||
case Check::CheckDAG:
|
||||
return Prefix.str() + "-DAG";
|
||||
case Check::CheckLabel:
|
||||
return Prefix.str() + "-LABEL";
|
||||
case Check::CheckEmpty:
|
||||
return Prefix.str() + "-EMPTY";
|
||||
case Check::CheckEOF:
|
||||
return "implicit EOF";
|
||||
case Check::CheckBadNot:
|
||||
return "bad NOT";
|
||||
}
|
||||
llvm_unreachable("unknown CheckType");
|
||||
}
|
||||
|
||||
static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
|
||||
if (Buffer.size() <= Prefix.size())
|
||||
return Check::CheckNone;
|
||||
|
||||
char NextChar = Buffer[Prefix.size()];
|
||||
|
||||
// Verify that the : is present after the prefix.
|
||||
@ -743,10 +825,14 @@ static Check::CheckType FindCheckType(StringRef Buffer, StringRef Prefix) {
|
||||
if (Rest.startswith("LABEL:"))
|
||||
return Check::CheckLabel;
|
||||
|
||||
if (Rest.startswith("EMPTY:"))
|
||||
return Check::CheckEmpty;
|
||||
|
||||
// You can't combine -NOT with another suffix.
|
||||
if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") ||
|
||||
Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") ||
|
||||
Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:"))
|
||||
Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:") ||
|
||||
Rest.startswith("EMPTY-NOT:") || Rest.startswith("NOT-EMPTY:"))
|
||||
return Check::CheckBadNot;
|
||||
|
||||
return Check::CheckNone;
|
||||
@ -906,10 +992,13 @@ static bool ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
|
||||
|
||||
Buffer = Buffer.substr(EOL);
|
||||
|
||||
// Verify that CHECK-NEXT lines have at least one CHECK line before them.
|
||||
if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame) &&
|
||||
// Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them.
|
||||
if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame ||
|
||||
CheckTy == Check::CheckEmpty) &&
|
||||
CheckStrings.empty()) {
|
||||
StringRef Type = CheckTy == Check::CheckNext ? "NEXT" : "SAME";
|
||||
StringRef Type = CheckTy == Check::CheckNext
|
||||
? "NEXT"
|
||||
: CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME";
|
||||
SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart),
|
||||
SourceMgr::DK_Error,
|
||||
"found '" + UsedPrefix + "-" + Type +
|
||||
@ -956,12 +1045,49 @@ static bool ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void PrintCheckFailed(const SourceMgr &SM, SMLoc Loc, const Pattern &Pat,
|
||||
StringRef Buffer,
|
||||
StringMap<StringRef> &VariableTable) {
|
||||
static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
|
||||
StringRef Prefix, SMLoc Loc, const Pattern &Pat,
|
||||
StringRef Buffer, StringMap<StringRef> &VariableTable,
|
||||
size_t MatchPos, size_t MatchLen) {
|
||||
if (ExpectedMatch) {
|
||||
if (!Verbose)
|
||||
return;
|
||||
if (!VerboseVerbose && Pat.getCheckTy() == Check::CheckEOF)
|
||||
return;
|
||||
}
|
||||
SMLoc MatchStart = SMLoc::getFromPointer(Buffer.data() + MatchPos);
|
||||
SMLoc MatchEnd = SMLoc::getFromPointer(Buffer.data() + MatchPos + MatchLen);
|
||||
SMRange MatchRange(MatchStart, MatchEnd);
|
||||
SM.PrintMessage(
|
||||
Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error,
|
||||
CheckTypeName(Prefix, Pat.getCheckTy()) + ": " +
|
||||
(ExpectedMatch ? "expected" : "excluded") +
|
||||
" string found in input");
|
||||
SM.PrintMessage(MatchStart, SourceMgr::DK_Note, "found here", {MatchRange});
|
||||
Pat.PrintVariableUses(SM, Buffer, VariableTable, MatchRange);
|
||||
}
|
||||
|
||||
static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM,
|
||||
const CheckString &CheckStr, StringRef Buffer,
|
||||
StringMap<StringRef> &VariableTable, size_t MatchPos,
|
||||
size_t MatchLen) {
|
||||
PrintMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
|
||||
Buffer, VariableTable, MatchPos, MatchLen);
|
||||
}
|
||||
|
||||
static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
|
||||
StringRef Prefix, SMLoc Loc, const Pattern &Pat,
|
||||
StringRef Buffer,
|
||||
StringMap<StringRef> &VariableTable) {
|
||||
if (!ExpectedMatch && !VerboseVerbose)
|
||||
return;
|
||||
|
||||
// Otherwise, we have an error, emit an error message.
|
||||
SM.PrintMessage(Loc, SourceMgr::DK_Error,
|
||||
"expected string not found in input");
|
||||
SM.PrintMessage(Loc,
|
||||
ExpectedMatch ? SourceMgr::DK_Error : SourceMgr::DK_Remark,
|
||||
CheckTypeName(Prefix, Pat.getCheckTy()) + ": " +
|
||||
(ExpectedMatch ? "expected" : "excluded") +
|
||||
" string not found in input");
|
||||
|
||||
// Print the "scanning from here" line. If the current position is at the
|
||||
// end of a line, advance to the start of the next line.
|
||||
@ -971,13 +1097,16 @@ static void PrintCheckFailed(const SourceMgr &SM, SMLoc Loc, const Pattern &Pat,
|
||||
"scanning from here");
|
||||
|
||||
// Allow the pattern to print additional information if desired.
|
||||
Pat.PrintFailureInfo(SM, Buffer, VariableTable);
|
||||
Pat.PrintVariableUses(SM, Buffer, VariableTable);
|
||||
if (ExpectedMatch)
|
||||
Pat.PrintFuzzyMatch(SM, Buffer, VariableTable);
|
||||
}
|
||||
|
||||
static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
|
||||
StringRef Buffer,
|
||||
StringMap<StringRef> &VariableTable) {
|
||||
PrintCheckFailed(SM, CheckStr.Loc, CheckStr.Pat, Buffer, VariableTable);
|
||||
static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM,
|
||||
const CheckString &CheckStr, StringRef Buffer,
|
||||
StringMap<StringRef> &VariableTable) {
|
||||
PrintNoMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat,
|
||||
Buffer, VariableTable);
|
||||
}
|
||||
|
||||
/// Count the number of newlines in the specified range.
|
||||
@ -1025,9 +1154,10 @@ size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
|
||||
StringRef MatchBuffer = Buffer.substr(LastPos);
|
||||
size_t MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
|
||||
if (MatchPos == StringRef::npos) {
|
||||
PrintCheckFailed(SM, *this, MatchBuffer, VariableTable);
|
||||
PrintNoMatch(true, SM, *this, MatchBuffer, VariableTable);
|
||||
return StringRef::npos;
|
||||
}
|
||||
PrintMatch(true, SM, *this, MatchBuffer, VariableTable, MatchPos, MatchLen);
|
||||
|
||||
// Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT
|
||||
// or CHECK-NOT
|
||||
@ -1055,22 +1185,27 @@ size_t CheckString::Check(const SourceMgr &SM, StringRef Buffer,
|
||||
|
||||
/// Verify there is a single line in the given buffer.
|
||||
bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
|
||||
if (Pat.getCheckTy() != Check::CheckNext)
|
||||
if (Pat.getCheckTy() != Check::CheckNext &&
|
||||
Pat.getCheckTy() != Check::CheckEmpty)
|
||||
return false;
|
||||
|
||||
Twine CheckName =
|
||||
Prefix +
|
||||
Twine(Pat.getCheckTy() == Check::CheckEmpty ? "-EMPTY" : "-NEXT");
|
||||
|
||||
// Count the number of newlines between the previous match and this one.
|
||||
assert(Buffer.data() !=
|
||||
SM.getMemoryBuffer(SM.FindBufferContainingLoc(
|
||||
SMLoc::getFromPointer(Buffer.data())))
|
||||
->getBufferStart() &&
|
||||
"CHECK-NEXT can't be the first check in a file");
|
||||
"CHECK-NEXT and CHECK-EMPTY can't be the first check in a file");
|
||||
|
||||
const char *FirstNewLine = nullptr;
|
||||
unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine);
|
||||
|
||||
if (NumNewLines == 0) {
|
||||
SM.PrintMessage(Loc, SourceMgr::DK_Error,
|
||||
Prefix + "-NEXT: is on the same line as previous match");
|
||||
CheckName + ": is on the same line as previous match");
|
||||
SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
|
||||
"'next' match was here");
|
||||
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
|
||||
@ -1080,8 +1215,8 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const {
|
||||
|
||||
if (NumNewLines != 1) {
|
||||
SM.PrintMessage(Loc, SourceMgr::DK_Error,
|
||||
Prefix +
|
||||
"-NEXT: is not on the line after the previous match");
|
||||
CheckName +
|
||||
": is not on the line after the previous match");
|
||||
SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note,
|
||||
"'next' match was here");
|
||||
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note,
|
||||
@ -1133,13 +1268,15 @@ bool CheckString::CheckNot(const SourceMgr &SM, StringRef Buffer,
|
||||
size_t MatchLen = 0;
|
||||
size_t Pos = Pat->Match(Buffer, MatchLen, VariableTable);
|
||||
|
||||
if (Pos == StringRef::npos)
|
||||
if (Pos == StringRef::npos) {
|
||||
PrintNoMatch(false, SM, Prefix, Pat->getLoc(), *Pat, Buffer,
|
||||
VariableTable);
|
||||
continue;
|
||||
}
|
||||
|
||||
PrintMatch(false, SM, Prefix, Pat->getLoc(), *Pat, Buffer, VariableTable,
|
||||
Pos, MatchLen);
|
||||
|
||||
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + Pos),
|
||||
SourceMgr::DK_Error, Prefix + "-NOT: string occurred!");
|
||||
SM.PrintMessage(Pat->getLoc(), SourceMgr::DK_Note,
|
||||
Prefix + "-NOT: pattern specified here");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1153,10 +1290,23 @@ size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
|
||||
if (DagNotStrings.empty())
|
||||
return 0;
|
||||
|
||||
size_t LastPos = 0;
|
||||
size_t StartPos = LastPos;
|
||||
// The start of the search range.
|
||||
size_t StartPos = 0;
|
||||
|
||||
for (const Pattern &Pat : DagNotStrings) {
|
||||
struct MatchRange {
|
||||
size_t Pos;
|
||||
size_t End;
|
||||
};
|
||||
// A sorted list of ranges for non-overlapping CHECK-DAG matches. Match
|
||||
// ranges are erased from this list once they are no longer in the search
|
||||
// range.
|
||||
std::list<MatchRange> MatchRanges;
|
||||
|
||||
// We need PatItr and PatEnd later for detecting the end of a CHECK-DAG
|
||||
// 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;
|
||||
assert((Pat.getCheckTy() == Check::CheckDAG ||
|
||||
Pat.getCheckTy() == Check::CheckNot) &&
|
||||
"Invalid CHECK-DAG or CHECK-NOT!");
|
||||
@ -1168,57 +1318,92 @@ size_t CheckString::CheckDag(const SourceMgr &SM, StringRef Buffer,
|
||||
|
||||
assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!");
|
||||
|
||||
size_t MatchLen = 0, MatchPos;
|
||||
|
||||
// CHECK-DAG always matches from the start.
|
||||
StringRef MatchBuffer = Buffer.substr(StartPos);
|
||||
MatchPos = Pat.Match(MatchBuffer, MatchLen, VariableTable);
|
||||
// With a group of CHECK-DAGs, a single mismatching means the match on
|
||||
// that group of CHECK-DAGs fails immediately.
|
||||
if (MatchPos == StringRef::npos) {
|
||||
PrintCheckFailed(SM, Pat.getLoc(), Pat, MatchBuffer, VariableTable);
|
||||
return StringRef::npos;
|
||||
}
|
||||
// Re-calc it as the offset relative to the start of the original string.
|
||||
MatchPos += StartPos;
|
||||
size_t MatchLen = 0, MatchPos = StartPos;
|
||||
|
||||
if (!NotStrings.empty()) {
|
||||
if (MatchPos < LastPos) {
|
||||
// Reordered?
|
||||
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + MatchPos),
|
||||
SourceMgr::DK_Error,
|
||||
Prefix + "-DAG: found a match of CHECK-DAG"
|
||||
" reordering across a CHECK-NOT");
|
||||
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data() + LastPos),
|
||||
SourceMgr::DK_Note,
|
||||
Prefix + "-DAG: the farthest match of CHECK-DAG"
|
||||
" is found here");
|
||||
SM.PrintMessage(NotStrings[0]->getLoc(), SourceMgr::DK_Note,
|
||||
Prefix + "-NOT: the crossed pattern specified"
|
||||
" here");
|
||||
SM.PrintMessage(Pat.getLoc(), SourceMgr::DK_Note,
|
||||
Prefix + "-DAG: the reordered pattern specified"
|
||||
" here");
|
||||
// Search for a match that doesn't overlap a previous match in this
|
||||
// CHECK-DAG group.
|
||||
for (auto MI = MatchRanges.begin(), ME = MatchRanges.end(); true; ++MI) {
|
||||
StringRef MatchBuffer = Buffer.substr(MatchPos);
|
||||
size_t MatchPosBuf = Pat.Match(MatchBuffer, MatchLen, VariableTable);
|
||||
// With a group of CHECK-DAGs, a single mismatching means the match on
|
||||
// that group of CHECK-DAGs fails immediately.
|
||||
if (MatchPosBuf == StringRef::npos) {
|
||||
PrintNoMatch(true, SM, Prefix, Pat.getLoc(), Pat, MatchBuffer,
|
||||
VariableTable);
|
||||
return StringRef::npos;
|
||||
}
|
||||
// All subsequent CHECK-DAGs should be matched from the farthest
|
||||
// position of all precedent CHECK-DAGs (including this one.)
|
||||
StartPos = LastPos;
|
||||
// If there's CHECK-NOTs between two CHECK-DAGs or from CHECK to
|
||||
// CHECK-DAG, verify that there's no 'not' strings occurred in that
|
||||
// region.
|
||||
StringRef SkippedRegion = Buffer.slice(LastPos, MatchPos);
|
||||
if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
|
||||
return StringRef::npos;
|
||||
// Clear "not strings".
|
||||
NotStrings.clear();
|
||||
// Re-calc it as the offset relative to the start of the original string.
|
||||
MatchPos += MatchPosBuf;
|
||||
if (VerboseVerbose)
|
||||
PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, Buffer, VariableTable,
|
||||
MatchPos, MatchLen);
|
||||
MatchRange M{MatchPos, MatchPos + MatchLen};
|
||||
if (AllowDeprecatedDagOverlap) {
|
||||
// We don't need to track all matches in this mode, so we just maintain
|
||||
// one match range that encompasses the current CHECK-DAG group's
|
||||
// matches.
|
||||
if (MatchRanges.empty())
|
||||
MatchRanges.insert(MatchRanges.end(), M);
|
||||
else {
|
||||
auto Block = MatchRanges.begin();
|
||||
Block->Pos = std::min(Block->Pos, M.Pos);
|
||||
Block->End = std::max(Block->End, M.End);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Iterate previous matches until overlapping match or insertion point.
|
||||
bool Overlap = false;
|
||||
for (; MI != ME; ++MI) {
|
||||
if (M.Pos < MI->End) {
|
||||
// !Overlap => New match has no overlap and is before this old match.
|
||||
// Overlap => New match overlaps this old match.
|
||||
Overlap = MI->Pos < M.End;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!Overlap) {
|
||||
// Insert non-overlapping match into list.
|
||||
MatchRanges.insert(MI, M);
|
||||
break;
|
||||
}
|
||||
if (VerboseVerbose) {
|
||||
SMLoc OldStart = SMLoc::getFromPointer(Buffer.data() + MI->Pos);
|
||||
SMLoc OldEnd = SMLoc::getFromPointer(Buffer.data() + MI->End);
|
||||
SMRange OldRange(OldStart, OldEnd);
|
||||
SM.PrintMessage(OldStart, SourceMgr::DK_Note,
|
||||
"match discarded, overlaps earlier DAG match here",
|
||||
{OldRange});
|
||||
}
|
||||
MatchPos = MI->End;
|
||||
}
|
||||
if (!VerboseVerbose)
|
||||
PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, Buffer, VariableTable,
|
||||
MatchPos, MatchLen);
|
||||
|
||||
// Update the last position with CHECK-DAG matches.
|
||||
LastPos = std::max(MatchPos + MatchLen, LastPos);
|
||||
// Handle the end of a CHECK-DAG group.
|
||||
if (std::next(PatItr) == PatEnd ||
|
||||
std::next(PatItr)->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
|
||||
// region.
|
||||
StringRef SkippedRegion =
|
||||
Buffer.slice(StartPos, MatchRanges.begin()->Pos);
|
||||
if (CheckNot(SM, SkippedRegion, NotStrings, VariableTable))
|
||||
return StringRef::npos;
|
||||
// Clear "not strings".
|
||||
NotStrings.clear();
|
||||
}
|
||||
// All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the
|
||||
// end of this CHECK-DAG group's match range.
|
||||
StartPos = MatchRanges.rbegin()->End;
|
||||
// Don't waste time checking for (impossible) overlaps before that.
|
||||
MatchRanges.clear();
|
||||
}
|
||||
}
|
||||
|
||||
return LastPos;
|
||||
return StartPos;
|
||||
}
|
||||
|
||||
// A check prefix must contain only alphanumeric, hyphens and underscores.
|
||||
@ -1357,8 +1542,7 @@ bool CheckInput(SourceMgr &SM, StringRef Buffer,
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
sys::PrintStackTraceOnErrorSignal(argv[0]);
|
||||
PrettyStackTraceProgram X(argc, argv);
|
||||
InitLLVM X(argc, argv);
|
||||
cl::ParseCommandLineOptions(argc, argv);
|
||||
|
||||
if (!ValidateCheckPrefixes()) {
|
||||
@ -1379,6 +1563,9 @@ int main(int argc, char **argv) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (VerboseVerbose)
|
||||
Verbose = true;
|
||||
|
||||
SourceMgr SM;
|
||||
|
||||
// Read the expected strings from the check file.
|
||||
@ -1425,5 +1612,9 @@ int main(int argc, char **argv) {
|
||||
InputFileText, InputFile.getBufferIdentifier()),
|
||||
SMLoc());
|
||||
|
||||
return CheckInput(SM, InputFileText, CheckStrings) ? EXIT_SUCCESS : 1;
|
||||
int ExitCode = CheckInput(SM, InputFileText, CheckStrings) ? EXIT_SUCCESS : 1;
|
||||
if (ExitCode == 1 && DumpInputOnFailure)
|
||||
errs() << "Full input was:\n<<<<<<\n" << InputFileText << "\n>>>>>>\n";
|
||||
|
||||
return ExitCode;
|
||||
}
|
||||
|
@ -1,3 +1,8 @@
|
||||
-------------------------------------------------------------------
|
||||
Mon Oct 29 16:28:27 UTC 2018 - Jiri Slaby <jslaby@suse.com>
|
||||
|
||||
- switch to LLVM 7
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Sat Oct 27 07:24:23 UTC 2018 - opensuse-packaging@opensuse.org
|
||||
|
||||
|
@ -12,11 +12,11 @@
|
||||
# license that conforms to the Open Source Definition (Version 1.9)
|
||||
# published by the Open Source Initiative.
|
||||
|
||||
# Please submit bugfixes or comments via http://bugs.opensuse.org/
|
||||
# Please submit bugfixes or comments via https://bugs.opensuse.org/
|
||||
#
|
||||
|
||||
|
||||
%define llvm_version_major 6
|
||||
%define llvm_version_major 7
|
||||
%define llvm_version_minor 0
|
||||
%define llvm_version %{llvm_version_major}
|
||||
|
||||
|
6
not.cpp
6
not.cpp
@ -38,8 +38,12 @@ int main(int argc, const char **argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<StringRef> Argv;
|
||||
Argv.reserve(argc);
|
||||
for (int i = 0; i < argc; ++i)
|
||||
Argv.push_back(argv[i]);
|
||||
std::string ErrMsg;
|
||||
int Result = sys::ExecuteAndWait(*Program, argv, nullptr, {}, 0, 0, &ErrMsg);
|
||||
int Result = sys::ExecuteAndWait(*Program, Argv, None, {}, 0, 0, &ErrMsg);
|
||||
#ifdef _WIN32
|
||||
// Handle abort() in msvcrt -- It has exit code as 3. abort(), aka
|
||||
// unreachable, should be recognized as a crash. However, some binaries use
|
||||
|
Loading…
x
Reference in New Issue
Block a user