https://github.com/ilovepi updated 
https://github.com/llvm/llvm-project/pull/190050

>From db0b28e7b01948e0ea0a200cb5a9b81bf4db6c50 Mon Sep 17 00:00:00 2001
From: Paul Kirth <[email protected]>
Date: Sat, 21 Mar 2026 04:52:04 +0000
Subject: [PATCH] [clang-doc] Make CommentInfo arena allocated

This patch move the CommentInfo type into the arena. It updates block
handling to collect child info types and serialize the array in one
shot.

We also clean up the test code to avoid using the arenas in the tests.
This has the upside of making the test more hermetic, and avoids churn
in the related code as the allocation API interfaces evolve.

Performance and memory usage regress slightly. This is somewhat expected
as we do not yet aggressively release short term memory during merge
operations. Future patches will reclaim this overhead.

| Metric | Baseline | Prev | This | Culm% | Seq% |
| :--- | :--- | :--- | :--- | :--- | :--- |
| Time | 920.5s | 998.5s | 1010.5s | +9.8% | +1.2% |
| Memory | 86.0G | 43.8G | 47.8G | -44.4% | +9.2% |

| Benchmark | Baseline | Prev | This | Culm% | Seq% |
| :--- | :--- | :--- | :--- | :--- | :--- |
| BM_BitcodeReader_Scale/10 | 67.9us | 68.8us | 68.7us | +1.1% | -0.2% |
| BM_BitcodeReader_Scale/10000 | 70.5ms | 24.5ms | 23.8ms | -66.2% | -2.8% |
| BM_BitcodeReader_Scale/4096 | 23.2ms | 4.4ms | 4.4ms | -80.9% | -0.0% |
| BM_BitcodeReader_Scale/512 | 509.4us | 538.6us | 538.3us | +5.7% | -0.1% |
| BM_BitcodeReader_Scale/64 | 114.8us | 116.9us | 116.8us | +1.8% | -0.1% |
| BM_Index_Insertion/10 | 2.3us | 4.2us | 3.8us | +65.6% | -8.2% |
| BM_Index_Insertion/10000 | 3.1ms | 5.3ms | 5.1ms | +61.7% | -5.4% |
| BM_Index_Insertion/4096 | 1.3ms | 2.1ms | 2.0ms | +56.8% | -6.1% |
| BM_Index_Insertion/512 | 153.6us | 257.2us | 243.3us | +58.5% | -5.4% |
| BM_Index_Insertion/64 | 18.1us | 30.5us | 29.1us | +61.1% | -4.8% |
| BM_JSONGenerator_Scale/10 | 36.8us | 36.6us | 37.6us | +2.2% | +2.9% |
| BM_JSONGenerator_Scale/10000 | 89.6ms | 90.2ms | 91.1ms | +1.6% | +1.0% |
| BM_JSONGenerator_Scale/4096 | 33.7ms | 34.5ms | 35.0ms | +3.7% | +1.3% |
| BM_JSONGenerator_Scale/512 | 1.9ms | 1.9ms | 2.0ms | +1.8% | +1.7% |
| BM_JSONGenerator_Scale/64 | 222.4us | 218.7us | 226.7us | +1.9% | +3.7% |
| BM_Mapper_Scale/10 | 2.5ms | 2.5ms | 2.5ms | +0.7% | +1.9% |
| BM_Mapper_Scale/10000 | 104.3ms | 106.1ms | 105.5ms | +1.1% | -0.6% |
| BM_Mapper_Scale/4096 | 44.3ms | 45.0ms | 44.5ms | +0.3% | -1.1% |
| BM_MergeInfos_Scale/10000 | 12.2ms | 2.0ms | 1.9ms | -84.8% | -7.1% |
| BM_MergeInfos_Scale/2 | 1.9us | 1.8us | 1.7us | -7.9% | -2.1% |
| BM_MergeInfos_Scale/4096 | 2.8ms | 574.7us | 531.2us | -80.9% | -7.6% |
| BM_MergeInfos_Scale/512 | 68.9us | 39.6us | 36.5us | -47.0% | -7.9% |
| BM_MergeInfos_Scale/64 | 10.3us | 6.5us | 6.0us | -41.3% | -7.0% |
| BM_MergeInfos_Scale/8 | 2.8us | 2.2us | 2.2us | -22.4% | -2.8% |
---
 clang-tools-extra/clang-doc/BitcodeReader.cpp |  26 +-
 clang-tools-extra/clang-doc/BitcodeWriter.cpp |   2 +-
 clang-tools-extra/clang-doc/JSONGenerator.cpp |   4 +-
 clang-tools-extra/clang-doc/MDGenerator.cpp   |  16 +-
 .../clang-doc/Representation.cpp              |   8 +-
 clang-tools-extra/clang-doc/Representation.h  |  19 +-
 clang-tools-extra/clang-doc/Serialize.cpp     |  20 +-
 clang-tools-extra/clang-doc/YAMLGenerator.cpp |   7 +
 .../unittests/clang-doc/BitcodeTest.cpp       | 199 ++++++---------
 .../unittests/clang-doc/MDGeneratorTest.cpp   | 236 ++++++++++--------
 .../unittests/clang-doc/MergeTest.cpp         |  45 ++--
 .../unittests/clang-doc/YAMLGeneratorTest.cpp | 187 ++++++--------
 12 files changed, 372 insertions(+), 397 deletions(-)

diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp 
b/clang-tools-extra/clang-doc/BitcodeReader.cpp
index ddb1bccdd5469..a3a73235cfbdf 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -385,6 +385,7 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, 
CommentInfo *I) {
   if (llvm::Error Err = Stream.EnterSubBlock(ID))
     return Err;
 
+  llvm::SmallVector<CommentInfo> LocalChildren;
   llvm::SmallVector<StringRef> AttrKeys;
   llvm::SmallVector<StringRef> AttrValues;
   llvm::SmallVector<StringRef> Args;
@@ -400,6 +401,8 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, 
CommentInfo *I) {
       return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                      "bad block found");
     case Cursor::BlockEnd: {
+      if (!LocalChildren.empty())
+        I->Children = allocateArray<CommentInfo>(LocalChildren, 
TransientArena);
       if (!AttrKeys.empty()) {
         StringRef *KeysMem =
             TransientArena.Allocate<StringRef>(AttrKeys.size());
@@ -421,10 +424,20 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, 
CommentInfo *I) {
       return llvm::Error::success();
     }
     case Cursor::BlockBegin:
-      if (llvm::Error Err = readSubBlock(BlockOrCode, I)) {
-        if (llvm::Error Skipped = Stream.SkipBlock())
-          return joinErrors(std::move(Err), std::move(Skipped));
-        return Err;
+      if (BlockOrCode == BI_COMMENT_BLOCK_ID) {
+        CommentInfo Child;
+        if (llvm::Error Err = readBlock(BlockOrCode, &Child)) {
+          if (llvm::Error Skipped = Stream.SkipBlock())
+            return joinErrors(std::move(Err), std::move(Skipped));
+          return Err;
+        }
+        LocalChildren.push_back(std::move(Child));
+      } else {
+        if (llvm::Error Err = readSubBlock(BlockOrCode, I)) {
+          if (llvm::Error Skipped = Stream.SkipBlock())
+            return joinErrors(std::move(Err), std::move(Skipped));
+          return Err;
+        }
       }
       continue;
     case Cursor::Record:
@@ -574,11 +587,6 @@ template <> llvm::Expected<CommentInfo *> 
getCommentInfo(EnumValueInfo *I) {
   return &I->Description.emplace_back();
 }
 
-template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) {
-  I->Children.emplace_back(allocatePtr<CommentInfo>());
-  return getPtr(I->Children.back());
-}
-
 template <> llvm::Expected<CommentInfo *> getCommentInfo(ConceptInfo *I) {
   return &I->Description.emplace_back();
 }
diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp 
b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
index 655a7f6336c1c..1aa1632f7bf9d 100644
--- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
@@ -563,7 +563,7 @@ void ClangDocBitcodeWriter::emitBlock(const CommentInfo &I) 
{
   for (const auto &A : I.Args)
     emitRecord(A, COMMENT_ARG);
   for (const auto &C : I.Children)
-    emitBlock(*C);
+    emitBlock(C);
 }
 
 void ClangDocBitcodeWriter::emitBlock(const NamespaceInfo &I) {
diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp 
b/clang-tools-extra/clang-doc/JSONGenerator.cpp
index 8db7eaafcfb30..1615e553fe109 100644
--- a/clang-tools-extra/clang-doc/JSONGenerator.cpp
+++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp
@@ -206,7 +206,7 @@ static Object serializeComment(const CommentInfo &I, Object 
&Description) {
   auto &CARef = *ChildArr.getAsArray();
   CARef.reserve(I.Children.size());
   for (const auto &C : I.Children)
-    CARef.emplace_back(serializeComment(*C, Description));
+    CARef.emplace_back(serializeComment(C, Description));
 
   switch (I.Kind) {
   case CommentKind::CK_TextComment: {
@@ -385,7 +385,7 @@ static void 
serializeDescription(llvm::ArrayRef<CommentInfo> Description,
   auto &Comments = Description.front().Children;
   Object DescriptionObj = Object();
   for (const auto &CommentInfo : Comments) {
-    json::Value Comment = serializeComment(*CommentInfo, DescriptionObj);
+    json::Value Comment = serializeComment(CommentInfo, DescriptionObj);
     // if a ParagraphComment is returned, then it is a top-level comment that
     // needs to be inserted manually.
     if (auto *ParagraphComment = Comment.getAsObject();
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp 
b/clang-tools-extra/clang-doc/MDGenerator.cpp
index 5fcd6da0492ca..b0253c5d71bfc 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -111,12 +111,12 @@ class TableCommentWriter {
     switch (I.Kind) {
     case CommentKind::CK_FullComment:
       for (const auto &Child : I.Children)
-        writeTableSafeComment(*Child);
+        writeTableSafeComment(Child);
       break;
 
     case CommentKind::CK_ParagraphComment:
       for (const auto &Child : I.Children)
-        writeTableSafeComment(*Child);
+        writeTableSafeComment(Child);
       // Next content after a paragraph needs a break
       NeedsParagraphBreak = true;
       break;
@@ -132,7 +132,7 @@ class TableCommentWriter {
     // Handle other comment types (BlockCommand, InlineCommand, etc.)
     default:
       for (const auto &Child : I.Children)
-        writeTableSafeComment(*Child);
+        writeTableSafeComment(Child);
       break;
     }
   }
@@ -153,19 +153,19 @@ static void writeDescription(const CommentInfo &I, 
raw_ostream &OS) {
   switch (I.Kind) {
   case CommentKind::CK_FullComment:
     for (const auto &Child : I.Children)
-      writeDescription(*Child, OS);
+      writeDescription(Child, OS);
     break;
 
   case CommentKind::CK_ParagraphComment:
     for (const auto &Child : I.Children)
-      writeDescription(*Child, OS);
+      writeDescription(Child, OS);
     writeNewLine(OS);
     break;
 
   case CommentKind::CK_BlockCommandComment:
     OS << genEmphasis(I.Name) << " ";
     for (const auto &Child : I.Children)
-      writeDescription(*Child, OS);
+      writeDescription(Child, OS);
     break;
 
   case CommentKind::CK_InlineCommandComment:
@@ -177,13 +177,13 @@ static void writeDescription(const CommentInfo &I, 
raw_ostream &OS) {
     std::string Direction = I.Explicit ? (" " + I.Direction).str() : "";
     OS << genEmphasis(I.ParamName) << I.Text << Direction << " ";
     for (const auto &Child : I.Children)
-      writeDescription(*Child, OS);
+      writeDescription(Child, OS);
     break;
   }
 
   case CommentKind::CK_VerbatimBlockComment:
     for (const auto &Child : I.Children)
-      writeDescription(*Child, OS);
+      writeDescription(Child, OS);
     break;
 
   case CommentKind::CK_VerbatimBlockLineComment:
diff --git a/clang-tools-extra/clang-doc/Representation.cpp 
b/clang-tools-extra/clang-doc/Representation.cpp
index 1535fcc71df66..38dfa90453499 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -188,7 +188,7 @@ bool CommentInfo::operator==(const CommentInfo &Other) 
const {
     return false;
 
   return std::equal(Children.begin(), Children.end(), Other.Children.begin(),
-                    llvm::deref<std::equal_to<>>{});
+                    Other.Children.end());
 }
 
 bool CommentInfo::operator<(const CommentInfo &Other) const {
@@ -203,9 +203,9 @@ bool CommentInfo::operator<(const CommentInfo &Other) const 
{
     return true;
 
   if (FirstCI == SecondCI) {
-    return std::lexicographical_compare(
-        Children.begin(), Children.end(), Other.Children.begin(),
-        Other.Children.end(), llvm::deref<std::less<>>());
+    return std::lexicographical_compare(Children.begin(), Children.end(),
+                                        Other.Children.begin(),
+                                        Other.Children.end());
   }
 
   return false;
diff --git a/clang-tools-extra/clang-doc/Representation.h 
b/clang-tools-extra/clang-doc/Representation.h
index aa298f99db1ea..9208b77fc8606 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -167,10 +167,23 @@ llvm::StringRef commentKindToString(CommentKind Kind);
 // A representation of a parsed comment.
 struct CommentInfo : public llvm::ilist_node<CommentInfo> {
   CommentInfo() = default;
-  CommentInfo(CommentInfo &Other) = delete;
+  CommentInfo(const CommentInfo &Other) = default;
+  CommentInfo &operator=(const CommentInfo &Other) = default;
   CommentInfo(CommentInfo &&Other) = default;
   CommentInfo &operator=(CommentInfo &&Other) = default;
 
+  CommentInfo(CommentKind Kind, llvm::ArrayRef<CommentInfo> Children = {},
+              StringRef Text = StringRef(), StringRef Name = StringRef(),
+              StringRef CloseName = StringRef(),
+              StringRef Direction = StringRef(),
+              StringRef ParamName = StringRef(), bool Explicit = false,
+              bool SelfClosing = false, llvm::ArrayRef<StringRef> AttrKeys = 
{},
+              llvm::ArrayRef<StringRef> AttrValues = {})
+      : Children(Children), Direction(Direction), Name(Name),
+        ParamName(ParamName), CloseName(CloseName), Text(Text),
+        AttrKeys(AttrKeys), AttrValues(AttrValues), Kind(Kind),
+        SelfClosing(SelfClosing), Explicit(Explicit) {}
+
   bool operator==(const CommentInfo &Other) const;
 
   // This operator is used to sort a vector of CommentInfos.
@@ -179,7 +192,7 @@ struct CommentInfo : public llvm::ilist_node<CommentInfo> {
   // the vector.
   bool operator<(const CommentInfo &Other) const;
 
-  OwningPtrVec<CommentInfo>
+  llvm::ArrayRef<CommentInfo>
       Children;              // List of child comments for this CommentInfo.
   StringRef Direction;       // Parameter direction (for (T)ParamCommand).
   StringRef Name;            // Name of the comment (for Verbatim and HTML).
@@ -759,6 +772,7 @@ struct ClangDocContext {
 
 // Ensure arena allocated types remain safe to allocate in the arena.
 // Only trivially destructible types are safe, so enforce that at compile-time.
+static_assert(std::is_trivially_destructible_v<CommentInfo>);
 static_assert(std::is_trivially_destructible_v<ConstraintInfo>);
 static_assert(std::is_trivially_destructible_v<FieldTypeInfo>);
 static_assert(std::is_trivially_destructible_v<Location>);
@@ -767,7 +781,6 @@ 
static_assert(std::is_trivially_destructible_v<TemplateParamInfo>);
 static_assert(std::is_trivially_destructible_v<TypeInfo>);
 
 // FIXME: These types need to be trivially destructible for arena allocation.
-static_assert(!std::is_trivially_destructible_v<CommentInfo>);
 static_assert(!std::is_trivially_destructible_v<ConceptInfo>);
 static_assert(!std::is_trivially_destructible_v<EnumInfo>);
 static_assert(!std::is_trivially_destructible_v<FriendInfo>);
diff --git a/clang-tools-extra/clang-doc/Serialize.cpp 
b/clang-tools-extra/clang-doc/Serialize.cpp
index 328b8c8a0c9ab..ef7fed6cc8501 100644
--- a/clang-tools-extra/clang-doc/Serialize.cpp
+++ b/clang-tools-extra/clang-doc/Serialize.cpp
@@ -228,11 +228,21 @@ class ClangDocCommentVisitor
 void ClangDocCommentVisitor::parseComment(const comments::Comment *C) {
   CurrentCI.Kind = stringToCommentKind(C->getCommentKindName());
   ConstCommentVisitor<ClangDocCommentVisitor>::visit(C);
-  for (comments::Comment *Child :
-       llvm::make_range(C->child_begin(), C->child_end())) {
-    CurrentCI.Children.emplace_back(allocatePtr<CommentInfo>());
-    ClangDocCommentVisitor Visitor(*CurrentCI.Children.back());
-    Visitor.parseComment(Child);
+
+  unsigned NumChildren = C->child_count();
+  if (NumChildren > 0) {
+    CommentInfo *ChildrenArray =
+        TransientArena.Allocate<CommentInfo>(NumChildren);
+    unsigned I = 0;
+    for (comments::Comment *Child :
+         llvm::make_range(C->child_begin(), C->child_end())) {
+      new (&ChildrenArray[I]) CommentInfo();
+      ClangDocCommentVisitor Visitor(ChildrenArray[I]);
+      Visitor.parseComment(Child);
+      I++;
+    }
+    CurrentCI.Children =
+        llvm::ArrayRef<CommentInfo>(ChildrenArray, NumChildren);
   }
 }
 
diff --git a/clang-tools-extra/clang-doc/YAMLGenerator.cpp 
b/clang-tools-extra/clang-doc/YAMLGenerator.cpp
index fc814c09c7f3a..9e3bca84877e0 100644
--- a/clang-tools-extra/clang-doc/YAMLGenerator.cpp
+++ b/clang-tools-extra/clang-doc/YAMLGenerator.cpp
@@ -33,6 +33,13 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(OwnedPtr<CommentInfo>)
 namespace llvm {
 namespace yaml {
 
+template <typename T> struct SequenceTraits<llvm::ArrayRef<T>> {
+  static size_t size(IO &io, llvm::ArrayRef<T> &seq) { return seq.size(); }
+  static T &element(IO &io, llvm::ArrayRef<T> &seq, size_t index) {
+    return const_cast<T &>(seq[index]);
+  }
+};
+
 // Enumerations to YAML output.
 
 template <> struct ScalarEnumerationTraits<clang::AccessSpecifier> {
diff --git a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp 
b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
index 7b117a96c53fe..6bdf538012303 100644
--- a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp
@@ -103,15 +103,12 @@ TEST_F(BitcodeTest, emitRecordInfoBitcode) {
   I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
 
   // Documentation for the data member.
-  CommentInfo TopComment;
-  TopComment.Kind = CommentKind::CK_FullComment;
-  TopComment.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Brief = TopComment.Children.back().get();
-  Brief->Kind = CommentKind::CK_ParagraphComment;
-  Brief->Children.emplace_back(allocatePtr<CommentInfo>());
-  Brief->Children.back()->Kind = CommentKind::CK_TextComment;
-  Brief->Children.back()->Name = "ParagraphComment";
-  Brief->Children.back()->Text = "Value of the thing.";
+  CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
+                                             "Value of the thing.",
+                                             "ParagraphComment")};
+  CommentInfo TopCommentChildren[] = {
+      CommentInfo(CommentKind::CK_ParagraphComment, BriefChildren)};
+  CommentInfo TopComment(CommentKind::CK_FullComment, TopCommentChildren);
   
I.Bases.back().Members.back().Description.emplace_back(std::move(TopComment));
 
   I.Children.Records.emplace_back(EmptySID, "ChildStruct", 
InfoType::IT_record);
@@ -194,14 +191,10 @@ TEST_F(BitcodeTest, emitTypedefInfoBitcode) {
   I.Underlying = TypeInfo("unsigned");
   I.IsUsing = true;
 
-  CommentInfo Top;
-  Top.Kind = CommentKind::CK_FullComment;
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *BlankLine = Top.Children.back().get();
-  BlankLine->Kind = CommentKind::CK_ParagraphComment;
-  BlankLine->Children.emplace_back(allocatePtr<CommentInfo>());
-  BlankLine->Children.back()->Kind = CommentKind::CK_TextComment;
+  CommentInfo BlankChildren[] = {CommentInfo(CommentKind::CK_TextComment)};
+  CommentInfo TopChildren[] = {
+      CommentInfo(CommentKind::CK_ParagraphComment, BlankChildren)};
+  CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
 
   I.Description.emplace_back(std::move(Top));
 
@@ -230,109 +223,75 @@ TEST_F(BitcodeTest, emitInfoWithCommentBitcode) {
   F.DefLoc = Location(0, 0, "test.cpp");
   F.Params.emplace_back(TypeInfo("int"), "I");
 
-  CommentInfo Top;
-  Top.Kind = CommentKind::CK_FullComment;
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *BlankLine = Top.Children.back().get();
-  BlankLine->Kind = CommentKind::CK_ParagraphComment;
-  BlankLine->Children.emplace_back(allocatePtr<CommentInfo>());
-  BlankLine->Children.back()->Kind = CommentKind::CK_TextComment;
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Brief = Top.Children.back().get();
-  Brief->Kind = CommentKind::CK_ParagraphComment;
-  Brief->Children.emplace_back(allocatePtr<CommentInfo>());
-  Brief->Children.back()->Kind = CommentKind::CK_TextComment;
-  Brief->Children.back()->Name = "ParagraphComment";
-  Brief->Children.back()->Text = " Brief description.";
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Extended = Top.Children.back().get();
-  Extended->Kind = CommentKind::CK_ParagraphComment;
-  Extended->Children.emplace_back(allocatePtr<CommentInfo>());
-  Extended->Children.back()->Kind = CommentKind::CK_TextComment;
-  Extended->Children.back()->Text = " Extended description that";
-  Extended->Children.emplace_back(allocatePtr<CommentInfo>());
-  Extended->Children.back()->Kind = CommentKind::CK_TextComment;
-  Extended->Children.back()->Text = " continues onto the next line.";
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *HTML = Top.Children.back().get();
-  HTML->Kind = CommentKind::CK_ParagraphComment;
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_TextComment;
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_HTMLStartTagComment;
-  HTML->Children.back()->Name = "ul";
-  {
-    llvm::SmallVector<StringRef, 1> Keys = {"class"};
-    HTML->Children.back()->AttrKeys =
-        allocateArray<StringRef>(Keys, TransientArena);
-
-    llvm::SmallVector<StringRef, 1> Values = {"test"};
-    HTML->Children.back()->AttrValues =
-        allocateArray<StringRef>(Values, TransientArena);
-  }
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_HTMLStartTagComment;
-  HTML->Children.back()->Name = "li";
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_TextComment;
-  HTML->Children.back()->Text = " Testing.";
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_HTMLEndTagComment;
-  HTML->Children.back()->Name = "ul";
-  HTML->Children.back()->SelfClosing = true;
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Verbatim = Top.Children.back().get();
-  Verbatim->Kind = CommentKind::CK_VerbatimBlockComment;
-  Verbatim->Name = "verbatim";
-  Verbatim->CloseName = "endverbatim";
-  Verbatim->Children.emplace_back(allocatePtr<CommentInfo>());
-  Verbatim->Children.back()->Kind = CommentKind::CK_VerbatimBlockLineComment;
-  Verbatim->Children.back()->Text = " The description continues.";
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *ParamOut = Top.Children.back().get();
-  ParamOut->Kind = CommentKind::CK_ParamCommandComment;
-  ParamOut->Direction = "[out]";
-  ParamOut->ParamName = "I";
-  ParamOut->Explicit = true;
-  ParamOut->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamOut->Children.back()->Kind = CommentKind::CK_ParagraphComment;
-  ParamOut->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamOut->Children.back()->Children.back()->Kind =
-      CommentKind::CK_TextComment;
-  ParamOut->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamOut->Children.back()->Children.back()->Kind =
-      CommentKind::CK_TextComment;
-  ParamOut->Children.back()->Children.back()->Text = " is a parameter.";
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *ParamIn = Top.Children.back().get();
-  ParamIn->Kind = CommentKind::CK_ParamCommandComment;
-  ParamIn->Direction = "[in]";
-  ParamIn->ParamName = "J";
-  ParamIn->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamIn->Children.back()->Kind = CommentKind::CK_ParagraphComment;
-  ParamIn->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamIn->Children.back()->Children.back()->Kind = 
CommentKind::CK_TextComment;
-  ParamIn->Children.back()->Children.back()->Text = " is a parameter.";
-  ParamIn->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamIn->Children.back()->Children.back()->Kind = 
CommentKind::CK_TextComment;
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Return = Top.Children.back().get();
-  Return->Kind = CommentKind::CK_BlockCommandComment;
-  Return->Name = "return";
-  Return->Explicit = true;
-  Return->Children.emplace_back(allocatePtr<CommentInfo>());
-  Return->Children.back()->Kind = CommentKind::CK_ParagraphComment;
-  Return->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  Return->Children.back()->Children.back()->Kind = CommentKind::CK_TextComment;
-  Return->Children.back()->Children.back()->Text = "void";
+  // BlankLine
+  CommentInfo BlankChildren[] = {CommentInfo(CommentKind::CK_TextComment)};
+  CommentInfo BlankLine(CommentKind::CK_ParagraphComment, BlankChildren);
+
+  // Brief
+  CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
+                                             " Brief description.",
+                                             "ParagraphComment")};
+  CommentInfo Brief(CommentKind::CK_ParagraphComment, BriefChildren);
+
+  // Extended
+  CommentInfo ExtChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
+                                           " Extended description that"),
+                               CommentInfo(CommentKind::CK_TextComment, {},
+                                           " continues onto the next line.")};
+  CommentInfo Extended(CommentKind::CK_ParagraphComment, ExtChildren);
+
+  // HTML
+  StringRef HtmlKeys[] = {"class"};
+  StringRef HtmlValues[] = {"test"};
+  CommentInfo HtmlStart(CommentKind::CK_HTMLStartTagComment, {}, "", "ul", "",
+                        "", "", false, false, HtmlKeys, HtmlValues);
+  CommentInfo HtmlStartLi(CommentKind::CK_HTMLStartTagComment, {}, "", "li");
+  CommentInfo HtmlEnd(CommentKind::CK_HTMLEndTagComment, {}, "", "ul", "", "",
+                      "", false, true);
+
+  CommentInfo HtmlChildren[] = {
+      CommentInfo(CommentKind::CK_TextComment), HtmlStart, HtmlStartLi,
+      CommentInfo(CommentKind::CK_TextComment, {}, " Testing."), HtmlEnd};
+  CommentInfo HTML(CommentKind::CK_ParagraphComment, HtmlChildren);
+
+  // Verbatim
+  CommentInfo VerbLine(CommentKind::CK_VerbatimBlockLineComment, {},
+                       " The description continues.");
+  CommentInfo VerbChildren[] = {VerbLine};
+  CommentInfo Verbatim(CommentKind::CK_VerbatimBlockComment, VerbChildren, "",
+                       "verbatim", "endverbatim");
+
+  // ParamOut
+  CommentInfo ParamOutParaChildren[] = {
+      CommentInfo(CommentKind::CK_TextComment),
+      CommentInfo(CommentKind::CK_TextComment, {}, " is a parameter.")};
+  CommentInfo ParamOutPara(CommentKind::CK_ParagraphComment,
+                           ParamOutParaChildren);
+  CommentInfo ParamOutChildren[] = {ParamOutPara};
+  CommentInfo ParamOut(CommentKind::CK_ParamCommandComment, ParamOutChildren,
+                       "", "", "", "[out]", "I", true);
+
+  // ParamIn
+  CommentInfo ParamInParaChildren[] = {
+      CommentInfo(CommentKind::CK_TextComment, {}, " is a parameter."),
+      CommentInfo(CommentKind::CK_TextComment)};
+  CommentInfo ParamInPara(CommentKind::CK_ParagraphComment,
+                          ParamInParaChildren);
+  CommentInfo ParamInChildren[] = {ParamInPara};
+  CommentInfo ParamIn(CommentKind::CK_ParamCommandComment, ParamInChildren, "",
+                      "", "", "[in]", "J");
+
+  // Return
+  CommentInfo ReturnParaChildren[] = {
+      CommentInfo(CommentKind::CK_TextComment, {}, "void")};
+  CommentInfo ReturnPara(CommentKind::CK_ParagraphComment, ReturnParaChildren);
+  CommentInfo ReturnChildren[] = {ReturnPara};
+  CommentInfo Return(CommentKind::CK_BlockCommandComment, ReturnChildren, "",
+                     "return", "", "", "", true);
+
+  CommentInfo TopChildren[] = {BlankLine, Brief,    Extended, HTML,
+                               Verbatim,  ParamOut, ParamIn,  Return};
+  CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
 
   F.Description.emplace_back(std::move(Top));
 
diff --git a/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp 
b/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp
index 12eec3f491fd0..6661360049881 100644
--- a/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp
@@ -215,109 +215,139 @@ TEST_F(MDGeneratorTest, emitCommentMD) {
   CommentInfo Top;
   Top.Kind = CommentKind::CK_FullComment;
 
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *BlankLine = Top.Children.back().get();
-  BlankLine->Kind = CommentKind::CK_ParagraphComment;
-  BlankLine->Children.emplace_back(allocatePtr<CommentInfo>());
-  BlankLine->Children.back()->Kind = CommentKind::CK_TextComment;
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Brief = Top.Children.back().get();
-  Brief->Kind = CommentKind::CK_ParagraphComment;
-  Brief->Children.emplace_back(allocatePtr<CommentInfo>());
-  Brief->Children.back()->Kind = CommentKind::CK_TextComment;
-  Brief->Children.back()->Name = "ParagraphComment";
-  Brief->Children.back()->Text = " Brief description.";
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Extended = Top.Children.back().get();
-  Extended->Kind = CommentKind::CK_ParagraphComment;
-  Extended->Children.emplace_back(allocatePtr<CommentInfo>());
-  Extended->Children.back()->Kind = CommentKind::CK_TextComment;
-  Extended->Children.back()->Text = " Extended description that";
-  Extended->Children.emplace_back(allocatePtr<CommentInfo>());
-  Extended->Children.back()->Kind = CommentKind::CK_TextComment;
-  Extended->Children.back()->Text = " continues onto the next line.";
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *HTML = Top.Children.back().get();
-  HTML->Kind = CommentKind::CK_ParagraphComment;
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_TextComment;
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_HTMLStartTagComment;
-  HTML->Children.back()->Name = "ul";
-  {
-    llvm::SmallVector<StringRef, 1> Keys = {"class"};
-    HTML->Children.back()->AttrKeys =
-        allocateArray<StringRef>(Keys, TransientArena);
-
-    llvm::SmallVector<StringRef, 1> Values = {"test"};
-    HTML->Children.back()->AttrValues =
-        allocateArray<StringRef>(Values, TransientArena);
-  }
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_HTMLStartTagComment;
-  HTML->Children.back()->Name = "li";
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_TextComment;
-  HTML->Children.back()->Text = " Testing.";
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_HTMLEndTagComment;
-  HTML->Children.back()->Name = "ul";
-  HTML->Children.back()->SelfClosing = true;
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Verbatim = Top.Children.back().get();
-  Verbatim->Kind = CommentKind::CK_VerbatimBlockComment;
-  Verbatim->Name = "verbatim";
-  Verbatim->CloseName = "endverbatim";
-  Verbatim->Children.emplace_back(allocatePtr<CommentInfo>());
-  Verbatim->Children.back()->Kind = CommentKind::CK_VerbatimBlockLineComment;
-  Verbatim->Children.back()->Text = " The description continues.";
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *ParamOut = Top.Children.back().get();
-  ParamOut->Kind = CommentKind::CK_ParamCommandComment;
-  ParamOut->Direction = "[out]";
-  ParamOut->ParamName = "I";
-  ParamOut->Explicit = true;
-  ParamOut->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamOut->Children.back()->Kind = CommentKind::CK_ParagraphComment;
-  ParamOut->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamOut->Children.back()->Children.back()->Kind =
-      CommentKind::CK_TextComment;
-  ParamOut->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamOut->Children.back()->Children.back()->Kind =
-      CommentKind::CK_TextComment;
-  ParamOut->Children.back()->Children.back()->Text = "is a parameter.";
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *ParamIn = Top.Children.back().get();
-  ParamIn->Kind = CommentKind::CK_ParamCommandComment;
-  ParamIn->Direction = "[in]";
-  ParamIn->ParamName = "J";
-  ParamIn->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamIn->Children.back()->Kind = CommentKind::CK_ParagraphComment;
-  ParamIn->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamIn->Children.back()->Children.back()->Kind = 
CommentKind::CK_TextComment;
-  ParamIn->Children.back()->Children.back()->Text = "is a parameter.";
-  ParamIn->Children.back()->Children.emplace_back(
-      std::make_unique<CommentInfo>());
-  ParamIn->Children.back()->Children.back()->Kind = 
CommentKind::CK_TextComment;
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Return = Top.Children.back().get();
-  Return->Kind = CommentKind::CK_BlockCommandComment;
-  Return->Name = "return";
-  Return->Explicit = true;
-  Return->Children.emplace_back(allocatePtr<CommentInfo>());
-  Return->Children.back()->Kind = CommentKind::CK_ParagraphComment;
-  Return->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  Return->Children.back()->Children.back()->Kind = CommentKind::CK_TextComment;
-  Return->Children.back()->Children.back()->Text = "void";
-
-  I.Description.emplace_back(std::move(Top));
+  llvm::SmallVector<CommentInfo, 8> TopChildren;
+
+  // BlankLine
+  CommentInfo BlankLine;
+  BlankLine.Kind = CommentKind::CK_ParagraphComment;
+  CommentInfo BlankText;
+  BlankText.Kind = CommentKind::CK_TextComment;
+  CommentInfo BlankChildren[] = {std::move(BlankText)};
+  BlankLine.Children = BlankChildren;
+  TopChildren.push_back(std::move(BlankLine));
+
+  // Brief
+  CommentInfo Brief;
+  Brief.Kind = CommentKind::CK_ParagraphComment;
+  CommentInfo BriefText;
+  BriefText.Kind = CommentKind::CK_TextComment;
+  BriefText.Name = "ParagraphComment";
+  BriefText.Text = " Brief description.";
+  CommentInfo BriefChildren[] = {std::move(BriefText)};
+  Brief.Children = BriefChildren;
+  TopChildren.push_back(std::move(Brief));
+
+  // Extended
+  CommentInfo Extended;
+  Extended.Kind = CommentKind::CK_ParagraphComment;
+  CommentInfo ExtText1;
+  ExtText1.Kind = CommentKind::CK_TextComment;
+  ExtText1.Text = " Extended description that";
+  CommentInfo ExtText2;
+  ExtText2.Kind = CommentKind::CK_TextComment;
+  ExtText2.Text = " continues onto the next line.";
+  CommentInfo ExtChildren[] = {std::move(ExtText1), std::move(ExtText2)};
+  Extended.Children = ExtChildren;
+  TopChildren.push_back(std::move(Extended));
+
+  // HTML
+  CommentInfo HTML;
+  HTML.Kind = CommentKind::CK_ParagraphComment;
+  CommentInfo HtmlText1;
+  HtmlText1.Kind = CommentKind::CK_TextComment;
+  CommentInfo HtmlStart;
+  HtmlStart.Kind = CommentKind::CK_HTMLStartTagComment;
+  HtmlStart.Name = "ul";
+  StringRef Keys[] = {"class"};
+  StringRef Values[] = {"test"};
+  HtmlStart.AttrKeys = Keys;
+  HtmlStart.AttrValues = Values;
+  CommentInfo HtmlStartLi;
+  HtmlStartLi.Kind = CommentKind::CK_HTMLStartTagComment;
+  HtmlStartLi.Name = "li";
+  CommentInfo HtmlText2;
+  HtmlText2.Kind = CommentKind::CK_TextComment;
+  HtmlText2.Text = " Testing.";
+  CommentInfo HtmlEnd;
+  HtmlEnd.Kind = CommentKind::CK_HTMLEndTagComment;
+  HtmlEnd.Name = "ul";
+  HtmlEnd.SelfClosing = true;
+  CommentInfo HtmlChildren[] = {std::move(HtmlText1), std::move(HtmlStart),
+                                std::move(HtmlStartLi), std::move(HtmlText2),
+                                std::move(HtmlEnd)};
+  HTML.Children = HtmlChildren;
+  TopChildren.push_back(std::move(HTML));
+
+  // Verbatim
+  CommentInfo Verbatim;
+  Verbatim.Kind = CommentKind::CK_VerbatimBlockComment;
+  Verbatim.Name = "verbatim";
+  Verbatim.CloseName = "endverbatim";
+  CommentInfo VerbLine;
+  VerbLine.Kind = CommentKind::CK_VerbatimBlockLineComment;
+  VerbLine.Text = " The description continues.";
+  CommentInfo VerbChildren[] = {std::move(VerbLine)};
+  Verbatim.Children = VerbChildren;
+  TopChildren.push_back(std::move(Verbatim));
+
+  // ParamOut
+  CommentInfo ParamOut;
+  ParamOut.Kind = CommentKind::CK_ParamCommandComment;
+  ParamOut.Direction = "[out]";
+  ParamOut.ParamName = "I";
+  ParamOut.Explicit = true;
+  CommentInfo ParamOutPara;
+  ParamOutPara.Kind = CommentKind::CK_ParagraphComment;
+  CommentInfo ParamOutText1;
+  ParamOutText1.Kind = CommentKind::CK_TextComment;
+  CommentInfo ParamOutText2;
+  ParamOutText2.Kind = CommentKind::CK_TextComment;
+  ParamOutText2.Text = "is a parameter.";
+  CommentInfo ParamOutParaChildren[] = {std::move(ParamOutText1),
+                                        std::move(ParamOutText2)};
+  ParamOutPara.Children = ParamOutParaChildren;
+  CommentInfo ParamOutChildren[] = {std::move(ParamOutPara)};
+  ParamOut.Children = ParamOutChildren;
+  TopChildren.push_back(std::move(ParamOut));
+
+  // ParamIn
+  CommentInfo ParamIn;
+  ParamIn.Kind = CommentKind::CK_ParamCommandComment;
+  ParamIn.Direction = "[in]";
+  ParamIn.ParamName = "J";
+  CommentInfo ParamInPara;
+  ParamInPara.Kind = CommentKind::CK_ParagraphComment;
+  CommentInfo ParamInText1;
+  ParamInText1.Kind = CommentKind::CK_TextComment;
+  ParamInText1.Text = "is a parameter.";
+  CommentInfo ParamInText2;
+  ParamInText2.Kind = CommentKind::CK_TextComment;
+  CommentInfo ParamInParaChildren[] = {std::move(ParamInText1),
+                                       std::move(ParamInText2)};
+  ParamInPara.Children = ParamInParaChildren;
+  CommentInfo ParamInChildren[] = {std::move(ParamInPara)};
+  ParamIn.Children = ParamInChildren;
+  TopChildren.push_back(std::move(ParamIn));
+
+  // Return
+  CommentInfo Return;
+  Return.Kind = CommentKind::CK_BlockCommandComment;
+  Return.Name = "return";
+  Return.Explicit = true;
+  CommentInfo ReturnPara;
+  ReturnPara.Kind = CommentKind::CK_ParagraphComment;
+  CommentInfo ReturnText1;
+  ReturnText1.Kind = CommentKind::CK_TextComment;
+  ReturnText1.Text = "void";
+  CommentInfo ReturnParaChildren[] = {std::move(ReturnText1)};
+  ReturnPara.Children = ReturnParaChildren;
+  CommentInfo ReturnChildren[] = {std::move(ReturnPara)};
+  Return.Children = ReturnChildren;
+  TopChildren.push_back(std::move(Return));
+
+  Top.Children = TopChildren;
+
+  I.Description.push_back(Top);
 
   auto G = getMDGenerator();
   assert(G);
diff --git a/clang-tools-extra/unittests/clang-doc/MergeTest.cpp 
b/clang-tools-extra/unittests/clang-doc/MergeTest.cpp
index b42c95c861b61..15b791a044d2d 100644
--- a/clang-tools-extra/unittests/clang-doc/MergeTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/MergeTest.cpp
@@ -166,16 +166,11 @@ TEST_F(MergeTest, mergeFunctionInfos) {
   One.IsMethod = true;
   One.Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace);
 
-  One.Description.emplace_back();
-  auto *OneFullComment = &One.Description.back();
-  OneFullComment->Kind = CommentKind::CK_FullComment;
-  auto OneParagraphComment = allocatePtr<CommentInfo>();
-  OneParagraphComment->Kind = CommentKind::CK_ParagraphComment;
-  auto OneTextComment = allocatePtr<CommentInfo>();
-  OneTextComment->Kind = CommentKind::CK_TextComment;
-  OneTextComment->Text = "This is a text comment.";
-  OneParagraphComment->Children.push_back(std::move(OneTextComment));
-  OneFullComment->Children.push_back(std::move(OneParagraphComment));
+  CommentInfo OneText[] = {
+      CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")};
+  CommentInfo OnePara[] = {
+      CommentInfo(CommentKind::CK_ParagraphComment, OneText)};
+  One.Description.emplace_back(CommentKind::CK_FullComment, OnePara);
 
   FunctionInfo Two;
   Two.Name = "f";
@@ -186,16 +181,11 @@ TEST_F(MergeTest, mergeFunctionInfos) {
   Two.ReturnType = TypeInfo("void");
   Two.Params.emplace_back(TypeInfo("int"), "P");
 
-  Two.Description.emplace_back();
-  auto *TwoFullComment = &Two.Description.back();
-  TwoFullComment->Kind = CommentKind::CK_FullComment;
-  auto TwoParagraphComment = allocatePtr<CommentInfo>();
-  TwoParagraphComment->Kind = CommentKind::CK_ParagraphComment;
-  auto TwoTextComment = allocatePtr<CommentInfo>();
-  TwoTextComment->Kind = CommentKind::CK_TextComment;
-  TwoTextComment->Text = "This is a text comment.";
-  TwoParagraphComment->Children.push_back(std::move(TwoTextComment));
-  TwoFullComment->Children.push_back(std::move(TwoParagraphComment));
+  CommentInfo TwoText[] = {
+      CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")};
+  CommentInfo TwoPara[] = {
+      CommentInfo(CommentKind::CK_ParagraphComment, TwoText)};
+  Two.Description.emplace_back(CommentKind::CK_FullComment, TwoPara);
 
   OwningPtrVec<Info> Infos;
   Infos.emplace_back(allocatePtr<FunctionInfo>(std::move(One)));
@@ -213,16 +203,11 @@ TEST_F(MergeTest, mergeFunctionInfos) {
   Expected->IsMethod = true;
   Expected->Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace);
 
-  Expected->Description.emplace_back();
-  auto *ExpectedFullComment = &Expected->Description.back();
-  ExpectedFullComment->Kind = CommentKind::CK_FullComment;
-  auto ExpectedParagraphComment = allocatePtr<CommentInfo>();
-  ExpectedParagraphComment->Kind = CommentKind::CK_ParagraphComment;
-  auto ExpectedTextComment = allocatePtr<CommentInfo>();
-  ExpectedTextComment->Kind = CommentKind::CK_TextComment;
-  ExpectedTextComment->Text = "This is a text comment.";
-  ExpectedParagraphComment->Children.push_back(std::move(ExpectedTextComment));
-  ExpectedFullComment->Children.push_back(std::move(ExpectedParagraphComment));
+  CommentInfo ExpectedText[] = {
+      CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")};
+  CommentInfo ExpectedPara[] = {
+      CommentInfo(CommentKind::CK_ParagraphComment, ExpectedText)};
+  Expected->Description.emplace_back(CommentKind::CK_FullComment, 
ExpectedPara);
 
   auto Actual = mergeInfos(Infos);
   assert(Actual);
diff --git a/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp 
b/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp
index 5382265b18ab4..a7f8629b926c1 100644
--- a/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp
@@ -93,15 +93,12 @@ TEST_F(YAMLGeneratorTest, emitRecordYAML) {
   I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
 
   // Member documentation.
-  CommentInfo TopComment;
-  TopComment.Kind = CommentKind::CK_FullComment;
-  TopComment.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Brief = TopComment.Children.back().get();
-  Brief->Kind = CommentKind::CK_ParagraphComment;
-  Brief->Children.emplace_back(allocatePtr<CommentInfo>());
-  Brief->Children.back()->Kind = CommentKind::CK_TextComment;
-  Brief->Children.back()->Name = "ParagraphComment";
-  Brief->Children.back()->Text = "Value of the thing.";
+  CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
+                                             "Value of the thing.",
+                                             "ParagraphComment")};
+  CommentInfo TopCommentChildren[] = {
+      CommentInfo(CommentKind::CK_ParagraphComment, BriefChildren)};
+  CommentInfo TopComment(CommentKind::CK_FullComment, TopCommentChildren);
   I.Members.back().Description.push_back(std::move(TopComment));
 
   I.TagType = TagTypeKind::Class;
@@ -377,109 +374,75 @@ TEST_F(YAMLGeneratorTest, emitCommentYAML) {
   I.Params.emplace_back(TypeInfo("int"), "J");
   I.Access = AccessSpecifier::AS_none;
 
-  CommentInfo Top;
-  Top.Kind = CommentKind::CK_FullComment;
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *BlankLine = Top.Children.back().get();
-  BlankLine->Kind = CommentKind::CK_ParagraphComment;
-  BlankLine->Children.emplace_back(allocatePtr<CommentInfo>());
-  BlankLine->Children.back()->Kind = CommentKind::CK_TextComment;
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Brief = Top.Children.back().get();
-  Brief->Kind = CommentKind::CK_ParagraphComment;
-  Brief->Children.emplace_back(allocatePtr<CommentInfo>());
-  Brief->Children.back()->Kind = CommentKind::CK_TextComment;
-  Brief->Children.back()->Name = "ParagraphComment";
-  Brief->Children.back()->Text = " Brief description.";
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Extended = Top.Children.back().get();
-  Extended->Kind = CommentKind::CK_ParagraphComment;
-  Extended->Children.emplace_back(allocatePtr<CommentInfo>());
-  Extended->Children.back()->Kind = CommentKind::CK_TextComment;
-  Extended->Children.back()->Text = " Extended description that";
-  Extended->Children.emplace_back(allocatePtr<CommentInfo>());
-  Extended->Children.back()->Kind = CommentKind::CK_TextComment;
-  Extended->Children.back()->Text = " continues onto the next line.";
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *HTML = Top.Children.back().get();
-  HTML->Kind = CommentKind::CK_ParagraphComment;
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_TextComment;
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_HTMLStartTagComment;
-  HTML->Children.back()->Name = "ul";
-  {
-    llvm::SmallVector<StringRef, 1> Keys = {"class"};
-    HTML->Children.back()->AttrKeys =
-        allocateArray<StringRef>(Keys, TransientArena);
-
-    llvm::SmallVector<StringRef, 1> Values = {"test"};
-    HTML->Children.back()->AttrValues =
-        allocateArray<StringRef>(Values, TransientArena);
-  }
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_HTMLStartTagComment;
-  HTML->Children.back()->Name = "li";
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_TextComment;
-  HTML->Children.back()->Text = " Testing.";
-  HTML->Children.emplace_back(allocatePtr<CommentInfo>());
-  HTML->Children.back()->Kind = CommentKind::CK_HTMLEndTagComment;
-  HTML->Children.back()->Name = "ul";
-  HTML->Children.back()->SelfClosing = true;
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Verbatim = Top.Children.back().get();
-  Verbatim->Kind = CommentKind::CK_VerbatimBlockComment;
-  Verbatim->Name = "verbatim";
-  Verbatim->CloseName = "endverbatim";
-  Verbatim->Children.emplace_back(allocatePtr<CommentInfo>());
-  Verbatim->Children.back()->Kind = CommentKind::CK_VerbatimBlockLineComment;
-  Verbatim->Children.back()->Text = " The description continues.";
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *ParamOut = Top.Children.back().get();
-  ParamOut->Kind = CommentKind::CK_ParamCommandComment;
-  ParamOut->Direction = "[out]";
-  ParamOut->ParamName = "I";
-  ParamOut->Explicit = true;
-  ParamOut->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamOut->Children.back()->Kind = CommentKind::CK_ParagraphComment;
-  ParamOut->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamOut->Children.back()->Children.back()->Kind =
-      CommentKind::CK_TextComment;
-  ParamOut->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamOut->Children.back()->Children.back()->Kind =
-      CommentKind::CK_TextComment;
-  ParamOut->Children.back()->Children.back()->Text = " is a parameter.";
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *ParamIn = Top.Children.back().get();
-  ParamIn->Kind = CommentKind::CK_ParamCommandComment;
-  ParamIn->Direction = "[in]";
-  ParamIn->ParamName = "J";
-  ParamIn->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamIn->Children.back()->Kind = CommentKind::CK_ParagraphComment;
-  ParamIn->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamIn->Children.back()->Children.back()->Kind = 
CommentKind::CK_TextComment;
-  ParamIn->Children.back()->Children.back()->Text = " is a parameter.";
-  ParamIn->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  ParamIn->Children.back()->Children.back()->Kind = 
CommentKind::CK_TextComment;
-
-  Top.Children.emplace_back(allocatePtr<CommentInfo>());
-  CommentInfo *Return = Top.Children.back().get();
-  Return->Kind = CommentKind::CK_BlockCommandComment;
-  Return->Name = "return";
-  Return->Explicit = true;
-  Return->Children.emplace_back(allocatePtr<CommentInfo>());
-  Return->Children.back()->Kind = CommentKind::CK_ParagraphComment;
-  Return->Children.back()->Children.emplace_back(allocatePtr<CommentInfo>());
-  Return->Children.back()->Children.back()->Kind = CommentKind::CK_TextComment;
-  Return->Children.back()->Children.back()->Text = "void";
+  // BlankLine
+  CommentInfo BlankChildren[] = {CommentInfo(CommentKind::CK_TextComment)};
+  CommentInfo BlankLine(CommentKind::CK_ParagraphComment, BlankChildren);
+
+  // Brief
+  CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
+                                             " Brief description.",
+                                             "ParagraphComment")};
+  CommentInfo Brief(CommentKind::CK_ParagraphComment, BriefChildren);
+
+  // Extended
+  CommentInfo ExtChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
+                                           " Extended description that"),
+                               CommentInfo(CommentKind::CK_TextComment, {},
+                                           " continues onto the next line.")};
+  CommentInfo Extended(CommentKind::CK_ParagraphComment, ExtChildren);
+
+  // HTML
+  StringRef HtmlKeys[] = {"class"};
+  StringRef HtmlValues[] = {"test"};
+  CommentInfo HtmlStart(CommentKind::CK_HTMLStartTagComment, {}, "", "ul", "",
+                        "", "", false, false, HtmlKeys, HtmlValues);
+  CommentInfo HtmlStartLi(CommentKind::CK_HTMLStartTagComment, {}, "", "li");
+  CommentInfo HtmlEnd(CommentKind::CK_HTMLEndTagComment, {}, "", "ul", "", "",
+                      "", false, true);
+
+  CommentInfo HtmlChildren[] = {
+      CommentInfo(CommentKind::CK_TextComment), HtmlStart, HtmlStartLi,
+      CommentInfo(CommentKind::CK_TextComment, {}, " Testing."), HtmlEnd};
+  CommentInfo HTML(CommentKind::CK_ParagraphComment, HtmlChildren);
+
+  // Verbatim
+  CommentInfo VerbLine(CommentKind::CK_VerbatimBlockLineComment, {},
+                       " The description continues.");
+  CommentInfo VerbChildren[] = {VerbLine};
+  CommentInfo Verbatim(CommentKind::CK_VerbatimBlockComment, VerbChildren, "",
+                       "verbatim", "endverbatim");
+
+  // ParamOut
+  CommentInfo ParamOutParaChildren[] = {
+      CommentInfo(CommentKind::CK_TextComment),
+      CommentInfo(CommentKind::CK_TextComment, {}, " is a parameter.")};
+  CommentInfo ParamOutPara(CommentKind::CK_ParagraphComment,
+                           ParamOutParaChildren);
+  CommentInfo ParamOutChildren[] = {ParamOutPara};
+  CommentInfo ParamOut(CommentKind::CK_ParamCommandComment, ParamOutChildren,
+                       "", "", "", "[out]", "I", true);
+
+  // ParamIn
+  CommentInfo ParamInParaChildren[] = {
+      CommentInfo(CommentKind::CK_TextComment, {}, " is a parameter."),
+      CommentInfo(CommentKind::CK_TextComment)};
+  CommentInfo ParamInPara(CommentKind::CK_ParagraphComment,
+                          ParamInParaChildren);
+  CommentInfo ParamInChildren[] = {ParamInPara};
+  CommentInfo ParamIn(CommentKind::CK_ParamCommandComment, ParamInChildren, "",
+                      "", "", "[in]", "J");
+
+  // Return
+  CommentInfo ReturnParaChildren[] = {
+      CommentInfo(CommentKind::CK_TextComment, {}, "void")};
+  CommentInfo ReturnPara(CommentKind::CK_ParagraphComment, ReturnParaChildren);
+  CommentInfo ReturnChildren[] = {ReturnPara};
+  CommentInfo Return(CommentKind::CK_BlockCommandComment, ReturnChildren, "",
+                     "return", "", "", "", true);
+
+  CommentInfo TopChildren[] = {BlankLine, Brief,    Extended, HTML,
+                               Verbatim,  ParamOut, ParamIn,  Return};
+  CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
 
   I.Description.emplace_back(std::move(Top));
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to