https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/173956
>From 7048bbc6b78a063bce8e5b660dbf4df311c61c1e Mon Sep 17 00:00:00 2001 From: Erick Velez <[email protected]> Date: Tue, 9 Dec 2025 00:00:25 -0800 Subject: [PATCH] [clang-doc] Add concepts to namespace template This patch serializes concepts in HTML. This patch also includes changes to bitcode reading/writing and JSON to serialize the concept's location, which was missing. --- clang-tools-extra/clang-doc/BitcodeReader.cpp | 2 + clang-tools-extra/clang-doc/BitcodeWriter.cpp | 5 +- clang-tools-extra/clang-doc/BitcodeWriter.h | 1 + clang-tools-extra/clang-doc/JSONGenerator.cpp | 6 +- .../assets/comment-template.mustache | 8 ++ .../assets/namespace-template.mustache | 30 +++++++ .../clang-doc/json/compound-constraints.cpp | 88 +++++++++++++++++++ .../test/clang-doc/json/concept.cpp | 5 ++ 8 files changed, 143 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index 817981aa0d4a3..731b6990cb697 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -429,6 +429,8 @@ static llvm::Error parseRecord(const Record &R, unsigned ID, return decodeRecord(R, I->IsType, Blob); case CONCEPT_CONSTRAINT_EXPRESSION: return decodeRecord(R, I->ConstraintExpression, Blob); + case CONCEPT_DEFLOCATION: + return decodeRecord(R, I->DefLoc, Blob); } llvm_unreachable("invalid field for ConceptInfo"); } diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp index 650501d1d7606..b7f60d88d96ff 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp +++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp @@ -223,6 +223,7 @@ static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor> {CONCEPT_IS_TYPE, {"IsType", &genBoolAbbrev}}, {CONCEPT_CONSTRAINT_EXPRESSION, {"ConstraintExpression", &genStringAbbrev}}, + {CONCEPT_DEFLOCATION, {"DefLocation", &genLocationAbbrev}}, {CONSTRAINT_EXPRESSION, {"Expression", &genStringAbbrev}}, {VAR_USR, {"USR", &genSymbolIdAbbrev}}, {VAR_NAME, {"Name", &genStringAbbrev}}, @@ -295,7 +296,7 @@ static const std::vector<std::pair<BlockId, std::vector<RecordId>>> // Concept Block {BI_CONCEPT_BLOCK_ID, {CONCEPT_USR, CONCEPT_NAME, CONCEPT_IS_TYPE, - CONCEPT_CONSTRAINT_EXPRESSION}}, + CONCEPT_CONSTRAINT_EXPRESSION, CONCEPT_DEFLOCATION}}, // Constraint Block {BI_CONSTRAINT_BLOCK_ID, {CONSTRAINT_EXPRESSION}}, {BI_VAR_BLOCK_ID, {VAR_NAME, VAR_USR, VAR_DEFLOCATION, VAR_IS_STATIC}}, @@ -698,6 +699,8 @@ void ClangDocBitcodeWriter::emitBlock(const ConceptInfo &I) { emitRecord(I.IsType, CONCEPT_IS_TYPE); emitRecord(I.ConstraintExpression, CONCEPT_CONSTRAINT_EXPRESSION); emitBlock(I.Template); + if (I.DefLoc) + emitRecord(*I.DefLoc, CONCEPT_DEFLOCATION); } void ClangDocBitcodeWriter::emitBlock(const TemplateInfo &T) { diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.h b/clang-tools-extra/clang-doc/BitcodeWriter.h index 6d1b9e9a7ebf2..89c556fc310cb 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.h +++ b/clang-tools-extra/clang-doc/BitcodeWriter.h @@ -148,6 +148,7 @@ enum RecordId { CONCEPT_NAME, CONCEPT_IS_TYPE, CONCEPT_CONSTRAINT_EXPRESSION, + CONCEPT_DEFLOCATION, CONSTRAINT_EXPRESSION, VAR_USR, VAR_NAME, diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp index 6dec347ed0bd0..2887c5e7bc187 100644 --- a/clang-tools-extra/clang-doc/JSONGenerator.cpp +++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp @@ -213,6 +213,8 @@ static Object serializeComment(const CommentInfo &I, Object &Description) { Child.insert({"Children", TextCommentsArray}); if (I.Kind == CommentKind::CK_ParamCommandComment) insertComment(Description, ChildVal, "ParamComments"); + if (I.Kind == CommentKind::CK_TParamCommandComment) + insertComment(Description, ChildVal, "TParamComments"); return Obj; } @@ -642,8 +644,10 @@ static void serializeInfo(const NamespaceInfo &I, json::Object &Obj, Obj["HasFunctions"] = true; } - if (!I.Children.Concepts.empty()) + if (!I.Children.Concepts.empty()) { serializeArray(I.Children.Concepts, Obj, "Concepts", SerializeInfo); + Obj["HasConcepts"] = true; + } if (!I.Children.Variables.empty()) serializeArray(I.Children.Variables, Obj, "Variables", SerializeInfo); diff --git a/clang-tools-extra/clang-doc/assets/comment-template.mustache b/clang-tools-extra/clang-doc/assets/comment-template.mustache index 1f40333cfd4b2..8d89cffd2c3bf 100644 --- a/clang-tools-extra/clang-doc/assets/comment-template.mustache +++ b/clang-tools-extra/clang-doc/assets/comment-template.mustache @@ -32,6 +32,14 @@ </div> {{/ParamComments}} {{/HasParamComments}} +{{#HasTParamComments}} +<h3>Template Parameters</h3> +{{#TParamComments}} +<div> + <b>{{ParamName}}</b> {{#Explicit}}{{Direction}}{{/Explicit}} {{#Children}}{{TextComment}}{{/Children}} +</div> +{{/#TParamComments}} +{{/HasTParamComments}} {{#HasReturnComments}} <h3>Returns</h3> {{#ReturnComments}} diff --git a/clang-tools-extra/clang-doc/assets/namespace-template.mustache b/clang-tools-extra/clang-doc/assets/namespace-template.mustache index 6a43def0386d5..3588ecf30b3f9 100644 --- a/clang-tools-extra/clang-doc/assets/namespace-template.mustache +++ b/clang-tools-extra/clang-doc/assets/namespace-template.mustache @@ -71,6 +71,20 @@ </ul> </li> {{/HasNamespaces}} + {{#HasConcepts}} + <li class="sidebar-section"> + <a class="sidebar-item" href="#Concepts">Concepts</a> + </li> + <li> + <ul> + {{#Concepts}} + <li class="sidebar-item-container"> + <a class="sidebar-item" href="#{{USR}}">{{Name}}</a> + </li> + {{/Concepts}} + </ul> + </li> + {{/HasConcepts}} </ul> </div> <div class="resizer" id="resizer"></div> @@ -125,6 +139,22 @@ </ul> </section> {{/HasFunctions}} + {{#HasConcepts}} + <section id="Concepts" class="section-container"> + <h2>Concepts</h2> + {{#Concepts}} + <div id="{{ID}}" class="delimiter-container"> + <div> + <pre><code class="language-cpp code-clang-doc">{{#Template}}template <{{#Parameters}}{{Param}}{{^End}}, {{/End}}{{/Parameters}}>{{/Template}} {{Name}} {{ConstraintExpression}}</code></pre> + </div> + {{#Description}} + {{>Comments}} + {{/Description}} + <p>Defined at line {{Location.LineNumber}} of file {{Location.Filename}}</p> + </div> + {{/Concepts}} + </section> + {{/HasConcepts}} </div> </div> </main> diff --git a/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp b/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp index afaad8f5d6775..3031740464d63 100644 --- a/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp +++ b/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp @@ -1,19 +1,33 @@ // RUN: rm -rf %t && mkdir -p %t // RUN: clang-doc --extra-arg -std=c++20 --output=%t --format=json --executor=standalone %s +// RUN: clang-doc --extra-arg -std=c++20 --output=%t --doxygen --format=html --executor=standalone %s // RUN: FileCheck %s < %t/json/GlobalNamespace/index.json +// RUN: FileCheck %s < %t/html/GlobalNamespace/index.html -check-prefix=CHECK-HTML +/// \brief Concept for an incrementable value +/// +/// \tparam T A value that can be incremented. template<typename T> concept Incrementable = requires (T a) { a++; }; +/// \brief Concept for a decrementable value +/// +/// \tparam T A value that can be decremented template<typename T> concept Decrementable = requires (T a) { a--; }; +/// \brief Concept for a pre-incrementable value +/// +/// \tparam T A value that can be pre-incremented template<typename T> concept PreIncrementable = requires (T a) { ++a; }; +/// \brief Concept for a -pre-decrementable value +/// +/// \tparam T A value that can be pre-decremented template<typename T> concept PreDecrementable = requires (T a) { --a; }; @@ -112,3 +126,77 @@ template<typename T> requires (Incrementable<T> && Decrementable<T>) || PreIncre // CHECK-NEXT: "USR": "{{[0-9A-F]*}}" // CHECK-NEXT: } // CHECK-NEXT: ], + +// CHECK-HTML: <a class="sidebar-item" href="#Concepts">Concepts</a> +// CHECK-HTML-NEXT: </li> +// CHECK-HTML-NEXT: <li> +// CHECK-HTML-NEXT: <ul> +// CHECK-HTML-NEXT: <li class="sidebar-item-container"> +// CHECK-HTML-NEXT: <a class="sidebar-item" href="#{{([0-9A-F]{40})}}">Incrementable</a> +// CHECK-HTML-NEXT: </li> +// CHECK-HTML-NEXT: <li class="sidebar-item-container"> +// CHECK-HTML-NEXT: <a class="sidebar-item" href="#{{([0-9A-F]{40})}}">Decrementable</a> +// CHECK-HTML-NEXT: </li> +// CHECK-HTML-NEXT: <li class="sidebar-item-container"> +// CHECK-HTML-NEXT: <a class="sidebar-item" href="#{{([0-9A-F]{40})}}">PreIncrementable</a> +// CHECK-HTML-NEXT: </li> +// CHECK-HTML-NEXT: <li class="sidebar-item-container"> +// CHECK-HTML-NEXT: <a class="sidebar-item" href="#{{([0-9A-F]{40})}}">PreDecrementable</a> +// CHECK-HTML-NEXT: </li> +// CHECK-HTML-NEXT: </ul> +// CHECK-HTML-NEXT: </li> +// CHECK-HTML: <section id="Concepts" class="section-container"> +// CHECK-HTML-NEXT: <h2>Concepts</h2> +// CHECK-HTML-NEXT: <div id="" class="delimiter-container"> +// CHECK-HTML-NEXT: <div> +// CHECK-HTML-NEXT: <pre><code class="language-cpp code-clang-doc">template <typename T> Incrementable requires (T a) { a++; }</code></pre> +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <div> +// CHECK-HTML-NEXT: <p> Concept for an incrementable value</p> +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <h3>Template Parameters</h3> +// CHECK-HTML-NEXT: <div> +// CHECK-HTML-NEXT: <b>T</b> A value that can be incremented. +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <p>Defined at line [[@LINE-151]] of file {{.*}}compound-constraints.cpp</p> +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <div id="" class="delimiter-container"> +// CHECK-HTML-NEXT: <div> +// CHECK-HTML-NEXT: <pre><code class="language-cpp code-clang-doc">template <typename T> Decrementable requires (T a) { a--; }</code></pre> +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <div> +// CHECK-HTML-NEXT: <p> Concept for a decrementable value</p> +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <h3>Template Parameters</h3> +// CHECK-HTML-NEXT: <div> +// CHECK-HTML-NEXT: <b>T</b> A value that can be decremented +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <p>Defined at line [[@LINE-157]] of file {{.*}}compound-constraints.cpp</p> +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <div id="" class="delimiter-container"> +// CHECK-HTML-NEXT: <div> +// CHECK-HTML-NEXT: <pre><code class="language-cpp code-clang-doc">template <typename T> PreIncrementable requires (T a) { ++a; }</code></pre> +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <div> +// CHECK-HTML-NEXT: <p> Concept for a pre-incrementable value</p> +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <h3>Template Parameters</h3> +// CHECK-HTML-NEXT: <div> +// CHECK-HTML-NEXT: <b>T</b> A value that can be pre-incremented +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <p>Defined at line [[@LINE-163]] of file {{.*}}compound-constraints.cpp</p> +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <div id="" class="delimiter-container"> +// CHECK-HTML-NEXT: <div> +// CHECK-HTML-NEXT: <pre><code class="language-cpp code-clang-doc">template <typename T> PreDecrementable requires (T a) { --a; }</code></pre> +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <div> +// CHECK-HTML-NEXT: <p> Concept for a -pre-decrementable value</p> +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <h3>Template Parameters</h3> +// CHECK-HTML-NEXT: <div> +// CHECK-HTML-NEXT: <b>T</b> A value that can be pre-decremented +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: <p>Defined at line [[@LINE-169]] of file {{.*}}compound-constraints.cpp</p> +// CHECK-HTML-NEXT: </div> +// CHECK-HTML-NEXT: </section> diff --git a/clang-tools-extra/test/clang-doc/json/concept.cpp b/clang-tools-extra/test/clang-doc/json/concept.cpp index fc440d095fc4c..976faee83fffc 100644 --- a/clang-tools-extra/test/clang-doc/json/concept.cpp +++ b/clang-tools-extra/test/clang-doc/json/concept.cpp @@ -1,5 +1,6 @@ // RUN: rm -rf %t && mkdir -p %t // RUN: clang-doc --extra-arg -std=c++20 --output=%t --format=json --executor=standalone %s +// RUN: clang-doc --extra-arg -std=c++20 --output=%t --format=html --executor=standalone %s // RUN: FileCheck %s < %t/json/GlobalNamespace/index.json // Requires that T suports post and pre-incrementing. @@ -22,6 +23,10 @@ concept Incrementable = requires(T x) { // CHECK: "End": true, // CHECK-NEXT: "InfoType": "concept", // CHECK-NEXT: "IsType": true, +// CHECK-NEXT: "Location": { +// CHECK-NEXT: "Filename": "{{.*}}concept.cpp", +// CHECK-NEXT: "LineNumber": 7 +// CHECK-NEXT: }, // CHECK-NEXT: "Name": "Incrementable", // CHECK-NEXT: "Template": { // CHECK-NEXT: "Parameters": [ _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
