From ba9adaa9dd18f6c9a898e16394c889b9747bc5ba Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Mon, 25 Jan 2021 13:02:20 -0800 Subject: [PATCH] [YAML I/O] Fix bug in emission of empty sequence Don't emit an output dash for an empty sequence. Take emitting a vector of strings for example: std::vector Strings = {"foo", "bar"}; LLVM_YAML_IS_SEQUENCE_VECTOR(std::string) yout << Strings; This emits the following YAML document. --- - foo - bar ... When the vector is empty, this generates the following result: --- - [] ... Although this is valid YAML, it does not match what we meant to emit. The result is a one-element sequence consisting of an empty list. Indeed, if we were to try to read this again we get an error: YAML:2:4: error: not a mapping - [] The problem is the output dash before the empty list. The correct output would be: --- [] ... This patch fixes that by not emitting the output dash for an empty sequence. Differential revision: https://reviews.llvm.org/D95280 --- include/llvm/Support/YAMLTraits.h | 2 +- lib/Support/YAMLTraits.cpp | 7 +++---- unittests/Support/YAMLIOTest.cpp | 23 +++++++++++++++++------ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index bdd27dd99e8..9ac9eb30098 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -1586,7 +1586,7 @@ public: private: void output(StringRef s); void outputUpToEndOfLine(StringRef s); - void newLineCheck(); + void newLineCheck(bool EmptySequence = false); void outputNewLine(); void paddedKey(StringRef key); void flowKey(StringRef Key); diff --git a/lib/Support/YAMLTraits.cpp b/lib/Support/YAMLTraits.cpp index b00357cc3b7..aa6163a7616 100644 --- a/lib/Support/YAMLTraits.cpp +++ b/lib/Support/YAMLTraits.cpp @@ -592,7 +592,7 @@ void Output::endSequence() { // If we did not emit anything, we should explicitly emit an empty sequence if (StateStack.back() == inSeqFirstElement) { Padding = PaddingBeforeContainer; - newLineCheck(); + newLineCheck(/*EmptySequence=*/true); output("[]"); Padding = "\n"; } @@ -798,7 +798,7 @@ void Output::outputNewLine() { // if seq in middle, use "- " if firstKey, else use " " // -void Output::newLineCheck() { +void Output::newLineCheck(bool EmptySequence) { if (Padding != "\n") { output(Padding); Padding = {}; @@ -807,7 +807,7 @@ void Output::newLineCheck() { outputNewLine(); Padding = {}; - if (StateStack.size() == 0) + if (StateStack.size() == 0 || EmptySequence) return; unsigned Indent = StateStack.size() - 1; @@ -831,7 +831,6 @@ void Output::newLineCheck() { if (OutputDash) { output("- "); } - } void Output::paddedKey(StringRef key) { diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index 863861fc322..3e1efbc7550 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -2691,12 +2691,23 @@ TEST(YAMLIO, TestEmptyMapWrite) { } TEST(YAMLIO, TestEmptySequenceWrite) { - FooBarContainer cont; - std::string str; - llvm::raw_string_ostream OS(str); - Output yout(OS); - yout << cont; - EXPECT_EQ(OS.str(), "---\nfbs: []\n...\n"); + { + FooBarContainer cont; + std::string str; + llvm::raw_string_ostream OS(str); + Output yout(OS); + yout << cont; + EXPECT_EQ(OS.str(), "---\nfbs: []\n...\n"); + } + + { + FooBarSequence seq; + std::string str; + llvm::raw_string_ostream OS(str); + Output yout(OS); + yout << seq; + EXPECT_EQ(OS.str(), "---\n[]\n...\n"); + } } static void TestEscaped(llvm::StringRef Input, llvm::StringRef Expected) {