[llvm] r320996 - [YAML] Add support for non-printable characters

Francis Visoiu Mistrih via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 18 09:38:03 PST 2017


Author: thegameg
Date: Mon Dec 18 09:38:03 2017
New Revision: 320996

URL: http://llvm.org/viewvc/llvm-project?rev=320996&view=rev
Log:
[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 at 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

Added:
    llvm/trunk/test/CodeGen/MIR/X86/escape-function-name.ll
Modified:
    llvm/trunk/docs/YamlIO.rst
    llvm/trunk/include/llvm/CodeGen/MIRYamlMapping.h
    llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h
    llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypes.h
    llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h
    llvm/trunk/include/llvm/ObjectYAML/YAML.h
    llvm/trunk/include/llvm/Support/YAMLTraits.h
    llvm/trunk/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
    llvm/trunk/lib/ObjectYAML/CodeViewYAMLSymbols.cpp
    llvm/trunk/lib/ObjectYAML/CodeViewYAMLTypes.cpp
    llvm/trunk/lib/ObjectYAML/MachOYAML.cpp
    llvm/trunk/lib/Support/Statistic.cpp
    llvm/trunk/lib/Support/Timer.cpp
    llvm/trunk/lib/Support/YAMLTraits.cpp
    llvm/trunk/tools/dsymutil/DebugMap.h
    llvm/trunk/unittests/Support/YAMLIOTest.cpp

Modified: llvm/trunk/docs/YamlIO.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/YamlIO.rst?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/docs/YamlIO.rst (original)
+++ llvm/trunk/docs/YamlIO.rst Mon Dec 18 09:38:03 2017
@@ -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

Modified: llvm/trunk/include/llvm/CodeGen/MIRYamlMapping.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MIRYamlMapping.h?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MIRYamlMapping.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MIRYamlMapping.h Mon Dec 18 09:38:03 2017
@@ -56,7 +56,7 @@ template <> struct ScalarTraits<StringVa
     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<FlowStri
     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<Unsigned
     return ScalarTraits<unsigned>::input(Scalar, Ctx, Value.Value);
   }
 
-  static bool mustQuote(StringRef Scalar) {
+  static QuotingType mustQuote(StringRef Scalar) {
     return ScalarTraits<unsigned>::mustQuote(Scalar);
   }
 };

Modified: llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h Mon Dec 18 09:38:03 2017
@@ -56,7 +56,7 @@ ArrayRef<uint8_t> toDebugH(const DebugHS
 } // 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

Modified: llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypes.h?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypes.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/CodeViewYAMLTypes.h Mon Dec 18 09:38:03 2017
@@ -58,7 +58,7 @@ ArrayRef<uint8_t> toDebugT(ArrayRef<Leaf
 
 } // 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)

Modified: llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/MachOYAML.h Mon Dec 18 09:38:03 2017
@@ -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

Modified: llvm/trunk/include/llvm/ObjectYAML/YAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/YAML.h?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/YAML.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/YAML.h Mon Dec 18 09:38:03 2017
@@ -107,7 +107,7 @@ inline bool operator==(const BinaryRef &
 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

Modified: llvm/trunk/include/llvm/Support/YAMLTraits.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/YAMLTraits.h?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/YAMLTraits.h (original)
+++ llvm/trunk/include/llvm/Support/YAMLTraits.h Mon Dec 18 09:38:03 2017
@@ -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::pac
     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 StdMapStrin
   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; }         \
   };                                                                           \
   }                                                                            \
   }

Modified: llvm/trunk/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp Mon Dec 18 09:38:03 2017
@@ -66,7 +66,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(CrossModule
 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)

Modified: llvm/trunk/lib/ObjectYAML/CodeViewYAMLSymbols.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/CodeViewYAMLSymbols.cpp?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/CodeViewYAMLSymbols.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/CodeViewYAMLSymbols.cpp Mon Dec 18 09:38:03 2017
@@ -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(ThunkOrdin
 
 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);

Modified: llvm/trunk/lib/ObjectYAML/CodeViewYAMLTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/CodeViewYAMLTypes.cpp?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/CodeViewYAMLTypes.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/CodeViewYAMLTypes.cpp Mon Dec 18 09:38:03 2017
@@ -48,8 +48,8 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(OneMethodRe
 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)

Modified: llvm/trunk/lib/ObjectYAML/MachOYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/MachOYAML.cpp?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/MachOYAML.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/MachOYAML.cpp Mon Dec 18 09:38:03 2017
@@ -52,7 +52,9 @@ StringRef ScalarTraits<char_16>::input(S
   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(St
   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) {

Modified: llvm/trunk/lib/Support/Statistic.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Statistic.cpp?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Statistic.cpp (original)
+++ llvm/trunk/lib/Support/Statistic.cpp Mon Dec 18 09:38:03 2017
@@ -168,9 +168,10 @@ void llvm::PrintStatisticsJSON(raw_ostre
   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";

Modified: llvm/trunk/lib/Support/Timer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Timer.cpp?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Timer.cpp (original)
+++ llvm/trunk/lib/Support/Timer.cpp Mon Dec 18 09:38:03 2017
@@ -362,8 +362,10 @@ void TimerGroup::printAll(raw_ostream &O
 
 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;
 }
 

Modified: llvm/trunk/lib/Support/YAMLTraits.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/YAMLTraits.cpp?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/lib/Support/YAMLTraits.cpp (original)
+++ llvm/trunk/lib/Support/YAMLTraits.cpp Mon Dec 18 09:38:03 2017
@@ -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, b
   }
 }
 
-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,
     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) {

Added: llvm/trunk/test/CodeGen/MIR/X86/escape-function-name.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/escape-function-name.ll?rev=320996&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/escape-function-name.ll (added)
+++ llvm/trunk/test/CodeGen/MIR/X86/escape-function-name.ll Mon Dec 18 09:38:03 2017
@@ -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
+}

Modified: llvm/trunk/tools/dsymutil/DebugMap.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DebugMap.h?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DebugMap.h (original)
+++ llvm/trunk/tools/dsymutil/DebugMap.h Mon Dec 18 09:38:03 2017
@@ -232,7 +232,7 @@ template <> struct MappingTraits<dsymuti
 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 <>

Modified: llvm/trunk/unittests/Support/YAMLIOTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/YAMLIOTest.cpp?rev=320996&r1=320995&r2=320996&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/YAMLIOTest.cpp (original)
+++ llvm/trunk/unittests/Support/YAMLIOTest.cpp Mon Dec 18 09:38:03 2017
@@ -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 at 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 at 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);
+}




More information about the llvm-commits mailing list