diff options
Diffstat (limited to 'llvm/lib/FileCheck/FileCheck.cpp')
-rw-r--r-- | llvm/lib/FileCheck/FileCheck.cpp | 54 |
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. |