[clang-tools-extra] [Clang-doc] Display values and comments in MD (PR #183754)
Samrudh Nelli via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 11 09:46:43 PDT 2026
https://github.com/SamrudhNelli updated https://github.com/llvm/llvm-project/pull/183754
>From d9e58f68ad9fa377e91d1778d2393c3bc8451c55 Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Fri, 27 Feb 2026 21:07:37 +0530
Subject: [PATCH 01/20] display in a table format
---
clang-tools-extra/clang-doc/MDGenerator.cpp | 63 ++++-
clang-tools-extra/test/clang-doc/enum.cpp | 284 +++++++++++++++-----
2 files changed, 277 insertions(+), 70 deletions(-)
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index fcb75af80f9e9..6fd0bf2df038a 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -67,6 +67,30 @@ static void writeSourceFileRef(const ClangDocContext &CDCtx, const Location &L,
OS << "\n\n";
}
+static std::string genRawText(const std::vector<CommentInfo> &Comments) {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ std::queue<const CommentInfo *> Q;
+ for (const auto &CI : Comments)
+ Q.push(&CI);
+ const CommentInfo *Comment;
+ bool First = true;
+ while (Q.size()) {
+ Comment = Q.front();
+ Q.pop();
+ if (!Comment->Text.empty())
+ {
+ if (!First)
+ OS << "<br>";
+ OS << Comment->Text;
+ First = false;
+ }
+ for (const auto &CI : Comment->Children)
+ Q.push(CI.get());
+ }
+ return Result;
+}
+
static void maybeWriteSourceFileRef(llvm::raw_ostream &OS,
const ClangDocContext &CDCtx,
const std::optional<Location> &DefLoc) {
@@ -157,16 +181,41 @@ static void writeNameLink(const StringRef &CurrentPath, const Reference &R,
static void genMarkdown(const ClangDocContext &CDCtx, const EnumInfo &I,
llvm::raw_ostream &OS) {
if (I.Scoped)
- writeLine("| enum class " + I.Name + " |", OS);
- else
- writeLine("| enum " + I.Name + " |", OS);
- writeLine("--", OS);
+ OS << "class ";
+ OS << (I.Name.empty() ? "(unnamed)" : StringRef(I.Name)) << " ";
+ if (I.BaseType && !I.BaseType->Type.QualName.empty()) {
+ OS << ": " << I.BaseType->Type.QualName << " ";
+ }
+ OS << "|\n\n";
std::string Buffer;
llvm::raw_string_ostream Members(Buffer);
- if (!I.Members.empty())
- for (const auto &N : I.Members)
- Members << "| " << N.Name << " |\n";
+ Members << "| Name | Value |";
+ if (!I.Members.empty()) {
+ bool HasComments = false;
+ for (const auto &Member : I.Members) {
+ if (!Member.Description.empty()) {
+ HasComments = true;
+ Members << " Comments |";
+ break;
+ }
+ }
+ Members << "\n";
+ Members << "|:-:|:-:|";
+ if (HasComments)
+ Members << ":-:|";
+ Members << "\n";
+ for (const auto &N : I.Members) {
+ Members << "| " << N.Name << " ";
+ if (!N.Value.empty())
+ Members << "| " << N.Value << " ";
+ if (HasComments) {
+ std::string RawComment = StringRef(genRawText(N.Description)).trim().str();
+ Members << "| " << (RawComment.empty() ? "--" : RawComment) << " ";
+ }
+ Members << "|\n";
+ }
+ }
writeLine(Members.str(), OS);
maybeWriteSourceFileRef(OS, CDCtx, I.DefLoc);
diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp
index 6e11bbf065f25..c58d94404fcdc 100644
--- a/clang-tools-extra/test/clang-doc/enum.cpp
+++ b/clang-tools-extra/test/clang-doc/enum.cpp
@@ -30,9 +30,9 @@ enum Color {
// MD-INDEX: ## Enums
// MD-INDEX: | enum Color |
// MD-INDEX: --
-// MD-INDEX: | Red |
-// MD-INDEX: | Green |
-// MD-INDEX: | Blue |
+// MD-INDEX: | Red | 0 | Comment 1 |
+// MD-INDEX: | Green | Comment 2 |
+// MD-INDEX: | Blue | Comment 3 |
// MD-INDEX: **brief** For specifying RGB colors
// HTML-INDEX: <div>
@@ -73,37 +73,192 @@ enum class Shapes {
/// Comment 3
Triangle
};
+
// MD-INDEX: | enum class Shapes |
// MD-INDEX: --
-// MD-INDEX: | Circle |
-// MD-INDEX: | Rectangle |
-// MD-INDEX: | Triangle |
+// MD-INDEX: | Circle | 0 | Comment 1 |
+// MD-INDEX: | Rectangle | 1 | Comment 2 |
+// MD-INDEX: | Triangle | 2 | Comment 3 |
// MD-INDEX: **brief** Shape Types
-// COM: FIXME: Serialize "enum class" in template
-// HTML-INDEX: <div>
-// HTML-INDEX: <pre><code class="language-cpp code-clang-doc">enum Shapes</code></pre>
-// HTML-INDEX: </div>
-// HTML-INDEX: <table class="table-wrapper">
-// HTML-INDEX: <tbody>
-// HTML-INDEX: <tr>
-// HTML-INDEX: <th>Name</th>
-// HTML-INDEX: <th>Value</th>
-// HTML-INDEX: </tr>
-// HTML-INDEX: <tr>
-// HTML-INDEX: <td>Circle</td>
-// HTML-INDEX: <td>0</td>
-// HTML-INDEX: </tr>
-// HTML-INDEX: <tr>
-// HTML-INDEX: <td>Rectangle</td>
-// HTML-INDEX: <td>1</td>
-// HTML-INDEX: </tr>
-// HTML-INDEX: <tr>
-// HTML-INDEX: <td>Triangle</td>
-// HTML-INDEX: <td>2</td>
-// HTML-INDEX: </tr>
-// HTML-INDEX: </tbody>
-// HTML-INDEX: </table>
+// HTML-INDEX-LABEL: <div id="{{([0-9A-F]{40})}}" class="delimiter-container">
+// HTML-INDEX-NEXT: <div>
+// HTML-INDEX-NEXT: <pre><code class="language-cpp code-clang-doc">enum class Shapes</code></pre>
+// HTML-INDEX-NEXT: </div>
+// HTML-INDEX-NEXT: <table class="table-wrapper">
+// HTML-INDEX-NEXT: <tbody>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <th>Name</th>
+// HTML-INDEX-NEXT: <th>Value</th>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <td>Circle</td>
+// HTML-INDEX-NEXT: <td>0</td>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <td>Rectangle</td>
+// HTML-INDEX-NEXT: <td>1</td>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <td>Triangle</td>
+// HTML-INDEX-NEXT: <td>2</td>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: </tbody>
+// HTML-INDEX-NEXT: </table>
+// HTML-INDEX-NEXT: <div class="doc-card">
+// HTML-INDEX-NEXT: <div class="nested-delimiter-container">
+// HTML-INDEX-NEXT: <p> Shape Types</p>
+// HTML-INDEX-NEXT: </div>
+// HTML-INDEX-NEXT: </div>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-48]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: </div>
+
+typedef unsigned char uint8_t;
+/**
+ * @brief Specify the size
+ */
+enum Size : uint8_t {
+ // MD-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]*
+ // HTML-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+ Small, ///< A pearl
+ Medium, ///< A tennis ball
+ Large ///< A football
+};
+
+// MD-INDEX: | enum Size : uint8_t |
+// MD-INDEX: --
+// MD-INDEX: | Small | 0 | A pearl |
+// MD-INDEX: | Medium | 1 | A tennis ball |
+// MD-INDEX: | Large | 2 | A football |
+// MD-INDEX: **brief** Specify the size
+
+// HTML-INDEX-LABEL: <div id="{{([0-9A-F]{40})}}" class="delimiter-container">
+// HTML-INDEX-NEXT: <div>
+// HTML-INDEX-NEXT: <pre><code class="language-cpp code-clang-doc">enum Size : uint8_t</code></pre>
+// HTML-INDEX-NEXT: </div>
+// HTML-INDEX-NEXT: <table class="table-wrapper">
+// HTML-INDEX-NEXT: <tbody>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <th>Name</th>
+// HTML-INDEX-NEXT: <th>Value</th>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <td>Small</td>
+// HTML-INDEX-NEXT: <td>0</td>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <td>Medium</td>
+// HTML-INDEX-NEXT: <td>1</td>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <td>Large</td>
+// HTML-INDEX-NEXT: <td>2</td>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: </tbody>
+// HTML-INDEX-NEXT: </table>
+// HTML-INDEX-NEXT: <div class="doc-card">
+// HTML-INDEX-NEXT: <div class="nested-delimiter-container">
+// HTML-INDEX-NEXT: <p> Specify the size</p>
+// HTML-INDEX-NEXT: </div>
+// HTML-INDEX-NEXT: </div>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-44]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: </div>
+
+/**
+ * @brief Very long number
+ */
+enum : long long {
+ // MD-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]*
+ // HTML-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+ BigVal = 999999999999 ///< A very large value
+};
+
+// MD-INDEX: | enum (unnamed) : long long |
+// MD-INDEX: --
+// MD-INDEX: | BigVal | 999999999999 | A very large value |
+// MD-INDEX: **brief** Very long number
+
+// HTML-INDEX-LABEL: <div id="{{([0-9A-F]{40})}}" class="delimiter-container">
+// HTML-INDEX-NEXT: <div>
+// HTML-INDEX-NEXT: <pre><code class="language-cpp code-clang-doc">enum (unnamed) : long long</code></pre>
+// HTML-INDEX-NEXT: </div>
+// HTML-INDEX-NEXT: <table class="table-wrapper">
+// HTML-INDEX-NEXT: <tbody>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <th>Name</th>
+// HTML-INDEX-NEXT: <th>Value</th>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <td>BigVal</td>
+// HTML-INDEX-NEXT: <td>999999999999</td>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: </tbody>
+// HTML-INDEX-NEXT: </table>
+// HTML-INDEX-NEXT: <div class="doc-card">
+// HTML-INDEX-NEXT: <div class="nested-delimiter-container">
+// HTML-INDEX-NEXT: <p> Very long number</p>
+// HTML-INDEX-NEXT: </div>
+// HTML-INDEX-NEXT: </div>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-32]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: </div>
+
+class FilePermissions {
+// MD-PERM-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]*
+// HTML-PERM-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+public:
+ /**
+ * @brief File permission flags
+ */
+ enum {
+ // MD-PERM-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]*
+ // HTML-PERM-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+ Read = 1, ///> Permission to READ r
+ Write = 2, ///> Permission to WRITE w
+ Execute = 4 ///> Permission to EXECUTE x
+ };
+};
+
+// MD-PERM: | enum (unnamed) |
+// MD-PERM: --
+// MD-PERM: | Read | 1 | Permission to READ r |
+// MD-PERM: | Write | 2 | Permission to WRITE w |
+// MD-PERM: | Execute | 4 | Permission to EXECUTE x |
+// MD-PERM: **brief** File permission flags
+
+// HTML-PERM-LABEL: <section id="Enums" class="section-container">
+// HTML-PERM-NEXT: <h2>Enumerations</h2>
+// HTML-PERM-NEXT: <div id="{{([0-9A-F]{40})}}" class="delimiter-container">
+// HTML-PERM-NEXT: <div>
+// HTML-PERM-NEXT: <pre><code class="language-cpp code-clang-doc">enum (unnamed)</code></pre>
+// HTML-PERM-NEXT: </div>
+// HTML-PERM-NEXT: <table class="table-wrapper">
+// HTML-PERM-NEXT: <tbody>
+// HTML-PERM-NEXT: <tr>
+// HTML-PERM-NEXT: <th>Name</th>
+// HTML-PERM-NEXT: <th>Value</th>
+// HTML-PERM-NEXT: </tr>
+// HTML-PERM-NEXT: <tr>
+// HTML-PERM-NEXT: <td>Read</td>
+// HTML-PERM-NEXT: <td>1</td>
+// HTML-PERM-NEXT: </tr>
+// HTML-PERM-NEXT: <tr>
+// HTML-PERM-NEXT: <td>Write</td>
+// HTML-PERM-NEXT: <td>2</td>
+// HTML-PERM-NEXT: </tr>
+// HTML-PERM-NEXT: <tr>
+// HTML-PERM-NEXT: <td>Execute</td>
+// HTML-PERM-NEXT: <td>4</td>
+// HTML-PERM-NEXT: </tr>
+// HTML-PERM-NEXT: </tbody>
+// HTML-PERM-NEXT: </table>
+// HTML-PERM-NEXT: <div class="doc-card">
+// HTML-PERM-NEXT: <div class="nested-delimiter-container">
+// HTML-PERM-NEXT: <p> File permission flags</p>
+// HTML-PERM-NEXT: </div>
+// HTML-PERM-NEXT: </div>
+// HTML-PERM-NEXT: <p>Defined at line [[@LINE-47]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-PERM-NEXT: </div>
+// HTML-PERM-NEXT: </section>
// COM: FIXME: Add enums declared inside of classes to class template
class Animals {
@@ -161,9 +316,9 @@ class Animals {
// MD-ANIMAL: ## Enums
// MD-ANIMAL: | enum AnimalType |
// MD-ANIMAL: --
-// MD-ANIMAL: | Dog |
-// MD-ANIMAL: | Cat |
-// MD-ANIMAL: | Iguana |
+// MD-ANIMAL: | Dog | 0 | Man's best friend |
+// MD-ANIMAL: | Cat | 1 | Man's other best friend |
+// MD-ANIMAL: | Iguana | 2 | A lizard |
// MD-ANIMAL: **brief** specify what animal the class is
namespace Vehicles {
@@ -185,10 +340,10 @@ enum Car {
// MD-VEHICLES: ## Enums
// MD-VEHICLES: | enum Car |
// MD-VEHICLES: --
-// MD-VEHICLES: | Sedan |
-// MD-VEHICLES: | SUV |
-// MD-VEHICLES: | Pickup |
-// MD-VEHICLES: | Hatchback |
+// MD-VEHICLES: | Sedan | 0 | Comment 1 |
+// MD-VEHICLES: | SUV | 1 | Comment 2 |
+// MD-VEHICLES: | Pickup | 2 | Comment 3 |
+// MD-VEHICLES: | Hatchback | 3 | Comment 4 |
// MD-VEHICLES: **brief** specify type of car
// HTML-VEHICLES: <div>
@@ -227,30 +382,33 @@ enum ColorUserSpecified {
// MD-INDEX: | enum ColorUserSpecified |
// MD-INDEX: --
-// MD-INDEX: | RedUserSpecified |
-// MD-INDEX: | GreenUserSpecified |
-// MD-INDEX: | BlueUserSpecified |
+// MD-INDEX: | RedUserSpecified | 65 |
+// MD-INDEX: | GreenUserSpecified | 2 |
+// MD-INDEX: | BlueUserSpecified | 67 |
-// HTML-INDEX: <div>
-// HTML-INDEX: <pre><code class="language-cpp code-clang-doc">enum ColorUserSpecified</code></pre>
-// HTML-INDEX: </div>
-// HTML-INDEX: <table class="table-wrapper">
-// HTML-INDEX: <tbody>
-// HTML-INDEX: <tr>
-// HTML-INDEX: <th>Name</th>
-// HTML-INDEX: <th>Value</th>
-// HTML-INDEX: </tr>
-// HTML-INDEX: <tr>
-// HTML-INDEX: <td>RedUserSpecified</td>
-// HTML-INDEX: <td>'A'</td>
-// HTML-INDEX: </tr>
-// HTML-INDEX: <tr>
-// HTML-INDEX: <td>GreenUserSpecified</td>
-// HTML-INDEX: <td>2</td>
-// HTML-INDEX: </tr>
-// HTML-INDEX: <tr>
-// HTML-INDEX: <td>BlueUserSpecified</td>
-// HTML-INDEX: <td>'C'</td>
-// HTML-INDEX: </tr>
-// HTML-INDEX: </tbody>
-// HTML-INDEX: </table>
+// HTML-INDEX-LABEL: <div id="{{([0-9A-F]{40})}}" class="delimiter-container">
+// HTML-INDEX-NEXT: <div>
+// HTML-INDEX-NEXT: <pre><code class="language-cpp code-clang-doc">enum ColorUserSpecified</code></pre>
+// HTML-INDEX-NEXT: </div>
+// HTML-INDEX-NEXT: <table class="table-wrapper">
+// HTML-INDEX-NEXT: <tbody>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <th>Name</th>
+// HTML-INDEX-NEXT: <th>Value</th>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <td>RedUserSpecified</td>
+// HTML-INDEX-NEXT: <td>'A'</td>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <td>GreenUserSpecified</td>
+// HTML-INDEX-NEXT: <td>2</td>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: <tr>
+// HTML-INDEX-NEXT: <td>BlueUserSpecified</td>
+// HTML-INDEX-NEXT: <td>'C'</td>
+// HTML-INDEX-NEXT: </tr>
+// HTML-INDEX-NEXT: </tbody>
+// HTML-INDEX-NEXT: </table>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-36]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: </div>
>From 7ee114499bf2dd88895ed16a0b463fd9c9ad3ced Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Mon, 2 Mar 2026 14:46:12 +0530
Subject: [PATCH 02/20] fix tests
---
clang-tools-extra/test/clang-doc/enum.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp
index c58d94404fcdc..280c8892e4d43 100644
--- a/clang-tools-extra/test/clang-doc/enum.cpp
+++ b/clang-tools-extra/test/clang-doc/enum.cpp
@@ -31,8 +31,8 @@ enum Color {
// MD-INDEX: | enum Color |
// MD-INDEX: --
// MD-INDEX: | Red | 0 | Comment 1 |
-// MD-INDEX: | Green | Comment 2 |
-// MD-INDEX: | Blue | Comment 3 |
+// MD-INDEX: | Green | 1 | Comment 2 |
+// MD-INDEX: | Blue | 2 | Comment 3 |
// MD-INDEX: **brief** For specifying RGB colors
// HTML-INDEX: <div>
>From 9b75c69c8aad9f5ecffe2d096a398d7358b40558 Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Mon, 2 Mar 2026 17:16:34 +0530
Subject: [PATCH 03/20] fix tests
---
clang-tools-extra/clang-doc/MDGenerator.cpp | 3 +-
clang-tools-extra/test/clang-doc/enum.cpp | 65 ++++++++++++-------
.../unittests/clang-doc/MDGeneratorTest.cpp | 14 ++--
3 files changed, 48 insertions(+), 34 deletions(-)
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index 665c86bfa2016..53605850b7a47 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -82,8 +82,9 @@ static std::string genRawText(const std::vector<CommentInfo> &Comments) {
{
if (!First)
OS << "<br>";
+ else
+ First = false;
OS << Comment->Text;
- First = false;
}
for (const auto &CI : Comment->Children)
Q.push(CI.get());
diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp
index 6730ad96934f1..d0a308c2d055f 100644
--- a/clang-tools-extra/test/clang-doc/enum.cpp
+++ b/clang-tools-extra/test/clang-doc/enum.cpp
@@ -33,7 +33,8 @@ enum Color {
// MD-INDEX: ## Enums
// MD-INDEX: | enum Color |
-// MD-INDEX: --
+// MD-INDEX: | Name | Value | Comments |
+// MD-INDEX: |:-:|:-:|:-:|
// MD-INDEX: | Red | 0 | Comment 1 |
// MD-INDEX: | Green | 1 | Comment 2 |
// MD-INDEX: | Blue | 2 | Comment 3 |
@@ -68,7 +69,7 @@ enum Color {
// HTML-INDEX-NEXT: <p> For specifying RGB colors</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-45]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-46]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
/**
@@ -87,7 +88,8 @@ enum class Shapes {
};
// MD-INDEX: | enum class Shapes |
-// MD-INDEX: --
+// MD-INDEX: | Name | Value | Comments |
+// MD-INDEX: |:-:|:-:|:-:|
// MD-INDEX: | Circle | 0 | Comment 1 |
// MD-INDEX: | Rectangle | 1 | Comment 2 |
// MD-INDEX: | Triangle | 2 | Comment 3 |
@@ -122,7 +124,7 @@ enum class Shapes {
// HTML-INDEX-NEXT: <p> Shape Types</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-48]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-49]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
typedef unsigned char uint8_t;
@@ -132,16 +134,26 @@ typedef unsigned char uint8_t;
enum Size : uint8_t {
// MD-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]*
// HTML-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
- Small, ///< A pearl
- Medium, ///< A tennis ball
- Large ///< A football
+
+ /// A pearl.
+ /// Pearls are quite small.
+ ///
+ /// Pearls are used in jewelry.
+ Small,
+
+ /// @brief A tennis ball.
+ Medium,
+
+ /// A football.
+ Large
};
// MD-INDEX: | enum Size : uint8_t |
-// MD-INDEX: --
-// MD-INDEX: | Small | 0 | A pearl |
-// MD-INDEX: | Medium | 1 | A tennis ball |
-// MD-INDEX: | Large | 2 | A football |
+// MD-INDEX: | Name | Value | Comments |
+// MD-INDEX: |:-:|:-:|:-:|
+// MD-INDEX: | Small | 0 | A pearl.<br> Pearls are quite small.<br> Pearls are used in jewelry. |
+// MD-INDEX: | Medium | 1 | A tennis ball. |
+// MD-INDEX: | Large | 2 | A football. |
// MD-INDEX: **brief** Specify the size
// HTML-INDEX-LABEL: <div id="{{([0-9A-F]{40})}}" class="delimiter-container">
@@ -173,7 +185,7 @@ enum Size : uint8_t {
// HTML-INDEX-NEXT: <p> Specify the size</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-44]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-54]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
/**
@@ -186,7 +198,8 @@ enum : long long {
};
// MD-INDEX: | enum (unnamed) : long long |
-// MD-INDEX: --
+// MD-INDEX: | Name | Value | Comments |
+// MD-INDEX: |:-:|:-:|:-:|
// MD-INDEX: | BigVal | 999999999999 | A very large value |
// MD-INDEX: **brief** Very long number
@@ -211,7 +224,7 @@ enum : long long {
// HTML-INDEX-NEXT: <p> Very long number</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-32]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-33]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
class FilePermissions {
@@ -224,14 +237,15 @@ class FilePermissions {
enum {
// MD-PERM-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]*
// HTML-PERM-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
- Read = 1, ///> Permission to READ r
- Write = 2, ///> Permission to WRITE w
- Execute = 4 ///> Permission to EXECUTE x
+ Read = 1, ///< Permission to READ r
+ Write = 2, ///< Permission to WRITE w
+ Execute = 4 ///< Permission to EXECUTE x
};
};
// MD-PERM: | enum (unnamed) |
-// MD-PERM: --
+// MD-PERM: | Name | Value | Comments |
+// MD-PERM: |:-:|:-:|:-:|
// MD-PERM: | Read | 1 | Permission to READ r |
// MD-PERM: | Write | 2 | Permission to WRITE w |
// MD-PERM: | Execute | 4 | Permission to EXECUTE x |
@@ -268,7 +282,7 @@ class FilePermissions {
// HTML-PERM-NEXT: <p> File permission flags</p>
// HTML-PERM-NEXT: </div>
// HTML-PERM-NEXT: </div>
-// HTML-PERM-NEXT: <p>Defined at line [[@LINE-47]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-PERM-NEXT: <p>Defined at line [[@LINE-48]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-PERM-NEXT: </div>
// HTML-PERM-NEXT: </section>
@@ -327,7 +341,8 @@ class Animals {
// MD-ANIMAL: # class Animals
// MD-ANIMAL: ## Enums
// MD-ANIMAL: | enum AnimalType |
-// MD-ANIMAL: --
+// MD-ANIMAL: | Name | Value | Comments |
+// MD-ANIMAL: |:-:|:-:|:-:|
// MD-ANIMAL: | Dog | 0 | Man's best friend |
// MD-ANIMAL: | Cat | 1 | Man's other best friend |
// MD-ANIMAL: | Iguana | 2 | A lizard |
@@ -351,7 +366,8 @@ enum Car {
// MD-VEHICLES: # namespace Vehicles
// MD-VEHICLES: ## Enums
// MD-VEHICLES: | enum Car |
-// MD-VEHICLES: --
+// MD-VEHICLES: | Name | Value | Comments |
+// MD-VEHICLES: |:-:|:-:|:-:|
// MD-VEHICLES: | Sedan | 0 | Comment 1 |
// MD-VEHICLES: | SUV | 1 | Comment 2 |
// MD-VEHICLES: | Pickup | 2 | Comment 3 |
@@ -391,7 +407,7 @@ enum Car {
// HTML-VEHICLES-NEXT: <p> specify type of car</p>
// HTML-VEHICLES-NEXT: </div>
// HTML-VEHICLES-NEXT: </div>
-// HTML-VEHICLES-NEXT: <p>Defined at line [[@LINE-54]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-VEHICLES-NEXT: <p>Defined at line [[@LINE-55]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-VEHICLES-NEXT: </div>
enum ColorUserSpecified {
@@ -401,7 +417,8 @@ enum ColorUserSpecified {
};
// MD-INDEX: | enum ColorUserSpecified |
-// MD-INDEX: --
+// MD-INDEX: | Name | Value |
+// MD-INDEX: |:-:|:-:|
// MD-INDEX: | RedUserSpecified | 65 |
// MD-INDEX: | GreenUserSpecified | 2 |
// MD-INDEX: | BlueUserSpecified | 67 |
@@ -430,5 +447,5 @@ enum ColorUserSpecified {
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: </tbody>
// HTML-INDEX-NEXT: </table>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-36]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-37]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
diff --git a/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp
index b44b09b28e90f..d9f32f8eabc41 100644
--- a/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp
@@ -69,9 +69,7 @@ TEST_F(MDGeneratorTest, emitNamespaceMD) {
| enum OneEnum |
---
-
-
+| Name | Value |
@@ -136,9 +134,7 @@ ChildStruct
| enum OneEnum |
---
-
-
+| Name | Value |
@@ -197,9 +193,9 @@ TEST_F(MDGeneratorTest, emitEnumMD) {
assert(!Err);
std::string Expected = R"raw(| enum class e |
---
-
-| X |
+| Name | Value |
+|:-:|:-:|
+| X | 0 |
*Defined at test.cpp#10*
>From 9980251ef58bc63792bcb23b59e4a3fc0403b071 Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Mon, 2 Mar 2026 17:19:15 +0530
Subject: [PATCH 04/20] format the code
---
clang-tools-extra/clang-doc/MDGenerator.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index 53605850b7a47..c410be0b1769b 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -82,7 +82,7 @@ static std::string genRawText(const std::vector<CommentInfo> &Comments) {
{
if (!First)
OS << "<br>";
- else
+ else
First = false;
OS << Comment->Text;
}
>From 87cb5c17c728906b67d86bc0557a7f974daf9960 Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Mon, 2 Mar 2026 17:28:00 +0530
Subject: [PATCH 05/20] clang-format the code
---
clang-tools-extra/clang-doc/MDGenerator.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index c410be0b1769b..e6b67fdec81e3 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -78,8 +78,7 @@ static std::string genRawText(const std::vector<CommentInfo> &Comments) {
while (Q.size()) {
Comment = Q.front();
Q.pop();
- if (!Comment->Text.empty())
- {
+ if (!Comment->Text.empty()) {
if (!First)
OS << "<br>";
else
@@ -212,7 +211,8 @@ static void genMarkdown(const ClangDocContext &CDCtx, const EnumInfo &I,
if (!N.Value.empty())
Members << "| " << N.Value << " ";
if (HasComments) {
- std::string RawComment = StringRef(genRawText(N.Description)).trim().str();
+ std::string RawComment =
+ StringRef(genRawText(N.Description)).trim().str();
Members << "| " << (RawComment.empty() ? "--" : RawComment) << " ";
}
Members << "|\n";
>From 96a9e19a3593acd7c385332a1677807dde0cc1da Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Wed, 4 Mar 2026 19:37:22 +0530
Subject: [PATCH 06/20] Switch to a recursive solution to handle paragraphs
---
clang-tools-extra/clang-doc/MDGenerator.cpp | 63 +++++++++++++--------
clang-tools-extra/test/clang-doc/enum.cpp | 2 +-
2 files changed, 41 insertions(+), 24 deletions(-)
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index e6b67fdec81e3..bec44a88944bb 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -8,7 +8,9 @@
#include "Generators.h"
#include "Representation.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
@@ -67,28 +69,42 @@ static void writeSourceFileRef(const ClangDocContext &CDCtx, const Location &L,
OS << "\n\n";
}
-static std::string genRawText(const std::vector<CommentInfo> &Comments) {
- std::string Result;
- llvm::raw_string_ostream OS(Result);
- std::queue<const CommentInfo *> Q;
- for (const auto &CI : Comments)
- Q.push(&CI);
- const CommentInfo *Comment;
- bool First = true;
- while (Q.size()) {
- Comment = Q.front();
- Q.pop();
- if (!Comment->Text.empty()) {
- if (!First)
- OS << "<br>";
- else
- First = false;
- OS << Comment->Text;
+static void extractChildComment(const CommentInfo &Comment,
+ llvm::raw_ostream &OS, bool &FirstLine,
+ bool &FirstParagraph, bool &ParagraphBreak) {
+ if (Comment.Kind == CommentKind::CK_ParagraphComment) {
+ if (!FirstParagraph)
+ ParagraphBreak = true;
+ }
+
+ if (!Comment.Text.empty()) {
+ if (FirstParagraph)
+ FirstParagraph = false;
+ if (ParagraphBreak) {
+ OS << "<br><br>";
+ ParagraphBreak = false;
+ FirstLine = true;
}
- for (const auto &CI : Comment->Children)
- Q.push(CI.get());
+
+ if (!FirstLine)
+ OS << "<br>";
+ else
+ FirstLine = false;
+
+ OS << Comment.Text;
}
- return Result;
+
+ for (const auto &Child : Comment.Children)
+ extractChildComment(*Child, OS, FirstLine, FirstParagraph, ParagraphBreak);
+}
+
+static void genCommentString(ArrayRef<CommentInfo> Comments,
+ std::string &Buffer) {
+ llvm::raw_string_ostream OS(Buffer);
+ bool FirstLine = true, FirstParagraph = true, ParagraphBreak = false;
+
+ for (const auto &Child : Comments)
+ extractChildComment(Child, OS, FirstLine, FirstParagraph, ParagraphBreak);
}
static void maybeWriteSourceFileRef(llvm::raw_ostream &OS,
@@ -211,9 +227,10 @@ static void genMarkdown(const ClangDocContext &CDCtx, const EnumInfo &I,
if (!N.Value.empty())
Members << "| " << N.Value << " ";
if (HasComments) {
- std::string RawComment =
- StringRef(genRawText(N.Description)).trim().str();
- Members << "| " << (RawComment.empty() ? "--" : RawComment) << " ";
+ std::string CommentString;
+ genCommentString(ArrayRef(N.Description), CommentString);
+ Members << "| " << (CommentString.empty() ? "--" : CommentString)
+ << " ";
}
Members << "|\n";
}
diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp
index d0a308c2d055f..6cb7c3fcdbdc5 100644
--- a/clang-tools-extra/test/clang-doc/enum.cpp
+++ b/clang-tools-extra/test/clang-doc/enum.cpp
@@ -151,7 +151,7 @@ enum Size : uint8_t {
// MD-INDEX: | enum Size : uint8_t |
// MD-INDEX: | Name | Value | Comments |
// MD-INDEX: |:-:|:-:|:-:|
-// MD-INDEX: | Small | 0 | A pearl.<br> Pearls are quite small.<br> Pearls are used in jewelry. |
+// MD-INDEX: | Small | 0 | A pearl.<br> Pearls are quite small.<br><br> Pearls are used in jewelry. |
// MD-INDEX: | Medium | 1 | A tennis ball. |
// MD-INDEX: | Large | 2 | A football. |
// MD-INDEX: **brief** Specify the size
>From fdae5455175fd2952b68afa22283234fe42259b2 Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Wed, 4 Mar 2026 19:47:30 +0530
Subject: [PATCH 07/20] remove unused header file
---
clang-tools-extra/clang-doc/MDGenerator.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index bec44a88944bb..ebbeda08dad28 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -10,7 +10,6 @@
#include "Representation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
>From ed2830985d476d38dcfdf1c7f9d499a12aead6fd Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Fri, 6 Mar 2026 03:47:14 +0530
Subject: [PATCH 08/20] implement paragraph breaks without using boolean flags
---
clang-tools-extra/clang-doc/MDGenerator.cpp | 68 +++++++++++----------
1 file changed, 36 insertions(+), 32 deletions(-)
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index ebbeda08dad28..3629307350a41 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -68,42 +68,47 @@ static void writeSourceFileRef(const ClangDocContext &CDCtx, const Location &L,
OS << "\n\n";
}
-static void extractChildComment(const CommentInfo &Comment,
- llvm::raw_ostream &OS, bool &FirstLine,
- bool &FirstParagraph, bool &ParagraphBreak) {
- if (Comment.Kind == CommentKind::CK_ParagraphComment) {
- if (!FirstParagraph)
- ParagraphBreak = true;
- }
+static std::string extractCommentText(const CommentInfo &Comment) {
+ std::vector<std::string> Parts;
+
+ if (!Comment.Text.empty())
+ Parts.push_back(StringRef(Comment.Text).str());
+
+ for (size_t Idx = 0; Idx < Comment.Children.size(); ++Idx) {
+ const auto &Child = Comment.Children[Idx];
+ std::string ChildText = extractCommentText(*Child);
- if (!Comment.Text.empty()) {
- if (FirstParagraph)
- FirstParagraph = false;
- if (ParagraphBreak) {
- OS << "<br><br>";
- ParagraphBreak = false;
- FirstLine = true;
+ if (ChildText.empty())
+ continue;
+
+ if (Idx > 0 && Comment.Kind == CommentKind::CK_ParagraphComment) {
+ if (Comment.Children[Idx - 1]->Kind == CommentKind::CK_TextComment &&
+ Child->Kind == CommentKind::CK_TextComment) {
+ Parts.push_back("<br>");
+ }
}
- if (!FirstLine)
- OS << "<br>";
- else
- FirstLine = false;
+ Parts.push_back(ChildText);
+ }
- OS << Comment.Text;
+ if (Comment.Kind == CommentKind::CK_BlockCommandComment ||
+ Comment.Kind == CommentKind::CK_FullComment) {
+ return llvm::join(Parts, "<br><br>");
}
- for (const auto &Child : Comment.Children)
- extractChildComment(*Child, OS, FirstLine, FirstParagraph, ParagraphBreak);
+ return llvm::join(Parts, "");
}
-static void genCommentString(ArrayRef<CommentInfo> Comments,
- std::string &Buffer) {
- llvm::raw_string_ostream OS(Buffer);
- bool FirstLine = true, FirstParagraph = true, ParagraphBreak = false;
-
- for (const auto &Child : Comments)
- extractChildComment(Child, OS, FirstLine, FirstParagraph, ParagraphBreak);
+static void genCommentString(llvm::ArrayRef<CommentInfo> Comments,
+ llvm::raw_ostream &OS) {
+ std::string CommentText = "";
+ for (const auto &Child : Comments) {
+ CommentText += extractCommentText(Child);
+ }
+ if (!CommentText.empty())
+ OS << CommentText;
+ else
+ OS << "--";
}
static void maybeWriteSourceFileRef(llvm::raw_ostream &OS,
@@ -226,10 +231,9 @@ static void genMarkdown(const ClangDocContext &CDCtx, const EnumInfo &I,
if (!N.Value.empty())
Members << "| " << N.Value << " ";
if (HasComments) {
- std::string CommentString;
- genCommentString(ArrayRef(N.Description), CommentString);
- Members << "| " << (CommentString.empty() ? "--" : CommentString)
- << " ";
+ Members << "| ";
+ genCommentString(ArrayRef(N.Description), Members);
+ Members << " ";
}
Members << "|\n";
}
>From 4468b4bcb897e79ce8ad83461676b41ddecf0d0d Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Fri, 6 Mar 2026 22:11:41 +0530
Subject: [PATCH 09/20] use streams rather than vector of strings
---
clang-tools-extra/clang-doc/MDGenerator.cpp | 49 ++++++++++-----------
1 file changed, 24 insertions(+), 25 deletions(-)
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index 3629307350a41..e0b05cd5f5d5b 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -9,11 +9,13 @@
#include "Generators.h"
#include "Representation.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
#include <string>
using namespace llvm;
@@ -68,46 +70,43 @@ static void writeSourceFileRef(const ClangDocContext &CDCtx, const Location &L,
OS << "\n\n";
}
-static std::string extractCommentText(const CommentInfo &Comment) {
- std::vector<std::string> Parts;
+static void extractCommentText(const CommentInfo &Comment,
+ llvm::raw_ostream &OS) {
- if (!Comment.Text.empty())
- Parts.push_back(StringRef(Comment.Text).str());
+ OS << Comment.Text;
+ bool FirstChild = true;
- for (size_t Idx = 0; Idx < Comment.Children.size(); ++Idx) {
+ for (size_t Idx = 0, End = Comment.Children.size(); Idx < End; ++Idx) {
const auto &Child = Comment.Children[Idx];
- std::string ChildText = extractCommentText(*Child);
+ llvm::SmallString<128> ChildBuffer;
+ llvm::raw_svector_ostream ChildOS(ChildBuffer);
+ extractCommentText(*Child, ChildOS);
- if (ChildText.empty())
+ if (ChildBuffer.empty())
continue;
- if (Idx > 0 && Comment.Kind == CommentKind::CK_ParagraphComment) {
- if (Comment.Children[Idx - 1]->Kind == CommentKind::CK_TextComment &&
- Child->Kind == CommentKind::CK_TextComment) {
- Parts.push_back("<br>");
- }
- }
+ if (Idx > 0 && Comment.Kind == CommentKind::CK_ParagraphComment &&
+ Comment.Children[Idx - 1]->Kind == CommentKind::CK_TextComment &&
+ Child->Kind == CommentKind::CK_TextComment)
+ OS << "<br>";
- Parts.push_back(ChildText);
- }
+ if (FirstChild)
+ FirstChild = false;
+ else if (Comment.Kind == CommentKind::CK_BlockCommandComment ||
+ Comment.Kind == CommentKind::CK_FullComment)
+ OS << "<br><br>";
- if (Comment.Kind == CommentKind::CK_BlockCommandComment ||
- Comment.Kind == CommentKind::CK_FullComment) {
- return llvm::join(Parts, "<br><br>");
+ OS << ChildBuffer;
}
-
- return llvm::join(Parts, "");
}
static void genCommentString(llvm::ArrayRef<CommentInfo> Comments,
llvm::raw_ostream &OS) {
- std::string CommentText = "";
+ uint64_t InitPos = OS.tell();
for (const auto &Child : Comments) {
- CommentText += extractCommentText(Child);
+ extractCommentText(Child, OS);
}
- if (!CommentText.empty())
- OS << CommentText;
- else
+ if (InitPos == OS.tell())
OS << "--";
}
>From 7de7e01db6377b616370a65234f4347f14091f90 Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Sat, 7 Mar 2026 18:28:02 +0530
Subject: [PATCH 10/20] use an efficient logic for formatting comments
A big thanks to @ilovepi for the code and approach.
Also revert to left-padding the table content.
---
clang-tools-extra/clang-doc/MDGenerator.cpp | 104 ++++++++++--------
clang-tools-extra/test/clang-doc/enum.cpp | 16 +--
.../unittests/clang-doc/MDGeneratorTest.cpp | 5 +-
3 files changed, 68 insertions(+), 57 deletions(-)
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index e0b05cd5f5d5b..4a9f159659b25 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -15,7 +15,6 @@
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
-#include <cstdint>
#include <string>
using namespace llvm;
@@ -70,43 +69,60 @@ static void writeSourceFileRef(const ClangDocContext &CDCtx, const Location &L,
OS << "\n\n";
}
-static void extractCommentText(const CommentInfo &Comment,
- llvm::raw_ostream &OS) {
+struct CommentState {
+ bool Started = false;
+ bool NeedsParagraphBreak = false;
- OS << Comment.Text;
- bool FirstChild = true;
-
- for (size_t Idx = 0, End = Comment.Children.size(); Idx < End; ++Idx) {
- const auto &Child = Comment.Children[Idx];
- llvm::SmallString<128> ChildBuffer;
- llvm::raw_svector_ostream ChildOS(ChildBuffer);
- extractCommentText(*Child, ChildOS);
+ void insertSeparator(llvm::raw_ostream &OS) {
+ if (!Started)
+ return;
+ if (NeedsParagraphBreak) {
+ OS << "<br><br>";
+ NeedsParagraphBreak = false;
+ } else {
+ OS << "<br>";
+ }
+ }
+};
- if (ChildBuffer.empty())
- continue;
+static void writeTableSafeComment(const CommentInfo &I, llvm::raw_ostream &OS,
+ CommentState &State) {
+ switch (I.Kind) {
+ case CommentKind::CK_FullComment:
+ for (const auto &Child : I.Children)
+ writeTableSafeComment(*Child, OS, State);
+ break;
- if (Idx > 0 && Comment.Kind == CommentKind::CK_ParagraphComment &&
- Comment.Children[Idx - 1]->Kind == CommentKind::CK_TextComment &&
- Child->Kind == CommentKind::CK_TextComment)
- OS << "<br>";
+ case CommentKind::CK_ParagraphComment:
+ for (const auto &Child : I.Children)
+ writeTableSafeComment(*Child, OS, State);
+ State.NeedsParagraphBreak =
+ true; // Next content after a paragraph needs a break
+ break;
- if (FirstChild)
- FirstChild = false;
- else if (Comment.Kind == CommentKind::CK_BlockCommandComment ||
- Comment.Kind == CommentKind::CK_FullComment)
- OS << "<br><br>";
+ case CommentKind::CK_TextComment:
+ if (!I.Text.empty()) {
+ State.insertSeparator(OS);
+ OS << I.Text;
+ State.Started = true;
+ }
+ break;
- OS << ChildBuffer;
+ // Handle other comment types (BlockCommand, InlineCommand, etc.)
+ default:
+ for (const auto &Child : I.Children)
+ writeTableSafeComment(*Child, OS, State);
+ break;
}
}
-static void genCommentString(llvm::ArrayRef<CommentInfo> Comments,
- llvm::raw_ostream &OS) {
- uint64_t InitPos = OS.tell();
- for (const auto &Child : Comments) {
- extractCommentText(Child, OS);
- }
- if (InitPos == OS.tell())
+static void genMDComment(llvm::ArrayRef<CommentInfo> Comments,
+ llvm::raw_ostream &OS) {
+ CommentState State;
+ for (const auto &C : Comments)
+ writeTableSafeComment(C, OS, State);
+
+ if (!State.Started)
OS << "--";
}
@@ -208,36 +224,34 @@ static void genMarkdown(const ClangDocContext &CDCtx, const EnumInfo &I,
}
OS << "|\n\n";
- std::string Buffer;
- llvm::raw_string_ostream Members(Buffer);
- Members << "| Name | Value |";
+ OS << "| Name | Value |";
if (!I.Members.empty()) {
bool HasComments = false;
for (const auto &Member : I.Members) {
if (!Member.Description.empty()) {
HasComments = true;
- Members << " Comments |";
+ OS << " Comments |";
break;
}
}
- Members << "\n";
- Members << "|:-:|:-:|";
+ OS << "\n";
+ OS << "|---|---|";
if (HasComments)
- Members << ":-:|";
- Members << "\n";
+ OS << "---|";
+ OS << "\n";
for (const auto &N : I.Members) {
- Members << "| " << N.Name << " ";
+ OS << "| " << N.Name << " ";
if (!N.Value.empty())
- Members << "| " << N.Value << " ";
+ OS << "| " << N.Value << " ";
if (HasComments) {
- Members << "| ";
- genCommentString(ArrayRef(N.Description), Members);
- Members << " ";
+ OS << "| ";
+ genMDComment(ArrayRef(N.Description), OS);
+ OS << " ";
}
- Members << "|\n";
+ OS << "|\n";
}
}
- writeLine(Members.str(), OS);
+ OS << "\n";
maybeWriteSourceFileRef(OS, CDCtx, I.DefLoc);
diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp
index 6cb7c3fcdbdc5..5168afc7c74b0 100644
--- a/clang-tools-extra/test/clang-doc/enum.cpp
+++ b/clang-tools-extra/test/clang-doc/enum.cpp
@@ -34,7 +34,7 @@ enum Color {
// MD-INDEX: ## Enums
// MD-INDEX: | enum Color |
// MD-INDEX: | Name | Value | Comments |
-// MD-INDEX: |:-:|:-:|:-:|
+// MD-INDEX: |---|---|---|
// MD-INDEX: | Red | 0 | Comment 1 |
// MD-INDEX: | Green | 1 | Comment 2 |
// MD-INDEX: | Blue | 2 | Comment 3 |
@@ -89,7 +89,7 @@ enum class Shapes {
// MD-INDEX: | enum class Shapes |
// MD-INDEX: | Name | Value | Comments |
-// MD-INDEX: |:-:|:-:|:-:|
+// MD-INDEX: |---|---|---|
// MD-INDEX: | Circle | 0 | Comment 1 |
// MD-INDEX: | Rectangle | 1 | Comment 2 |
// MD-INDEX: | Triangle | 2 | Comment 3 |
@@ -150,7 +150,7 @@ enum Size : uint8_t {
// MD-INDEX: | enum Size : uint8_t |
// MD-INDEX: | Name | Value | Comments |
-// MD-INDEX: |:-:|:-:|:-:|
+// MD-INDEX: |---|---|---|
// MD-INDEX: | Small | 0 | A pearl.<br> Pearls are quite small.<br><br> Pearls are used in jewelry. |
// MD-INDEX: | Medium | 1 | A tennis ball. |
// MD-INDEX: | Large | 2 | A football. |
@@ -199,7 +199,7 @@ enum : long long {
// MD-INDEX: | enum (unnamed) : long long |
// MD-INDEX: | Name | Value | Comments |
-// MD-INDEX: |:-:|:-:|:-:|
+// MD-INDEX: |---|---|---|
// MD-INDEX: | BigVal | 999999999999 | A very large value |
// MD-INDEX: **brief** Very long number
@@ -245,7 +245,7 @@ class FilePermissions {
// MD-PERM: | enum (unnamed) |
// MD-PERM: | Name | Value | Comments |
-// MD-PERM: |:-:|:-:|:-:|
+// MD-PERM: |---|---|---|
// MD-PERM: | Read | 1 | Permission to READ r |
// MD-PERM: | Write | 2 | Permission to WRITE w |
// MD-PERM: | Execute | 4 | Permission to EXECUTE x |
@@ -342,7 +342,7 @@ class Animals {
// MD-ANIMAL: ## Enums
// MD-ANIMAL: | enum AnimalType |
// MD-ANIMAL: | Name | Value | Comments |
-// MD-ANIMAL: |:-:|:-:|:-:|
+// MD-ANIMAL: |---|---|---|
// MD-ANIMAL: | Dog | 0 | Man's best friend |
// MD-ANIMAL: | Cat | 1 | Man's other best friend |
// MD-ANIMAL: | Iguana | 2 | A lizard |
@@ -367,7 +367,7 @@ enum Car {
// MD-VEHICLES: ## Enums
// MD-VEHICLES: | enum Car |
// MD-VEHICLES: | Name | Value | Comments |
-// MD-VEHICLES: |:-:|:-:|:-:|
+// MD-VEHICLES: |---|---|---|
// MD-VEHICLES: | Sedan | 0 | Comment 1 |
// MD-VEHICLES: | SUV | 1 | Comment 2 |
// MD-VEHICLES: | Pickup | 2 | Comment 3 |
@@ -418,7 +418,7 @@ enum ColorUserSpecified {
// MD-INDEX: | enum ColorUserSpecified |
// MD-INDEX: | Name | Value |
-// MD-INDEX: |:-:|:-:|
+// MD-INDEX: |---|---|
// MD-INDEX: | RedUserSpecified | 65 |
// MD-INDEX: | GreenUserSpecified | 2 |
// MD-INDEX: | BlueUserSpecified | 67 |
diff --git a/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp
index d9f32f8eabc41..53d8b8444b3ad 100644
--- a/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp
@@ -72,7 +72,6 @@ TEST_F(MDGeneratorTest, emitNamespaceMD) {
| Name | Value |
-
)raw";
EXPECT_EQ(Expected, Actual.str());
}
@@ -137,7 +136,6 @@ ChildStruct
| Name | Value |
-
)raw";
EXPECT_EQ(Expected, Actual.str());
}
@@ -194,10 +192,9 @@ TEST_F(MDGeneratorTest, emitEnumMD) {
std::string Expected = R"raw(| enum class e |
| Name | Value |
-|:-:|:-:|
+|---|---|
| X | 0 |
-
*Defined at test.cpp#10*
)raw";
>From 6c9152300c3d5188b1646663a589f52551faeacb Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Sat, 7 Mar 2026 18:33:35 +0530
Subject: [PATCH 11/20] remove unused header SmallString.h
---
clang-tools-extra/clang-doc/MDGenerator.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index 4a9f159659b25..18e9895ea590a 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -9,7 +9,6 @@
#include "Generators.h"
#include "Representation.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
>From 302c185f62867c22036ea2c7baeaf638fc6cbd06 Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Tue, 10 Mar 2026 02:05:44 +0530
Subject: [PATCH 12/20] implement suggested changes
---
clang-tools-extra/clang-doc/MDGenerator.cpp | 99 ++++++++++++---------
1 file changed, 58 insertions(+), 41 deletions(-)
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index 18e9895ea590a..e5e5e1cf6fe68 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -68,11 +68,27 @@ static void writeSourceFileRef(const ClangDocContext &CDCtx, const Location &L,
OS << "\n\n";
}
-struct CommentState {
+/// Writer for writing comments to a table cell in MD.
+///
+/// The writer traverses the comments recursively and outputs the
+/// comments into a stream.
+/// The formatter inserts single/double line breaks to retain the comment
+/// structure.
+///
+/// Usage :
+/// Initialize an object with a llvm::raw_ostream to output into.
+/// Call the write(C) function with an array of Comments 'C'.
+class MDCommentWriter {
+private:
+ llvm::raw_ostream &OS;
bool Started = false;
bool NeedsParagraphBreak = false;
- void insertSeparator(llvm::raw_ostream &OS) {
+ /// This function inserts breaks into the stream.
+ ///
+ /// We add a double break in between paragraphs.
+ /// Inside a paragraph, a single break between lines is maintained.
+ void insertSeparator() {
if (!Started)
return;
if (NeedsParagraphBreak) {
@@ -82,48 +98,49 @@ struct CommentState {
OS << "<br>";
}
}
-};
-
-static void writeTableSafeComment(const CommentInfo &I, llvm::raw_ostream &OS,
- CommentState &State) {
- switch (I.Kind) {
- case CommentKind::CK_FullComment:
- for (const auto &Child : I.Children)
- writeTableSafeComment(*Child, OS, State);
- break;
- case CommentKind::CK_ParagraphComment:
- for (const auto &Child : I.Children)
- writeTableSafeComment(*Child, OS, State);
- State.NeedsParagraphBreak =
- true; // Next content after a paragraph needs a break
- break;
+ /// This function processes every comment and its children recursively.
+ void writeTableSafeComment(const CommentInfo &I) {
+ switch (I.Kind) {
+ case CommentKind::CK_FullComment:
+ for (const auto &Child : I.Children)
+ writeTableSafeComment(*Child);
+ break;
+
+ case CommentKind::CK_ParagraphComment:
+ for (const auto &Child : I.Children)
+ writeTableSafeComment(*Child);
+ // Next content after a paragraph needs a break
+ NeedsParagraphBreak = true;
+ break;
+
+ case CommentKind::CK_TextComment:
+ if (!I.Text.empty()) {
+ insertSeparator();
+ OS << I.Text;
+ Started = true;
+ }
+ break;
- case CommentKind::CK_TextComment:
- if (!I.Text.empty()) {
- State.insertSeparator(OS);
- OS << I.Text;
- State.Started = true;
+ // Handle other comment types (BlockCommand, InlineCommand, etc.)
+ default:
+ for (const auto &Child : I.Children)
+ writeTableSafeComment(*Child);
+ break;
}
- break;
-
- // Handle other comment types (BlockCommand, InlineCommand, etc.)
- default:
- for (const auto &Child : I.Children)
- writeTableSafeComment(*Child, OS, State);
- break;
}
-}
-static void genMDComment(llvm::ArrayRef<CommentInfo> Comments,
- llvm::raw_ostream &OS) {
- CommentState State;
- for (const auto &C : Comments)
- writeTableSafeComment(C, OS, State);
+public:
+ explicit MDCommentWriter(llvm::raw_ostream &OS) : OS(OS) {}
- if (!State.Started)
- OS << "--";
-}
+ void write(llvm::ArrayRef<CommentInfo> Comments) {
+ for (const auto &C : Comments)
+ writeTableSafeComment(C);
+
+ if (!Started)
+ OS << "--";
+ }
+};
static void maybeWriteSourceFileRef(llvm::raw_ostream &OS,
const ClangDocContext &CDCtx,
@@ -233,8 +250,7 @@ static void genMarkdown(const ClangDocContext &CDCtx, const EnumInfo &I,
break;
}
}
- OS << "\n";
- OS << "|---|---|";
+ OS << "\n|---|---|";
if (HasComments)
OS << "---|";
OS << "\n";
@@ -244,7 +260,8 @@ static void genMarkdown(const ClangDocContext &CDCtx, const EnumInfo &I,
OS << "| " << N.Value << " ";
if (HasComments) {
OS << "| ";
- genMDComment(ArrayRef(N.Description), OS);
+ MDCommentWriter CommentWriter(OS);
+ CommentWriter.write(N.Description);
OS << " ";
}
OS << "|\n";
>From 96b7bcfef8ac1ab74e5ed457374e775a0f16da76 Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Tue, 10 Mar 2026 04:05:13 +0530
Subject: [PATCH 13/20] rename the class and reorder the functions
---
clang-tools-extra/clang-doc/MDGenerator.cpp | 32 ++++++++++-----------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index e5e5e1cf6fe68..de1703d7b6fa1 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -78,12 +78,19 @@ static void writeSourceFileRef(const ClangDocContext &CDCtx, const Location &L,
/// Usage :
/// Initialize an object with a llvm::raw_ostream to output into.
/// Call the write(C) function with an array of Comments 'C'.
-class MDCommentWriter {
-private:
- llvm::raw_ostream &OS;
- bool Started = false;
- bool NeedsParagraphBreak = false;
+class TableCommentWriter {
+public:
+ explicit TableCommentWriter(llvm::raw_ostream &OS) : OS(OS) {}
+
+ void write(llvm::ArrayRef<CommentInfo> Comments) {
+ for (const auto &C : Comments)
+ writeTableSafeComment(C);
+
+ if (!Started)
+ OS << "--";
+ }
+private:
/// This function inserts breaks into the stream.
///
/// We add a double break in between paragraphs.
@@ -130,16 +137,9 @@ class MDCommentWriter {
}
}
-public:
- explicit MDCommentWriter(llvm::raw_ostream &OS) : OS(OS) {}
-
- void write(llvm::ArrayRef<CommentInfo> Comments) {
- for (const auto &C : Comments)
- writeTableSafeComment(C);
-
- if (!Started)
- OS << "--";
- }
+ llvm::raw_ostream &OS;
+ bool Started = false;
+ bool NeedsParagraphBreak = false;
};
static void maybeWriteSourceFileRef(llvm::raw_ostream &OS,
@@ -260,7 +260,7 @@ static void genMarkdown(const ClangDocContext &CDCtx, const EnumInfo &I,
OS << "| " << N.Value << " ";
if (HasComments) {
OS << "| ";
- MDCommentWriter CommentWriter(OS);
+ TableCommentWriter CommentWriter(OS);
CommentWriter.write(N.Description);
OS << " ";
}
>From 45a875c044605e6b4565327764676ff5315cd0ea Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Tue, 10 Mar 2026 04:22:44 +0530
Subject: [PATCH 14/20] fix tests
---
clang-tools-extra/test/clang-doc/enum.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp
index 5168afc7c74b0..7e71aaa67d8de 100644
--- a/clang-tools-extra/test/clang-doc/enum.cpp
+++ b/clang-tools-extra/test/clang-doc/enum.cpp
@@ -69,7 +69,7 @@ enum Color {
// HTML-INDEX-NEXT: <p> For specifying RGB colors</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-46]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-47]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
/**
@@ -124,7 +124,7 @@ enum class Shapes {
// HTML-INDEX-NEXT: <p> Shape Types</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-49]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-50]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
typedef unsigned char uint8_t;
>From 88a055dee09babe21f88874a6373c506846d194b Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Tue, 10 Mar 2026 04:41:31 +0530
Subject: [PATCH 15/20] fix tests
---
clang-tools-extra/test/clang-doc/enum.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp
index 7e71aaa67d8de..db9144b239df2 100644
--- a/clang-tools-extra/test/clang-doc/enum.cpp
+++ b/clang-tools-extra/test/clang-doc/enum.cpp
@@ -407,7 +407,7 @@ enum Car {
// HTML-VEHICLES-NEXT: <p> specify type of car</p>
// HTML-VEHICLES-NEXT: </div>
// HTML-VEHICLES-NEXT: </div>
-// HTML-VEHICLES-NEXT: <p>Defined at line [[@LINE-55]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-VEHICLES-NEXT: <p>Defined at line [[@LINE-56]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-VEHICLES-NEXT: </div>
enum ColorUserSpecified {
>From 59f1cddb53c4f8e38acd00939b882d2efdc5edbe Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Wed, 11 Mar 2026 21:05:28 +0530
Subject: [PATCH 16/20] [Clang-doc] Display enum comments in HTML (#183085)
Currently comments of enum variables are not displayed in HTML.
Add support to display the comments.
---
clang-tools-extra/clang-doc/JSONGenerator.cpp | 66 +++---
.../clang-doc/assets/clang-doc-mustache.css | 10 +-
.../clang-doc/assets/enum-template.mustache | 22 ++
clang-tools-extra/test/clang-doc/enum.cpp | 122 ++++++++++-
.../test/clang-doc/json/enum.cpp | 201 ++++++++++++++++++
5 files changed, 386 insertions(+), 35 deletions(-)
create mode 100644 clang-tools-extra/test/clang-doc/json/enum.cpp
diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp
index 9a8f51b808cab..7c0485692fad2 100644
--- a/clang-tools-extra/clang-doc/JSONGenerator.cpp
+++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp
@@ -1,5 +1,6 @@
#include "Generators.h"
#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/JSON.h"
using namespace llvm;
@@ -353,10 +354,34 @@ static void generateContext(const Info &I, Object &Obj) {
Obj["HasContexts"] = true;
}
-static void
-serializeCommonAttributes(const Info &I, json::Object &Obj,
- const std::optional<StringRef> RepositoryUrl,
- const std::optional<StringRef> RepositoryLinePrefix) {
+static void serializeDescription(llvm::ArrayRef<CommentInfo> Description,
+ json::Object &Obj, StringRef Key = "") {
+ if (Description.empty())
+ return;
+
+ // Skip straight to the FullComment's children
+ auto &Comments = Description.front().Children;
+ Object DescriptionObj = Object();
+ for (const auto &CommentInfo : Comments) {
+ 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();
+ ParagraphComment->get("ParagraphComment")) {
+ auto TextCommentsArray = extractTextComments(ParagraphComment);
+ if (TextCommentsArray.kind() == json::Value::Null ||
+ TextCommentsArray.getAsArray()->empty())
+ continue;
+ insertComment(DescriptionObj, TextCommentsArray, "ParagraphComments");
+ }
+ }
+ Obj["Description"] = std::move(DescriptionObj);
+ if (!Key.empty())
+ Obj[Key] = true;
+}
+
+void JSONGenerator::serializeCommonAttributes(const Info &I,
+ json::Object &Obj) {
insertNonEmpty("Name", I.Name, Obj);
Obj["USR"] = toHex(toStringRef(I.USR));
Obj["InfoType"] = infoTypeToString(I.IT);
@@ -372,25 +397,7 @@ serializeCommonAttributes(const Info &I, json::Object &Obj,
Obj["Namespace"].getAsArray()->push_back(NS.Name);
}
- if (!I.Description.empty()) {
- Object Description = Object();
- // Skip straight to the FullComment's children
- auto &Comments = I.Description.at(0).Children;
- for (const auto &CommentInfo : Comments) {
- json::Value Comment = serializeComment(*CommentInfo, Description);
- // if a ParagraphComment is returned, then it is a top-level comment that
- // needs to be inserted manually.
- if (auto *ParagraphComment = Comment.getAsObject();
- ParagraphComment->get("ParagraphComment")) {
- auto TextCommentsArray = extractTextComments(ParagraphComment);
- if (TextCommentsArray.kind() == json::Value::Null ||
- TextCommentsArray.getAsArray()->empty())
- continue;
- insertComment(Description, TextCommentsArray, "ParagraphComments");
- }
- }
- Obj["Description"] = std::move(Description);
- }
+ serializeDescription(I.Description, Obj);
// Namespaces aren't SymbolInfos, so they dont have a DefLoc
if (I.IT != InfoType::IT_namespace) {
@@ -565,6 +572,8 @@ static void serializeInfo(const EnumValueInfo &I, Object &Obj) {
Obj["ValueExpr"] = I.ValueExpr;
else
Obj["Value"] = I.Value;
+
+ serializeDescription(I.Description, Obj, "HasEnumMemberComments");
}
static void serializeInfo(const EnumInfo &I, json::Object &Obj,
@@ -582,8 +591,15 @@ static void serializeInfo(const EnumInfo &I, json::Object &Obj,
Obj["BaseType"] = BaseTypeVal;
}
- if (!I.Members.empty())
- serializeArray(I.Members, Obj, "Members", SerializeInfoLambda);
+ if (!I.Members.empty()) {
+ for (const auto &Member : I.Members) {
+ if (!Member.Description.empty()) {
+ Obj["HasComments"] = true;
+ break;
+ }
+ }
+ serializeArray(I.Members, Obj, "Members", serializeInfoLambda());
+ }
}
static void
diff --git a/clang-tools-extra/clang-doc/assets/clang-doc-mustache.css b/clang-tools-extra/clang-doc/assets/clang-doc-mustache.css
index 3727981efddc5..fcdf2df013f59 100644
--- a/clang-tools-extra/clang-doc/assets/clang-doc-mustache.css
+++ b/clang-tools-extra/clang-doc/assets/clang-doc-mustache.css
@@ -528,4 +528,12 @@ a, a:visited, a:hover, a:active {
.param-container {
display: block;
-}
\ No newline at end of file
+}
+
+.paragraph-container {
+ margin-bottom: 1rem;
+}
+
+.paragraph-container:last-of-type {
+ margin-bottom: 0rem;
+}
diff --git a/clang-tools-extra/clang-doc/assets/enum-template.mustache b/clang-tools-extra/clang-doc/assets/enum-template.mustache
index d88f88cc30cee..60429dc6df9d3 100644
--- a/clang-tools-extra/clang-doc/assets/enum-template.mustache
+++ b/clang-tools-extra/clang-doc/assets/enum-template.mustache
@@ -15,6 +15,9 @@
<tr>
<th>Name</th>
<th>Value</th>
+ {{#HasComments}}
+ <th>Comments</th>
+ {{/HasComments}}
</tr>
{{#Members}}
<tr>
@@ -26,6 +29,25 @@
{{^Value}}
<td>{{ValueExpr}}</td>
{{/Value}}
+ {{#HasComments}}
+ <td>{{#HasEnumMemberComments}}
+ {{#Description}}
+ {{#BriefComments}}
+ {{#.}}
+ <p class="paragraph-container">{{TextComment}}</p>
+ {{/.}}
+ {{/BriefComments}}
+ {{#ParagraphComments}}
+ <p class="paragraph-container">
+ {{#.}}
+ {{TextComment}}<br>
+ {{/.}}
+ </p>
+ {{/ParagraphComments}}
+ {{/Description}}
+ {{/HasEnumMemberComments}}
+ {{^HasEnumMemberComments}} -- {{/HasEnumMemberComments}}</td>
+ {{/HasComments}}
</tr>
{{/Members}}
</tbody>
diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp
index db9144b239df2..1355a5a6fbff3 100644
--- a/clang-tools-extra/test/clang-doc/enum.cpp
+++ b/clang-tools-extra/test/clang-doc/enum.cpp
@@ -18,7 +18,6 @@
// RUN: FileCheck %s < %t/Vehicles/index.md --check-prefix=MD-VEHICLES-LINE
// RUN: FileCheck %s < %t/Vehicles/index.md --check-prefix=MD-VEHICLES
-// COM: FIXME: Add enum value comments to template
/**
* @brief For specifying RGB colors
@@ -49,18 +48,34 @@ enum Color {
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <th>Name</th>
// HTML-INDEX-NEXT: <th>Value</th>
+// HTML-INDEX-NEXT: <th>Comments</th>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <td>Red</td>
// HTML-INDEX-NEXT: <td>0</td>
+// HTML-INDEX-NEXT: <td>
+// HTML-INDEX-NEXT: <p class="paragraph-container">
+// HTML-INDEX-NEXT: Comment 1<br>
+// HTML-INDEX-NEXT: </p>
+// HTML-INDEX-NEXT: </td>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <td>Green</td>
// HTML-INDEX-NEXT: <td>1</td>
+// HTML-INDEX-NEXT: <td>
+// HTML-INDEX-NEXT: <p class="paragraph-container">
+// HTML-INDEX-NEXT: Comment 2<br>
+// HTML-INDEX-NEXT: </p>
+// HTML-INDEX-NEXT: </td>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <td>Blue</td>
// HTML-INDEX-NEXT: <td>2</td>
+// HTML-INDEX-NEXT: <td>
+// HTML-INDEX-NEXT: <p class="paragraph-container">
+// HTML-INDEX-NEXT: Comment 3<br>
+// HTML-INDEX-NEXT: </p>
+// HTML-INDEX-NEXT: </td>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: </tbody>
// HTML-INDEX-NEXT: </table>
@@ -69,7 +84,7 @@ enum Color {
// HTML-INDEX-NEXT: <p> For specifying RGB colors</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-47]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-62]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
/**
@@ -104,18 +119,34 @@ enum class Shapes {
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <th>Name</th>
// HTML-INDEX-NEXT: <th>Value</th>
+// HTML-INDEX-NEXT: <th>Comments</th>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <td>Circle</td>
// HTML-INDEX-NEXT: <td>0</td>
+// HTML-INDEX-NEXT: <td>
+// HTML-INDEX-NEXT: <p class="paragraph-container">
+// HTML-INDEX-NEXT: Comment 1<br>
+// HTML-INDEX-NEXT: </p>
+// HTML-INDEX-NEXT: </td>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <td>Rectangle</td>
// HTML-INDEX-NEXT: <td>1</td>
+// HTML-INDEX-NEXT: <td>
+// HTML-INDEX-NEXT: <p class="paragraph-container">
+// HTML-INDEX-NEXT: Comment 2<br>
+// HTML-INDEX-NEXT: </p>
+// HTML-INDEX-NEXT: </td>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <td>Triangle</td>
// HTML-INDEX-NEXT: <td>2</td>
+// HTML-INDEX-NEXT: <td>
+// HTML-INDEX-NEXT: <p class="paragraph-container">
+// HTML-INDEX-NEXT: Comment 3<br>
+// HTML-INDEX-NEXT: </p>
+// HTML-INDEX-NEXT: </td>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: </tbody>
// HTML-INDEX-NEXT: </table>
@@ -124,7 +155,7 @@ enum class Shapes {
// HTML-INDEX-NEXT: <p> Shape Types</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-50]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-64]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
typedef unsigned char uint8_t;
@@ -165,18 +196,36 @@ enum Size : uint8_t {
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <th>Name</th>
// HTML-INDEX-NEXT: <th>Value</th>
+// HTML-INDEX-NEXT: <th>Comments</th>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <td>Small</td>
// HTML-INDEX-NEXT: <td>0</td>
+// HTML-INDEX-NEXT: <td>
+// HTML-INDEX-NEXT: <p class="paragraph-container">
+// HTML-INDEX-NEXT: A pearl.<br>
+// HTML-INDEX-NEXT: Pearls are quite small.<br>
+// HTML-INDEX-NEXT: </p>
+// HTML-INDEX-NEXT: <p class="paragraph-container">
+// HTML-INDEX-NEXT: Pearls are used in jewelry.<br>
+// HTML-INDEX-NEXT: </p>
+// HTML-INDEX-NEXT: </td>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <td>Medium</td>
// HTML-INDEX-NEXT: <td>1</td>
+// HTML-INDEX-NEXT: <td>
+// HTML-INDEX-NEXT: <p class="paragraph-container">A tennis ball.</p>
+// HTML-INDEX-NEXT: </td>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <td>Large</td>
// HTML-INDEX-NEXT: <td>2</td>
+// HTML-INDEX-NEXT: <td>
+// HTML-INDEX-NEXT: <p class="paragraph-container">
+// HTML-INDEX-NEXT: A football.<br>
+// HTML-INDEX-NEXT: </p>
+// HTML-INDEX-NEXT: </td>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: </tbody>
// HTML-INDEX-NEXT: </table>
@@ -185,7 +234,7 @@ enum Size : uint8_t {
// HTML-INDEX-NEXT: <p> Specify the size</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-54]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-71]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
/**
@@ -212,10 +261,16 @@ enum : long long {
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <th>Name</th>
// HTML-INDEX-NEXT: <th>Value</th>
+// HTML-INDEX-NEXT: <th>Comments</th>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: <tr>
// HTML-INDEX-NEXT: <td>BigVal</td>
// HTML-INDEX-NEXT: <td>999999999999</td>
+// HTML-INDEX-NEXT: <td>
+// HTML-INDEX-NEXT: <p class="paragraph-container">
+// HTML-INDEX-NEXT: A very large value<br>
+// HTML-INDEX-NEXT: </p>
+// HTML-INDEX-NEXT: </td>
// HTML-INDEX-NEXT: </tr>
// HTML-INDEX-NEXT: </tbody>
// HTML-INDEX-NEXT: </table>
@@ -224,7 +279,7 @@ enum : long long {
// HTML-INDEX-NEXT: <p> Very long number</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-33]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-38]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
class FilePermissions {
@@ -262,18 +317,34 @@ class FilePermissions {
// HTML-PERM-NEXT: <tr>
// HTML-PERM-NEXT: <th>Name</th>
// HTML-PERM-NEXT: <th>Value</th>
+// HTML-PERM-NEXT: <th>Comments</th>
// HTML-PERM-NEXT: </tr>
// HTML-PERM-NEXT: <tr>
// HTML-PERM-NEXT: <td>Read</td>
// HTML-PERM-NEXT: <td>1</td>
+// HTML-PERM-NEXT: <td>
+// HTML-PERM-NEXT: <p class="paragraph-container">
+// HTML-PERM-NEXT: Permission to READ r<br>
+// HTML-PERM-NEXT: </p>
+// HTML-PERM-NEXT: </td>
// HTML-PERM-NEXT: </tr>
// HTML-PERM-NEXT: <tr>
// HTML-PERM-NEXT: <td>Write</td>
// HTML-PERM-NEXT: <td>2</td>
+// HTML-PERM-NEXT: <td>
+// HTML-PERM-NEXT: <p class="paragraph-container">
+// HTML-PERM-NEXT: Permission to WRITE w<br>
+// HTML-PERM-NEXT: </p>
+// HTML-PERM-NEXT: </td>
// HTML-PERM-NEXT: </tr>
// HTML-PERM-NEXT: <tr>
// HTML-PERM-NEXT: <td>Execute</td>
// HTML-PERM-NEXT: <td>4</td>
+// HTML-PERM-NEXT: <td>
+// HTML-PERM-NEXT: <p class="paragraph-container">
+// HTML-PERM-NEXT: Permission to EXECUTE x<br>
+// HTML-PERM-NEXT: </p>
+// HTML-PERM-NEXT: </td>
// HTML-PERM-NEXT: </tr>
// HTML-PERM-NEXT: </tbody>
// HTML-PERM-NEXT: </table>
@@ -282,7 +353,7 @@ class FilePermissions {
// HTML-PERM-NEXT: <p> File permission flags</p>
// HTML-PERM-NEXT: </div>
// HTML-PERM-NEXT: </div>
-// HTML-PERM-NEXT: <p>Defined at line [[@LINE-48]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-PERM-NEXT: <p>Defined at line [[@LINE-63]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-PERM-NEXT: </div>
// HTML-PERM-NEXT: </section>
@@ -314,18 +385,34 @@ class Animals {
// HTML-ANIMAL-NEXT: <tr>
// HTML-ANIMAL-NEXT: <th>Name</th>
// HTML-ANIMAL-NEXT: <th>Value</th>
+// HTML-ANIMAL-NEXT: <th>Comments</th>
// HTML-ANIMAL-NEXT: </tr>
// HTML-ANIMAL-NEXT: <tr>
// HTML-ANIMAL-NEXT: <td>Dog</td>
// HTML-ANIMAL-NEXT: <td>0</td>
+// HTML-ANIMAL-NEXT: <td>
+// HTML-ANIMAL-NEXT: <p class="paragraph-container">
+// HTML-ANIMAL-NEXT: Man's best friend<br>
+// HTML-ANIMAL-NEXT: </p>
+// HTML-ANIMAL-NEXT: </td>
// HTML-ANIMAL-NEXT: </tr>
// HTML-ANIMAL-NEXT: <tr>
// HTML-ANIMAL-NEXT: <td>Cat</td>
// HTML-ANIMAL-NEXT: <td>1</td>
+// HTML-ANIMAL-NEXT: <td>
+// HTML-ANIMAL-NEXT: <p class="paragraph-container">
+// HTML-ANIMAL-NEXT: Man's other best friend<br>
+// HTML-ANIMAL-NEXT: </p>
+// HTML-ANIMAL-NEXT: </td>
// HTML-ANIMAL-NEXT: </tr>
// HTML-ANIMAL-NEXT: <tr>
// HTML-ANIMAL-NEXT: <td>Iguana</td>
// HTML-ANIMAL-NEXT: <td>2</td>
+// HTML-ANIMAL-NEXT: <td>
+// HTML-ANIMAL-NEXT: <p class="paragraph-container">
+// HTML-ANIMAL-NEXT: A lizard<br>
+// HTML-ANIMAL-NEXT: </p>
+// HTML-ANIMAL-NEXT: </td>
// HTML-ANIMAL-NEXT: </tr>
// HTML-ANIMAL-NEXT: </tbody>
// HTML-ANIMAL-NEXT: </table>
@@ -334,7 +421,7 @@ class Animals {
// HTML-ANIMAL-NEXT: <p> specify what animal the class is</p>
// HTML-ANIMAL-NEXT: </div>
// HTML-ANIMAL-NEXT: </div>
-// HTML-ANIMAL-NEXT: <p>Defined at line [[@LINE-40]] of file {{.*}}enum.cpp</p>
+// HTML-ANIMAL-NEXT: <p>Defined at line [[@LINE-57]] of file {{.*}}enum.cpp</p>
// HTML-ANIMAL-NEXT: </div>
// HTML-ANIMAL-NEXT: </section>
@@ -358,7 +445,7 @@ enum Car {
Sedan, ///< Comment 1
SUV, ///< Comment 2
- Pickup, ///< Comment 3
+ Pickup,
Hatchback ///< Comment 4
};
} // namespace Vehicles
@@ -383,22 +470,39 @@ enum Car {
// HTML-VEHICLES-NEXT: <tr>
// HTML-VEHICLES-NEXT: <th>Name</th>
// HTML-VEHICLES-NEXT: <th>Value</th>
+// HTML-VEHICLES-NEXT: <th>Comments</th>
// HTML-VEHICLES-NEXT: </tr>
// HTML-VEHICLES-NEXT: <tr>
// HTML-VEHICLES-NEXT: <td>Sedan</td>
// HTML-VEHICLES-NEXT: <td>0</td>
+// HTML-VEHICLES-NEXT: <td>
+// HTML-VEHICLES-NEXT: <p class="paragraph-container">
+// HTML-VEHICLES-NEXT: Comment 1<br>
+// HTML-VEHICLES-NEXT: </p>
+// HTML-VEHICLES-NEXT: </td>
// HTML-VEHICLES-NEXT: </tr>
// HTML-VEHICLES-NEXT: <tr>
// HTML-VEHICLES-NEXT: <td>SUV</td>
// HTML-VEHICLES-NEXT: <td>1</td>
+// HTML-VEHICLES-NEXT: <td>
+// HTML-VEHICLES-NEXT: <p class="paragraph-container">
+// HTML-VEHICLES-NEXT: Comment 2<br>
+// HTML-VEHICLES-NEXT: </p>
+// HTML-VEHICLES-NEXT: </td>
// HTML-VEHICLES-NEXT: </tr>
// HTML-VEHICLES-NEXT: <tr>
// HTML-VEHICLES-NEXT: <td>Pickup</td>
// HTML-VEHICLES-NEXT: <td>2</td>
+// HTML-VEHICLES-NEXT: <td> -- </td>
// HTML-VEHICLES-NEXT: </tr>
// HTML-VEHICLES-NEXT: <tr>
// HTML-VEHICLES-NEXT: <td>Hatchback</td>
// HTML-VEHICLES-NEXT: <td>3</td>
+// HTML-VEHICLES-NEXT: <td>
+// HTML-VEHICLES-NEXT: <p class="paragraph-container">
+// HTML-VEHICLES-NEXT: Comment 4<br>
+// HTML-VEHICLES-NEXT: </p>
+// HTML-VEHICLES-NEXT: </td>
// HTML-VEHICLES-NEXT: </tr>
// HTML-VEHICLES-NEXT: </tbody>
// HTML-VEHICLES-NEXT: </table>
@@ -407,7 +511,7 @@ enum Car {
// HTML-VEHICLES-NEXT: <p> specify type of car</p>
// HTML-VEHICLES-NEXT: </div>
// HTML-VEHICLES-NEXT: </div>
-// HTML-VEHICLES-NEXT: <p>Defined at line [[@LINE-56]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-VEHICLES-NEXT: <p>Defined at line [[@LINE-72]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-VEHICLES-NEXT: </div>
enum ColorUserSpecified {
diff --git a/clang-tools-extra/test/clang-doc/json/enum.cpp b/clang-tools-extra/test/clang-doc/json/enum.cpp
new file mode 100644
index 0000000000000..442de78a03d77
--- /dev/null
+++ b/clang-tools-extra/test/clang-doc/json/enum.cpp
@@ -0,0 +1,201 @@
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: clang-doc --output=%t --format=json --executor=standalone %s
+// RUN: FileCheck %s < %t/json/GlobalNamespace/index.json --check-prefix=JSON-INDEX
+// RUN: FileCheck %s < %t/json/Vehicles/index.json --check-prefix=JSON-VEHICLES-INDEX
+
+typedef unsigned char uint8_t;
+/**
+ * @brief Specify the size
+ */
+enum Size : uint8_t {
+ /// A pearl.
+ /// Pearls are quite small.
+ ///
+ /// Pearls are used in jewelry.
+ Small,
+
+ /// @brief A tennis ball.
+ Medium,
+
+ /// A football.
+ Large
+};
+
+// JSON-INDEX-LABEL: {
+// JSON-INDEX-NEXT: "DocumentationFileName": "index",
+// JSON-INDEX-NEXT: "Enums": [
+// JSON-INDEX-NEXT: {
+// JSON-INDEX-NEXT: "BaseType": {
+// JSON-INDEX-NEXT: "Name": "uint8_t",
+// JSON-INDEX-NEXT: "QualName": "uint8_t",
+// JSON-INDEX-NEXT: "USR": "0000000000000000000000000000000000000000"
+// JSON-INDEX-NEXT: },
+// JSON-INDEX-NEXT: "Description": {
+// JSON-INDEX-NEXT: "BriefComments": [
+// JSON-INDEX-NEXT: [
+// JSON-INDEX-NEXT: {
+// JSON-INDEX-NEXT: "TextComment": "Specify the size"
+// JSON-INDEX-NEXT: }
+// JSON-INDEX-NEXT: ]
+// JSON-INDEX-NEXT: ],
+// JSON-INDEX-NEXT: "HasBriefComments": true
+// JSON-INDEX-NEXT: },
+// JSON-INDEX-NEXT: "End": true,
+// JSON-INDEX-NEXT: "HasComments": true,
+// JSON-INDEX-NEXT: "InfoType": "enum",
+// JSON-INDEX-NEXT: "Location": {
+// JSON-INDEX-NEXT: "Filename": "{{.*}}enum.cpp",
+// JSON-INDEX-NEXT: "LineNumber": [[@LINE-38]]
+// JSON-INDEX-NEXT: },
+// JSON-INDEX-NEXT: "Members": [
+// JSON-INDEX-NEXT: {
+// JSON-INDEX-NEXT: "Description": {
+// JSON-INDEX-NEXT: "HasParagraphComments": true,
+// JSON-INDEX-NEXT: "ParagraphComments": [
+// JSON-INDEX-NEXT: [
+// JSON-INDEX-NEXT: {
+// JSON-INDEX-NEXT: "TextComment": "A pearl."
+// JSON-INDEX-NEXT: },
+// JSON-INDEX-NEXT: {
+// JSON-INDEX-NEXT: "TextComment": "Pearls are quite small."
+// JSON-INDEX-NEXT: }
+// JSON-INDEX-NEXT: ],
+// JSON-INDEX-NEXT: [
+// JSON-INDEX-NEXT: {
+// JSON-INDEX-NEXT: "TextComment": "Pearls are used in jewelry."
+// JSON-INDEX-NEXT: }
+// JSON-INDEX-NEXT: ]
+// JSON-INDEX-NEXT: ]
+// JSON-INDEX-NEXT: },
+// JSON-INDEX-NEXT: "HasEnumMemberComments": true,
+// JSON-INDEX-NEXT: "Name": "Small",
+// JSON-INDEX-NEXT: "Value": "0"
+// JSON-INDEX-NEXT: },
+// JSON-INDEX-NEXT: {
+// JSON-INDEX-NEXT: "Description": {
+// JSON-INDEX-NEXT: "BriefComments": [
+// JSON-INDEX-NEXT: [
+// JSON-INDEX-NEXT: {
+// JSON-INDEX-NEXT: "TextComment": "A tennis ball."
+// JSON-INDEX-NEXT: }
+// JSON-INDEX-NEXT: ]
+// JSON-INDEX-NEXT: ],
+// JSON-INDEX-NEXT: "HasBriefComments": true
+// JSON-INDEX-NEXT: },
+// JSON-INDEX-NEXT: "HasEnumMemberComments": true,
+// JSON-INDEX-NEXT: "Name": "Medium",
+// JSON-INDEX-NEXT: "Value": "1"
+// JSON-INDEX-NEXT: },
+// JSON-INDEX-NEXT: {
+// JSON-INDEX-NEXT: "Description": {
+// JSON-INDEX-NEXT: "HasParagraphComments": true,
+// JSON-INDEX-NEXT: "ParagraphComments": [
+// JSON-INDEX-NEXT: [
+// JSON-INDEX-NEXT: {
+// JSON-INDEX-NEXT: "TextComment": "A football."
+// JSON-INDEX-NEXT: }
+// JSON-INDEX-NEXT: ]
+// JSON-INDEX-NEXT: ]
+// JSON-INDEX-NEXT: },
+// JSON-INDEX-NEXT: "End": true,
+// JSON-INDEX-NEXT: "HasEnumMemberComments": true,
+// JSON-INDEX-NEXT: "Name": "Large",
+// JSON-INDEX-NEXT: "Value": "2"
+// JSON-INDEX-NEXT: }
+// JSON-INDEX-NEXT: ],
+// JSON-INDEX-NEXT: "Name": "Size",
+// JSON-INDEX-NEXT: "Scoped": false,
+// JSON-INDEX-NEXT: "USR": "{{[0-9A-F]*}}"
+// JSON-INDEX-NEXT: }
+
+namespace Vehicles {
+/**
+ * @brief specify type of car
+ */
+enum Car {
+ Sedan, ///< Comment 1
+ SUV, ///< Comment 2
+ Pickup,
+ Hatchback ///< Comment 4
+};
+} // namespace Vehicles
+
+// JSON-VEHICLES-INDEX-LABEL: "DocumentationFileName": "index",
+// JSON-VEHICLES-INDEX-NEXT: "Enums": [
+// JSON-VEHICLES-INDEX-NEXT: {
+// JSON-VEHICLES-INDEX-NEXT: "Description": {
+// JSON-VEHICLES-INDEX-NEXT: "BriefComments": [
+// JSON-VEHICLES-INDEX-NEXT: [
+// JSON-VEHICLES-INDEX-NEXT: {
+// JSON-VEHICLES-INDEX-NEXT: "TextComment": "specify type of car"
+// JSON-VEHICLES-INDEX-NEXT: }
+// JSON-VEHICLES-INDEX-NEXT: ]
+// JSON-VEHICLES-INDEX-NEXT: ],
+// JSON-VEHICLES-INDEX-NEXT: "HasBriefComments": true
+// JSON-VEHICLES-INDEX-NEXT: },
+// JSON-VEHICLES-INDEX-NEXT: "End": true,
+// JSON-VEHICLES-INDEX-NEXT: "HasComments": true,
+// JSON-VEHICLES-INDEX-NEXT: "InfoType": "enum",
+// JSON-VEHICLES-INDEX-NEXT: "Location": {
+// JSON-VEHICLES-INDEX-NEXT: "Filename": "{{.*}}enum.cpp",
+// JSON-VEHICLES-INDEX-NEXT: "LineNumber": [[@LINE-26]]
+// JSON-VEHICLES-INDEX-NEXT: },
+// JSON-VEHICLES-INDEX-NEXT: "Members": [
+// JSON-VEHICLES-INDEX-NEXT: {
+// JSON-VEHICLES-INDEX-NEXT: "Description": {
+// JSON-VEHICLES-INDEX-NEXT: "HasParagraphComments": true,
+// JSON-VEHICLES-INDEX-NEXT: "ParagraphComments": [
+// JSON-VEHICLES-INDEX-NEXT: [
+// JSON-VEHICLES-INDEX-NEXT: {
+// JSON-VEHICLES-INDEX-NEXT: "TextComment": "Comment 1"
+// JSON-VEHICLES-INDEX-NEXT: }
+// JSON-VEHICLES-INDEX-NEXT: ]
+// JSON-VEHICLES-INDEX-NEXT: ]
+// JSON-VEHICLES-INDEX-NEXT: },
+// JSON-VEHICLES-INDEX-NEXT: "HasEnumMemberComments": true,
+// JSON-VEHICLES-INDEX-NEXT: "Name": "Sedan",
+// JSON-VEHICLES-INDEX-NEXT: "Value": "0"
+// JSON-VEHICLES-INDEX-NEXT: },
+// JSON-VEHICLES-INDEX-NEXT: {
+// JSON-VEHICLES-INDEX-NEXT: "Description": {
+// JSON-VEHICLES-INDEX-NEXT: "HasParagraphComments": true,
+// JSON-VEHICLES-INDEX-NEXT: "ParagraphComments": [
+// JSON-VEHICLES-INDEX-NEXT: [
+// JSON-VEHICLES-INDEX-NEXT: {
+// JSON-VEHICLES-INDEX-NEXT: "TextComment": "Comment 2"
+// JSON-VEHICLES-INDEX-NEXT: }
+// JSON-VEHICLES-INDEX-NEXT: ]
+// JSON-VEHICLES-INDEX-NEXT: ]
+// JSON-VEHICLES-INDEX-NEXT: },
+// JSON-VEHICLES-INDEX-NEXT: "HasEnumMemberComments": true,
+// JSON-VEHICLES-INDEX-NEXT: "Name": "SUV",
+// JSON-VEHICLES-INDEX-NEXT: "Value": "1"
+// JSON-VEHICLES-INDEX-NEXT: },
+// JSON-VEHICLES-INDEX-NEXT: {
+// JSON-VEHICLES-INDEX-NEXT: "Name": "Pickup",
+// JSON-VEHICLES-INDEX-NEXT: "Value": "2"
+// JSON-VEHICLES-INDEX-NEXT: },
+// JSON-VEHICLES-INDEX-NEXT: {
+// JSON-VEHICLES-INDEX-NEXT: "Description": {
+// JSON-VEHICLES-INDEX-NEXT: "HasParagraphComments": true,
+// JSON-VEHICLES-INDEX-NEXT: "ParagraphComments": [
+// JSON-VEHICLES-INDEX-NEXT: [
+// JSON-VEHICLES-INDEX-NEXT: {
+// JSON-VEHICLES-INDEX-NEXT: "TextComment": "Comment 4"
+// JSON-VEHICLES-INDEX-NEXT: }
+// JSON-VEHICLES-INDEX-NEXT: ]
+// JSON-VEHICLES-INDEX-NEXT: ]
+// JSON-VEHICLES-INDEX-NEXT: },
+// JSON-VEHICLES-INDEX-NEXT: "End": true,
+// JSON-VEHICLES-INDEX-NEXT: "HasEnumMemberComments": true,
+// JSON-VEHICLES-INDEX-NEXT: "Name": "Hatchback",
+// JSON-VEHICLES-INDEX-NEXT: "Value": "3"
+// JSON-VEHICLES-INDEX-NEXT: }
+// JSON-VEHICLES-INDEX-NEXT: ],
+// JSON-VEHICLES-INDEX-NEXT: "Name": "Car",
+// JSON-VEHICLES-INDEX-NEXT: "Namespace": [
+// JSON-VEHICLES-INDEX-NEXT: "Vehicles"
+// JSON-VEHICLES-INDEX-NEXT: ],
+// JSON-VEHICLES-INDEX-NEXT: "Scoped": false,
+// JSON-VEHICLES-INDEX-NEXT: "USR": "{{[0-9A-F]*}}"
+// JSON-VEHICLES-INDEX-NEXT: }
>From 5de9046865ce92fb14a5ede149f1104bb081cd3e Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Wed, 11 Mar 2026 21:45:17 +0530
Subject: [PATCH 17/20] fix tests
---
clang-tools-extra/test/clang-doc/enum.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp
index 1355a5a6fbff3..854de5ee007e2 100644
--- a/clang-tools-extra/test/clang-doc/enum.cpp
+++ b/clang-tools-extra/test/clang-doc/enum.cpp
@@ -155,7 +155,7 @@ enum class Shapes {
// HTML-INDEX-NEXT: <p> Shape Types</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-64]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-65]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
typedef unsigned char uint8_t;
@@ -234,7 +234,7 @@ enum Size : uint8_t {
// HTML-INDEX-NEXT: <p> Specify the size</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-71]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-72]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
/**
@@ -279,7 +279,7 @@ enum : long long {
// HTML-INDEX-NEXT: <p> Very long number</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-38]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-39]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
class FilePermissions {
@@ -353,7 +353,7 @@ class FilePermissions {
// HTML-PERM-NEXT: <p> File permission flags</p>
// HTML-PERM-NEXT: </div>
// HTML-PERM-NEXT: </div>
-// HTML-PERM-NEXT: <p>Defined at line [[@LINE-63]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-PERM-NEXT: <p>Defined at line [[@LINE-64]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-PERM-NEXT: </div>
// HTML-PERM-NEXT: </section>
@@ -421,7 +421,7 @@ class Animals {
// HTML-ANIMAL-NEXT: <p> specify what animal the class is</p>
// HTML-ANIMAL-NEXT: </div>
// HTML-ANIMAL-NEXT: </div>
-// HTML-ANIMAL-NEXT: <p>Defined at line [[@LINE-57]] of file {{.*}}enum.cpp</p>
+// HTML-ANIMAL-NEXT: <p>Defined at line [[@LINE-56]] of file {{.*}}enum.cpp</p>
// HTML-ANIMAL-NEXT: </div>
// HTML-ANIMAL-NEXT: </section>
>From 67e93cfa87850262361410c30663de974e8ceaf1 Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Wed, 11 Mar 2026 22:00:28 +0530
Subject: [PATCH 18/20] fix tests
---
clang-tools-extra/test/clang-doc/enum.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp
index 854de5ee007e2..3288cd580ba6c 100644
--- a/clang-tools-extra/test/clang-doc/enum.cpp
+++ b/clang-tools-extra/test/clang-doc/enum.cpp
@@ -84,7 +84,7 @@ enum Color {
// HTML-INDEX-NEXT: <p> For specifying RGB colors</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-62]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-63]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
/**
@@ -155,7 +155,7 @@ enum class Shapes {
// HTML-INDEX-NEXT: <p> Shape Types</p>
// HTML-INDEX-NEXT: </div>
// HTML-INDEX-NEXT: </div>
-// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-65]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-INDEX-NEXT: <p>Defined at line [[@LINE-66]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-INDEX-NEXT: </div>
typedef unsigned char uint8_t;
@@ -421,7 +421,7 @@ class Animals {
// HTML-ANIMAL-NEXT: <p> specify what animal the class is</p>
// HTML-ANIMAL-NEXT: </div>
// HTML-ANIMAL-NEXT: </div>
-// HTML-ANIMAL-NEXT: <p>Defined at line [[@LINE-56]] of file {{.*}}enum.cpp</p>
+// HTML-ANIMAL-NEXT: <p>Defined at line [[@LINE-57]] of file {{.*}}enum.cpp</p>
// HTML-ANIMAL-NEXT: </div>
// HTML-ANIMAL-NEXT: </section>
@@ -511,7 +511,7 @@ enum Car {
// HTML-VEHICLES-NEXT: <p> specify type of car</p>
// HTML-VEHICLES-NEXT: </div>
// HTML-VEHICLES-NEXT: </div>
-// HTML-VEHICLES-NEXT: <p>Defined at line [[@LINE-72]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
+// HTML-VEHICLES-NEXT: <p>Defined at line [[@LINE-73]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p>
// HTML-VEHICLES-NEXT: </div>
enum ColorUserSpecified {
>From 50d753c694c93d8403f2c21090f154f05b05542a Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Wed, 11 Mar 2026 22:08:22 +0530
Subject: [PATCH 19/20] fix tests
---
clang-tools-extra/test/clang-doc/enum.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp
index 3288cd580ba6c..11abb870bbb1b 100644
--- a/clang-tools-extra/test/clang-doc/enum.cpp
+++ b/clang-tools-extra/test/clang-doc/enum.cpp
@@ -182,7 +182,7 @@ enum Size : uint8_t {
// MD-INDEX: | enum Size : uint8_t |
// MD-INDEX: | Name | Value | Comments |
// MD-INDEX: |---|---|---|
-// MD-INDEX: | Small | 0 | A pearl.<br> Pearls are quite small.<br><br> Pearls are used in jewelry. |
+// MD-INDEX: | Small | 0 | A pearl.<br>Pearls are quite small.<br><br>Pearls are used in jewelry. |
// MD-INDEX: | Medium | 1 | A tennis ball. |
// MD-INDEX: | Large | 2 | A football. |
// MD-INDEX: **brief** Specify the size
>From 6c34ed8582679e95bebdc5db4fe92f282c5c17ea Mon Sep 17 00:00:00 2001
From: Samrudh Nelli <samrudhnelli at gmail.com>
Date: Wed, 11 Mar 2026 22:14:12 +0530
Subject: [PATCH 20/20] fix tests
---
clang-tools-extra/test/clang-doc/enum.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp
index 11abb870bbb1b..3cbcab86ff77a 100644
--- a/clang-tools-extra/test/clang-doc/enum.cpp
+++ b/clang-tools-extra/test/clang-doc/enum.cpp
@@ -457,7 +457,7 @@ enum Car {
// MD-VEHICLES: |---|---|---|
// MD-VEHICLES: | Sedan | 0 | Comment 1 |
// MD-VEHICLES: | SUV | 1 | Comment 2 |
-// MD-VEHICLES: | Pickup | 2 | Comment 3 |
+// MD-VEHICLES: | Pickup | 2 | -- |
// MD-VEHICLES: | Hatchback | 3 | Comment 4 |
// MD-VEHICLES: **brief** specify type of car
More information about the cfe-commits
mailing list