mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-29 22:30:33 +00:00
[YAML] Add support for non-printable characters
LLVM IR function names which disable mangling start with '\01' (https://www.llvm.org/docs/LangRef.html#identifiers). When an identifier like "\01@abc@" gets dumped to MIR, it is quoted, but only with single quotes. http://www.yaml.org/spec/1.2/spec.html#id2770814: "The allowed character range explicitly excludes the C0 control block allowed), the surrogate block #xD800-#xDFFF, #xFFFE, and #xFFFF." http://www.yaml.org/spec/1.2/spec.html#id2776092: "All non-printable characters must be escaped. [...] Note that escape sequences are only interpreted in double-quoted scalars." This patch adds support for printing escaped non-printable characters between double quotes if needed. Should also fix PR31743. Differential Revision: https://reviews.llvm.org/D41290 llvm-svn: 320996
This commit is contained in:
parent
3b753d324c
commit
061acf9c7f
@ -466,7 +466,7 @@ looks like:
|
||||
return StringRef();
|
||||
}
|
||||
// Determine if this scalar needs quotes.
|
||||
static bool mustQuote(StringRef) { return true; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
|
||||
};
|
||||
|
||||
Block Scalars
|
||||
|
@ -56,7 +56,7 @@ template <> struct ScalarTraits<StringValue> {
|
||||
return "";
|
||||
}
|
||||
|
||||
static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
|
||||
static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
|
||||
};
|
||||
|
||||
struct FlowStringValue : StringValue {
|
||||
@ -73,7 +73,7 @@ template <> struct ScalarTraits<FlowStringValue> {
|
||||
return ScalarTraits<StringValue>::input(Scalar, Ctx, S);
|
||||
}
|
||||
|
||||
static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
|
||||
static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
|
||||
};
|
||||
|
||||
struct BlockStringValue {
|
||||
@ -120,7 +120,7 @@ template <> struct ScalarTraits<UnsignedValue> {
|
||||
return ScalarTraits<unsigned>::input(Scalar, Ctx, Value.Value);
|
||||
}
|
||||
|
||||
static bool mustQuote(StringRef Scalar) {
|
||||
static QuotingType mustQuote(StringRef Scalar) {
|
||||
return ScalarTraits<unsigned>::mustQuote(Scalar);
|
||||
}
|
||||
};
|
||||
|
@ -56,7 +56,7 @@ ArrayRef<uint8_t> toDebugH(const DebugHSection &DebugH,
|
||||
} // end namespace llvm
|
||||
|
||||
LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::DebugHSection)
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(CodeViewYAML::GlobalHash, false)
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(CodeViewYAML::GlobalHash, QuotingType::None)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(CodeViewYAML::GlobalHash)
|
||||
|
||||
#endif // LLVM_OBJECTYAML_CODEVIEWYAMLTYPES_H
|
||||
|
@ -58,7 +58,7 @@ ArrayRef<uint8_t> toDebugT(ArrayRef<LeafRecord>, BumpPtrAllocator &Alloc);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(codeview::GUID, true)
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(codeview::GUID, QuotingType::Single)
|
||||
|
||||
LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::LeafRecord)
|
||||
LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::MemberRecord)
|
||||
|
@ -261,7 +261,7 @@ using char_16 = char[16];
|
||||
template <> struct ScalarTraits<char_16> {
|
||||
static void output(const char_16 &Val, void *, raw_ostream &Out);
|
||||
static StringRef input(StringRef Scalar, void *, char_16 &Val);
|
||||
static bool mustQuote(StringRef S);
|
||||
static QuotingType mustQuote(StringRef S);
|
||||
};
|
||||
|
||||
// This trait is used for UUIDs. It reads and writes them matching otool's
|
||||
@ -271,7 +271,7 @@ using uuid_t = raw_ostream::uuid_t;
|
||||
template <> struct ScalarTraits<uuid_t> {
|
||||
static void output(const uuid_t &Val, void *, raw_ostream &Out);
|
||||
static StringRef input(StringRef Scalar, void *, uuid_t &Val);
|
||||
static bool mustQuote(StringRef S);
|
||||
static QuotingType mustQuote(StringRef S);
|
||||
};
|
||||
|
||||
// Load Command struct mapping traits
|
||||
|
@ -107,7 +107,7 @@ inline bool operator==(const BinaryRef &LHS, const BinaryRef &RHS) {
|
||||
template <> struct ScalarTraits<BinaryRef> {
|
||||
static void output(const BinaryRef &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, BinaryRef &);
|
||||
static bool mustQuote(StringRef S) { return needsQuotes(S); }
|
||||
static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
|
||||
};
|
||||
|
||||
} // end namespace yaml
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
@ -117,6 +118,11 @@ struct ScalarBitSetTraits {
|
||||
// static void bitset(IO &io, T &value);
|
||||
};
|
||||
|
||||
/// Describe which type of quotes should be used when quoting is necessary.
|
||||
/// Some non-printable characters need to be double-quoted, while some others
|
||||
/// are fine with simple-quoting, and some don't need any quoting.
|
||||
enum class QuotingType { None, Single, Double };
|
||||
|
||||
/// This class should be specialized by type that requires custom conversion
|
||||
/// to/from a yaml scalar. For example:
|
||||
///
|
||||
@ -131,7 +137,7 @@ struct ScalarBitSetTraits {
|
||||
/// // return empty string on success, or error string
|
||||
/// return StringRef();
|
||||
/// }
|
||||
/// static bool mustQuote(StringRef) { return true; }
|
||||
/// static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
|
||||
/// };
|
||||
template<typename T>
|
||||
struct ScalarTraits {
|
||||
@ -145,7 +151,7 @@ struct ScalarTraits {
|
||||
//static StringRef input(StringRef scalar, void *ctxt, T &value);
|
||||
//
|
||||
// Function to determine if the value should be quoted.
|
||||
//static bool mustQuote(StringRef);
|
||||
//static QuotingType mustQuote(StringRef);
|
||||
};
|
||||
|
||||
/// This class should be specialized by type that requires custom conversion
|
||||
@ -270,7 +276,7 @@ struct has_ScalarTraits
|
||||
{
|
||||
using Signature_input = StringRef (*)(StringRef, void*, T&);
|
||||
using Signature_output = void (*)(const T&, void*, raw_ostream&);
|
||||
using Signature_mustQuote = bool (*)(StringRef);
|
||||
using Signature_mustQuote = QuotingType (*)(StringRef);
|
||||
|
||||
template <typename U>
|
||||
static char test(SameType<Signature_input, &U::input> *,
|
||||
@ -495,28 +501,66 @@ inline bool isBool(StringRef S) {
|
||||
S.equals("false") || S.equals("False") || S.equals("FALSE");
|
||||
}
|
||||
|
||||
inline bool needsQuotes(StringRef S) {
|
||||
// 5.1. Character Set
|
||||
// The allowed character range explicitly excludes the C0 control block #x0-#x1F
|
||||
// (except for TAB #x9, LF #xA, and CR #xD which are allowed), DEL #x7F, the C1
|
||||
// control block #x80-#x9F (except for NEL #x85 which is allowed), the surrogate
|
||||
// block #xD800-#xDFFF, #xFFFE, and #xFFFF.
|
||||
inline QuotingType needsQuotes(StringRef S) {
|
||||
if (S.empty())
|
||||
return true;
|
||||
return QuotingType::Single;
|
||||
if (isspace(S.front()) || isspace(S.back()))
|
||||
return true;
|
||||
return QuotingType::Single;
|
||||
if (S.front() == ',')
|
||||
return true;
|
||||
|
||||
static const char ScalarSafeChars[] =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-/^., \t";
|
||||
if (S.find_first_not_of(ScalarSafeChars) != StringRef::npos)
|
||||
return true;
|
||||
|
||||
return QuotingType::Single;
|
||||
if (isNull(S))
|
||||
return true;
|
||||
return QuotingType::Single;
|
||||
if (isBool(S))
|
||||
return true;
|
||||
return QuotingType::Single;
|
||||
if (isNumeric(S))
|
||||
return true;
|
||||
return QuotingType::Single;
|
||||
|
||||
return false;
|
||||
QuotingType MaxQuotingNeeded = QuotingType::None;
|
||||
for (unsigned char C : S) {
|
||||
// Alphanum is safe.
|
||||
if (isAlnum(C))
|
||||
continue;
|
||||
|
||||
switch (C) {
|
||||
// Safe scalar characters.
|
||||
case '_':
|
||||
case '-':
|
||||
case '/':
|
||||
case '^':
|
||||
case '.':
|
||||
case ',':
|
||||
case ' ':
|
||||
// TAB (0x9), LF (0xA), CR (0xD) and NEL (0x85) are allowed.
|
||||
case 0x9:
|
||||
case 0xA:
|
||||
case 0xD:
|
||||
case 0x85:
|
||||
continue;
|
||||
// DEL (0x7F) are excluded from the allowed character range.
|
||||
case 0x7F:
|
||||
return QuotingType::Double;
|
||||
default: {
|
||||
// C0 control block (0x0 - 0x1F) is excluded from the allowed character
|
||||
// range.
|
||||
if (C <= 0x1F)
|
||||
return QuotingType::Double;
|
||||
// C1 control block (0x80 - 0x9F) is excluded from the allowed character
|
||||
// range.
|
||||
if (C >= 0x80 && C <= 0x9F)
|
||||
return QuotingType::Double;
|
||||
|
||||
// The character is not safe, at least simple quoting needed.
|
||||
MaxQuotingNeeded = QuotingType::Single;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MaxQuotingNeeded;
|
||||
}
|
||||
|
||||
template <typename T, typename Context>
|
||||
@ -581,7 +625,7 @@ public:
|
||||
virtual bool bitSetMatch(const char*, bool) = 0;
|
||||
virtual void endBitSetScalar() = 0;
|
||||
|
||||
virtual void scalarString(StringRef &, bool) = 0;
|
||||
virtual void scalarString(StringRef &, QuotingType) = 0;
|
||||
virtual void blockScalarString(StringRef &) = 0;
|
||||
|
||||
virtual void setError(const Twine &) = 0;
|
||||
@ -911,91 +955,91 @@ template<>
|
||||
struct ScalarTraits<bool> {
|
||||
static void output(const bool &, void* , raw_ostream &);
|
||||
static StringRef input(StringRef, void *, bool &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<StringRef> {
|
||||
static void output(const StringRef &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, StringRef &);
|
||||
static bool mustQuote(StringRef S) { return needsQuotes(S); }
|
||||
static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<std::string> {
|
||||
static void output(const std::string &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, std::string &);
|
||||
static bool mustQuote(StringRef S) { return needsQuotes(S); }
|
||||
static QuotingType mustQuote(StringRef S) { return needsQuotes(S); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<uint8_t> {
|
||||
static void output(const uint8_t &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, uint8_t &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<uint16_t> {
|
||||
static void output(const uint16_t &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, uint16_t &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<uint32_t> {
|
||||
static void output(const uint32_t &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, uint32_t &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<uint64_t> {
|
||||
static void output(const uint64_t &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, uint64_t &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<int8_t> {
|
||||
static void output(const int8_t &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, int8_t &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<int16_t> {
|
||||
static void output(const int16_t &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, int16_t &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<int32_t> {
|
||||
static void output(const int32_t &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, int32_t &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<int64_t> {
|
||||
static void output(const int64_t &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, int64_t &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<float> {
|
||||
static void output(const float &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, float &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<double> {
|
||||
static void output(const double &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, double &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
// For endian types, we just use the existing ScalarTraits for the underlying
|
||||
@ -1019,7 +1063,7 @@ struct ScalarTraits<support::detail::packed_endian_specific_integral<
|
||||
return R;
|
||||
}
|
||||
|
||||
static bool mustQuote(StringRef Str) {
|
||||
static QuotingType mustQuote(StringRef Str) {
|
||||
return ScalarTraits<value_type>::mustQuote(Str);
|
||||
}
|
||||
};
|
||||
@ -1148,7 +1192,7 @@ private:
|
||||
bool beginBitSetScalar(bool &) override;
|
||||
bool bitSetMatch(const char *, bool ) override;
|
||||
void endBitSetScalar() override;
|
||||
void scalarString(StringRef &, bool) override;
|
||||
void scalarString(StringRef &, QuotingType) override;
|
||||
void blockScalarString(StringRef &) override;
|
||||
void setError(const Twine &message) override;
|
||||
bool canElideEmptySequence() override;
|
||||
@ -1293,7 +1337,7 @@ public:
|
||||
bool beginBitSetScalar(bool &) override;
|
||||
bool bitSetMatch(const char *, bool ) override;
|
||||
void endBitSetScalar() override;
|
||||
void scalarString(StringRef &, bool) override;
|
||||
void scalarString(StringRef &, QuotingType) override;
|
||||
void blockScalarString(StringRef &) override;
|
||||
void setError(const Twine &message) override;
|
||||
bool canElideEmptySequence() override;
|
||||
@ -1371,28 +1415,28 @@ template<>
|
||||
struct ScalarTraits<Hex8> {
|
||||
static void output(const Hex8 &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, Hex8 &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<Hex16> {
|
||||
static void output(const Hex16 &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, Hex16 &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<Hex32> {
|
||||
static void output(const Hex32 &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, Hex32 &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ScalarTraits<Hex64> {
|
||||
static void output(const Hex64 &, void *, raw_ostream &);
|
||||
static StringRef input(StringRef, void *, Hex64 &);
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
// Define non-member operator>> so that Input can stream in a document list.
|
||||
@ -1681,7 +1725,7 @@ template <typename T> struct StdMapStringCustomMappingTraitsImpl {
|
||||
template <> struct ScalarTraits<Type> { \
|
||||
static void output(const Type &Value, void *ctx, raw_ostream &Out); \
|
||||
static StringRef input(StringRef Scalar, void *ctxt, Type &Value); \
|
||||
static bool mustQuote(StringRef) { return MustQuote; } \
|
||||
static QuotingType mustQuote(StringRef) { return MustQuote; } \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(CrossModuleExport)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLCrossModuleImport)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLFrameData)
|
||||
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, false)
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, QuotingType::None)
|
||||
LLVM_YAML_DECLARE_ENUM_TRAITS(DebugSubsectionKind)
|
||||
LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecksumKind)
|
||||
LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags)
|
||||
|
@ -42,8 +42,8 @@ using namespace llvm::yaml;
|
||||
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)
|
||||
|
||||
// We only need to declare these, the definitions are in CodeViewYAMLTypes.cpp
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, false)
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, false)
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, QuotingType::None)
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, QuotingType::None)
|
||||
|
||||
LLVM_YAML_DECLARE_ENUM_TRAITS(SymbolKind)
|
||||
LLVM_YAML_DECLARE_ENUM_TRAITS(FrameCookieKind)
|
||||
@ -62,7 +62,7 @@ LLVM_YAML_DECLARE_ENUM_TRAITS(ThunkOrdinal)
|
||||
|
||||
LLVM_YAML_STRONG_TYPEDEF(StringRef, TypeName)
|
||||
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeName, true)
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeName, QuotingType::Single)
|
||||
|
||||
StringRef ScalarTraits<TypeName>::input(StringRef S, void *V, TypeName &T) {
|
||||
return ScalarTraits<StringRef>::input(S, V, T.value);
|
||||
|
@ -48,8 +48,8 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(OneMethodRecord)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(VFTableSlotKind)
|
||||
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)
|
||||
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, false)
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, false)
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, QuotingType::None)
|
||||
LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, QuotingType::None)
|
||||
|
||||
LLVM_YAML_DECLARE_ENUM_TRAITS(TypeLeafKind)
|
||||
LLVM_YAML_DECLARE_ENUM_TRAITS(PointerToMemberRepresentation)
|
||||
|
@ -52,7 +52,9 @@ StringRef ScalarTraits<char_16>::input(StringRef Scalar, void *, char_16 &Val) {
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
bool ScalarTraits<char_16>::mustQuote(StringRef S) { return needsQuotes(S); }
|
||||
QuotingType ScalarTraits<char_16>::mustQuote(StringRef S) {
|
||||
return needsQuotes(S);
|
||||
}
|
||||
|
||||
void ScalarTraits<uuid_t>::output(const uuid_t &Val, void *, raw_ostream &Out) {
|
||||
Out.write_uuid(Val);
|
||||
@ -75,7 +77,9 @@ StringRef ScalarTraits<uuid_t>::input(StringRef Scalar, void *, uuid_t &Val) {
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
bool ScalarTraits<uuid_t>::mustQuote(StringRef S) { return needsQuotes(S); }
|
||||
QuotingType ScalarTraits<uuid_t>::mustQuote(StringRef S) {
|
||||
return needsQuotes(S);
|
||||
}
|
||||
|
||||
void MappingTraits<MachOYAML::FileHeader>::mapping(
|
||||
IO &IO, MachOYAML::FileHeader &FileHdr) {
|
||||
|
@ -168,9 +168,10 @@ void llvm::PrintStatisticsJSON(raw_ostream &OS) {
|
||||
const char *delim = "";
|
||||
for (const Statistic *Stat : Stats.Stats) {
|
||||
OS << delim;
|
||||
assert(!yaml::needsQuotes(Stat->getDebugType()) &&
|
||||
assert(yaml::needsQuotes(Stat->getDebugType()) == yaml::QuotingType::None &&
|
||||
"Statistic group/type name is simple.");
|
||||
assert(!yaml::needsQuotes(Stat->getName()) && "Statistic name is simple");
|
||||
assert(yaml::needsQuotes(Stat->getName()) == yaml::QuotingType::None &&
|
||||
"Statistic name is simple");
|
||||
OS << "\t\"" << Stat->getDebugType() << '.' << Stat->getName() << "\": "
|
||||
<< Stat->getValue();
|
||||
delim = ",\n";
|
||||
|
@ -362,8 +362,10 @@ void TimerGroup::printAll(raw_ostream &OS) {
|
||||
|
||||
void TimerGroup::printJSONValue(raw_ostream &OS, const PrintRecord &R,
|
||||
const char *suffix, double Value) {
|
||||
assert(!yaml::needsQuotes(Name) && "TimerGroup name needs no quotes");
|
||||
assert(!yaml::needsQuotes(R.Name) && "Timer name needs no quotes");
|
||||
assert(yaml::needsQuotes(Name) == yaml::QuotingType::None &&
|
||||
"TimerGroup name needs no quotes");
|
||||
assert(yaml::needsQuotes(R.Name) == yaml::QuotingType::None &&
|
||||
"Timer name needs no quotes");
|
||||
OS << "\t\"time." << Name << '.' << R.Name << suffix << "\": " << Value;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/LineIterator.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/Unicode.h"
|
||||
#include "llvm/Support/YAMLParser.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
@ -330,7 +331,7 @@ void Input::endBitSetScalar() {
|
||||
}
|
||||
}
|
||||
|
||||
void Input::scalarString(StringRef &S, bool) {
|
||||
void Input::scalarString(StringRef &S, QuotingType) {
|
||||
if (ScalarHNode *SN = dyn_cast<ScalarHNode>(CurrentNode)) {
|
||||
S = SN->value();
|
||||
} else {
|
||||
@ -338,7 +339,7 @@ void Input::scalarString(StringRef &S, bool) {
|
||||
}
|
||||
}
|
||||
|
||||
void Input::blockScalarString(StringRef &S) { scalarString(S, false); }
|
||||
void Input::blockScalarString(StringRef &S) { scalarString(S, QuotingType::None); }
|
||||
|
||||
void Input::setError(HNode *hnode, const Twine &message) {
|
||||
assert(hnode && "HNode must not be NULL");
|
||||
@ -617,7 +618,7 @@ void Output::endBitSetScalar() {
|
||||
this->outputUpToEndOfLine(" ]");
|
||||
}
|
||||
|
||||
void Output::scalarString(StringRef &S, bool MustQuote) {
|
||||
void Output::scalarString(StringRef &S, QuotingType MustQuote) {
|
||||
this->newLineCheck();
|
||||
if (S.empty()) {
|
||||
// Print '' for the empty string because leaving the field empty is not
|
||||
@ -625,27 +626,52 @@ void Output::scalarString(StringRef &S, bool MustQuote) {
|
||||
this->outputUpToEndOfLine("''");
|
||||
return;
|
||||
}
|
||||
if (!MustQuote) {
|
||||
if (MustQuote == QuotingType::None) {
|
||||
// Only quote if we must.
|
||||
this->outputUpToEndOfLine(S);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned i = 0;
|
||||
unsigned j = 0;
|
||||
unsigned End = S.size();
|
||||
output("'"); // Starting single quote.
|
||||
const char *Base = S.data();
|
||||
|
||||
const char *const Quote = MustQuote == QuotingType::Single ? "'" : "\"";
|
||||
const char QuoteChar = MustQuote == QuotingType::Single ? '\'' : '"';
|
||||
|
||||
output(Quote); // Starting quote.
|
||||
|
||||
// When using single-quoted strings, any single quote ' must be doubled to be
|
||||
// escaped.
|
||||
// When using double-quoted strings, print \x + hex for non-printable ASCII
|
||||
// characters, and escape double quotes.
|
||||
while (j < End) {
|
||||
// Escape a single quote by doubling it.
|
||||
if (S[j] == '\'') {
|
||||
output(StringRef(&Base[i], j - i + 1));
|
||||
output("'");
|
||||
if (S[j] == QuoteChar) { // Escape quotes.
|
||||
output(StringRef(&Base[i], j - i)); // "flush".
|
||||
if (MustQuote == QuotingType::Double) { // Print it as \"
|
||||
output(StringLiteral("\\"));
|
||||
output(StringRef(Quote, 1));
|
||||
} else { // Single
|
||||
output(StringLiteral("''")); // Print it as ''
|
||||
}
|
||||
i = j + 1;
|
||||
} else if (MustQuote == QuotingType::Double &&
|
||||
!sys::unicode::isPrintable(S[j])) {
|
||||
output(StringRef(&Base[i], j - i)); // "flush"
|
||||
output(StringLiteral("\\x"));
|
||||
|
||||
// Output the byte 0x0F as \x0f.
|
||||
auto FormattedHex = format_hex_no_prefix(S[j], 2);
|
||||
Out << FormattedHex;
|
||||
Column += 4; // one for the '\', one for the 'x', and two for the hex
|
||||
|
||||
i = j + 1;
|
||||
}
|
||||
++j;
|
||||
}
|
||||
output(StringRef(&Base[i], j - i));
|
||||
this->outputUpToEndOfLine("'"); // Ending single quote.
|
||||
this->outputUpToEndOfLine(Quote); // Ending quote.
|
||||
}
|
||||
|
||||
void Output::blockScalarString(StringRef &S) {
|
||||
|
6
test/CodeGen/MIR/X86/escape-function-name.ll
Normal file
6
test/CodeGen/MIR/X86/escape-function-name.ll
Normal file
@ -0,0 +1,6 @@
|
||||
; RUN: llc -mtriple=x86_64-unknown-unknown -stop-after branch-folder -o - %s 2>&1 | FileCheck %s
|
||||
|
||||
define void @"\01?f@@YAXXZ"() {
|
||||
; CHECK: name: "\x01?f@@YAXXZ"
|
||||
ret void
|
||||
}
|
@ -232,7 +232,7 @@ template <> struct MappingTraits<dsymutil::DebugMapObject> {
|
||||
template <> struct ScalarTraits<Triple> {
|
||||
static void output(const Triple &val, void *, raw_ostream &out);
|
||||
static StringRef input(StringRef scalar, void *, Triple &value);
|
||||
static bool mustQuote(StringRef) { return true; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
|
||||
};
|
||||
|
||||
template <>
|
||||
|
@ -860,7 +860,7 @@ namespace yaml {
|
||||
return "malformed by";
|
||||
}
|
||||
}
|
||||
static bool mustQuote(StringRef) { return true; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1064,7 +1064,7 @@ namespace yaml {
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
static bool mustQuote(StringRef) { return false; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
|
||||
};
|
||||
|
||||
template <> struct ScalarTraits<MyString> {
|
||||
@ -1075,7 +1075,9 @@ namespace yaml {
|
||||
static StringRef input(StringRef S, void *Ctx, MyString &V) {
|
||||
return Impl::input(S, Ctx, V.value);
|
||||
}
|
||||
static bool mustQuote(StringRef S) { return Impl::mustQuote(S); }
|
||||
static QuotingType mustQuote(StringRef S) {
|
||||
return Impl::mustQuote(S);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -2232,7 +2234,7 @@ struct ScalarTraits<FlowSeq> {
|
||||
return "";
|
||||
}
|
||||
|
||||
static bool mustQuote(StringRef S) { return false; }
|
||||
static QuotingType mustQuote(StringRef S) { return QuotingType::None; }
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -2455,3 +2457,87 @@ TEST(YAMLIO, InvalidInput) {
|
||||
yin >> Data;
|
||||
EXPECT_TRUE((bool)yin.error());
|
||||
}
|
||||
|
||||
TEST(YAMLIO, TestEscapedSingleQuote) {
|
||||
std::string Id = "@abc@";
|
||||
|
||||
std::string out;
|
||||
llvm::raw_string_ostream ostr(out);
|
||||
Output xout(ostr, nullptr, 0);
|
||||
|
||||
llvm::yaml::EmptyContext Ctx;
|
||||
yamlize(xout, Id, true, Ctx);
|
||||
|
||||
ostr.flush();
|
||||
EXPECT_EQ("'@abc@'", out);
|
||||
}
|
||||
|
||||
TEST(YAMLIO, TestEscapedNoQuote) {
|
||||
std::string Id = "abc/";
|
||||
|
||||
std::string out;
|
||||
llvm::raw_string_ostream ostr(out);
|
||||
Output xout(ostr, nullptr, 0);
|
||||
|
||||
llvm::yaml::EmptyContext Ctx;
|
||||
yamlize(xout, Id, true, Ctx);
|
||||
|
||||
ostr.flush();
|
||||
EXPECT_EQ("abc/", out);
|
||||
}
|
||||
|
||||
TEST(YAMLIO, TestEscapedDoubleQuoteNonPrintable) {
|
||||
std::string Id = "\01@abc@";
|
||||
|
||||
std::string out;
|
||||
llvm::raw_string_ostream ostr(out);
|
||||
Output xout(ostr, nullptr, 0);
|
||||
|
||||
llvm::yaml::EmptyContext Ctx;
|
||||
yamlize(xout, Id, true, Ctx);
|
||||
|
||||
ostr.flush();
|
||||
EXPECT_EQ("\"\\x01@abc@\"", out);
|
||||
}
|
||||
|
||||
TEST(YAMLIO, TestEscapedDoubleQuoteInsideSingleQuote) {
|
||||
std::string Id = "abc\"fdf";
|
||||
|
||||
std::string out;
|
||||
llvm::raw_string_ostream ostr(out);
|
||||
Output xout(ostr, nullptr, 0);
|
||||
|
||||
llvm::yaml::EmptyContext Ctx;
|
||||
yamlize(xout, Id, true, Ctx);
|
||||
|
||||
ostr.flush();
|
||||
EXPECT_EQ("'abc\"fdf'", out);
|
||||
}
|
||||
|
||||
TEST(YAMLIO, TestEscapedDoubleQuoteInsideDoubleQuote) {
|
||||
std::string Id = "\01bc\"fdf";
|
||||
|
||||
std::string out;
|
||||
llvm::raw_string_ostream ostr(out);
|
||||
Output xout(ostr, nullptr, 0);
|
||||
|
||||
llvm::yaml::EmptyContext Ctx;
|
||||
yamlize(xout, Id, true, Ctx);
|
||||
|
||||
ostr.flush();
|
||||
EXPECT_EQ("\"\\x01bc\\\"fdf\"", out);
|
||||
}
|
||||
|
||||
TEST(YAMLIO, TestEscapedSingleQuoteInsideSingleQuote) {
|
||||
std::string Id = "abc'fdf";
|
||||
|
||||
std::string out;
|
||||
llvm::raw_string_ostream ostr(out);
|
||||
Output xout(ostr, nullptr, 0);
|
||||
|
||||
llvm::yaml::EmptyContext Ctx;
|
||||
yamlize(xout, Id, true, Ctx);
|
||||
|
||||
ostr.flush();
|
||||
EXPECT_EQ("'abc''fdf'", out);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user