Index: include/llvm/Support/YAMLTraits.h =================================================================== --- include/llvm/Support/YAMLTraits.h +++ include/llvm/Support/YAMLTraits.h @@ -1092,6 +1092,10 @@ /// \brief Returns the current node that's being parsed by the YAML Parser. const Node *getCurrentNode(); + /// \brief Resets the error code so that we can skip and parse the other + /// documents in a YAML file. + void resetError(); + private: llvm::SourceMgr SrcMgr; // must be before Strm std::unique_ptr Strm; Index: lib/Support/YAMLTraits.cpp =================================================================== --- lib/Support/YAMLTraits.cpp +++ lib/Support/YAMLTraits.cpp @@ -101,6 +101,10 @@ return CurrentNode ? CurrentNode->_node : nullptr; } +void Input::resetError() { + EC = std::error_code(); +} + bool Input::mapTag(StringRef Tag, bool Default) { std::string foundTag = CurrentNode->_node->getVerbatimTag(); if (foundTag.empty()) { Index: unittests/Support/YAMLIOTest.cpp =================================================================== --- unittests/Support/YAMLIOTest.cpp +++ unittests/Support/YAMLIOTest.cpp @@ -1593,6 +1593,56 @@ } //===----------------------------------------------------------------------===// +// Test error recovery +//===----------------------------------------------------------------------===// + +// +// Test that the parsing of documents still works when they follow documents +// that have semantic errors. +// + +struct ErrorMapping { + std::string Test; + std::string Test2; +}; + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits { + static void mapping(IO &YamlIO, ErrorMapping &Map) { + YamlIO.mapRequired("test", Map.Test); + YamlIO.mapRequired("test2", Map.Test2); + } + }; +} +} + +TEST(YAMLIO, DocumentErrorRecovery) { + ErrorMapping Map[3]; + Input In("---\n" + "test2: 10\n" + "...\n" + "---\n" + "test: ad\n" + "test2: bc\n" + "...\n" + "---\n" + "test: da\n" + "test2: cb\n", + /*Ctxt=*/ nullptr, suppressErrorMessages); + for (size_t I = 0; In.setCurrentDocument(); ++I) { + llvm::yaml::yamlize(In, Map[I], true); + In.resetError(); + In.nextDocument(); + } + EXPECT_EQ(Map[1].Test, "ad"); + EXPECT_EQ(Map[1].Test2, "bc"); + EXPECT_EQ(Map[2].Test, "da"); + EXPECT_EQ(Map[2].Test2, "cb"); +} + +//===----------------------------------------------------------------------===// // Test error handling //===----------------------------------------------------------------------===//