aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/FileCheck/FileCheck.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/FileCheck/FileCheck.cpp')
-rw-r--r--llvm/lib/FileCheck/FileCheck.cpp54
1 files changed, 48 insertions, 6 deletions
diff --git a/llvm/lib/FileCheck/FileCheck.cpp b/llvm/lib/FileCheck/FileCheck.cpp
index bcca499..b79f6ec 100644
--- a/llvm/lib/FileCheck/FileCheck.cpp
+++ b/llvm/lib/FileCheck/FileCheck.cpp
@@ -264,7 +264,7 @@ BinaryOperation::getImplicitFormat(const SourceMgr &SM) const {
: *RightFormat;
}
-Expected<std::string> NumericSubstitution::getResult() const {
+Expected<std::string> NumericSubstitution::getResultRegex() const {
assert(ExpressionPointer->getAST() != nullptr &&
"Substituting empty expression");
Expected<APInt> EvaluatedValue = ExpressionPointer->getAST()->eval();
@@ -274,7 +274,18 @@ Expected<std::string> NumericSubstitution::getResult() const {
return Format.getMatchingString(*EvaluatedValue);
}
-Expected<std::string> StringSubstitution::getResult() const {
+Expected<std::string> NumericSubstitution::getResultForDiagnostics() const {
+ // The "regex" returned by getResultRegex() is just a numeric value
+ // like '42', '0x2A', '-17', 'DEADBEEF' etc. This is already suitable for use
+ // in diagnostics.
+ Expected<std::string> Literal = getResultRegex();
+ if (!Literal)
+ return Literal;
+
+ return "\"" + std::move(*Literal) + "\"";
+}
+
+Expected<std::string> StringSubstitution::getResultRegex() const {
// Look up the value and escape it so that we can put it into the regex.
Expected<StringRef> VarVal = Context->getPatternVarValue(FromStr);
if (!VarVal)
@@ -282,6 +293,36 @@ Expected<std::string> StringSubstitution::getResult() const {
return Regex::escape(*VarVal);
}
+Expected<std::string> StringSubstitution::getResultForDiagnostics() const {
+ Expected<StringRef> VarVal = Context->getPatternVarValue(FromStr);
+ if (!VarVal)
+ return VarVal.takeError();
+
+ std::string Result;
+ Result.reserve(VarVal->size() + 2);
+ raw_string_ostream OS(Result);
+
+ OS << '"';
+ // Escape the string if it contains any characters that
+ // make it hard to read, such as non-printable characters (including all
+ // whitespace except space) and double quotes. These are the characters that
+ // are escaped by write_escaped(), except we do not include backslashes,
+ // because they are common in Windows paths and escaping them would make the
+ // output harder to read. However, when we do escape, backslashes are escaped
+ // as well, otherwise the output would be ambiguous.
+ const bool NeedsEscaping =
+ llvm::any_of(*VarVal, [](char C) { return !isPrint(C) || C == '"'; });
+ if (NeedsEscaping)
+ OS.write_escaped(*VarVal);
+ else
+ OS << *VarVal;
+ OS << '"';
+ if (NeedsEscaping)
+ OS << " (escaped value)";
+
+ return Result;
+}
+
bool Pattern::isValidVarNameStart(char C) { return C == '_' || isAlpha(C); }
Expected<Pattern::VariableProperties>
@@ -1106,7 +1147,7 @@ Pattern::MatchResult Pattern::match(StringRef Buffer,
Error Errs = Error::success();
for (const auto &Substitution : Substitutions) {
// Substitute and check for failure (e.g. use of undefined variable).
- Expected<std::string> Value = Substitution->getResult();
+ Expected<std::string> Value = Substitution->getResultRegex();
if (!Value) {
// Convert to an ErrorDiagnostic to get location information. This is
// done here rather than printMatch/printNoMatch since now we know which
@@ -1210,7 +1251,8 @@ void Pattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,
SmallString<256> Msg;
raw_svector_ostream OS(Msg);
- Expected<std::string> MatchedValue = Substitution->getResult();
+ Expected<std::string> MatchedValue =
+ Substitution->getResultForDiagnostics();
// Substitution failures are handled in printNoMatch().
if (!MatchedValue) {
consumeError(MatchedValue.takeError());
@@ -1218,8 +1260,8 @@ void Pattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer,
}
OS << "with \"";
- OS.write_escaped(Substitution->getFromString()) << "\" equal to \"";
- OS.write_escaped(*MatchedValue) << "\"";
+ OS.write_escaped(Substitution->getFromString()) << "\" equal to ";
+ OS << *MatchedValue;
// We report only the start of the match/search range to suggest we are
// reporting the substitutions as set at the start of the match/search.