[clang] [clang][doc]: Merge the contents of identical entries. (PR #134089)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Apr 5 01:34:31 PDT 2025
https://github.com/YLChenZ updated https://github.com/llvm/llvm-project/pull/134089
>From 319c55aef5c458ae4ac6c7f3f186d338f6fe2e37 Mon Sep 17 00:00:00 2001
From: YLChenZ <chentongyongcz at gmail.com>
Date: Wed, 2 Apr 2025 22:03:53 +0800
Subject: [PATCH 1/5] [llvm][doc]: Merge the contents of identical entries.
---
clang/utils/TableGen/ClangAttrEmitter.cpp | 68 +++++++++++++++++------
1 file changed, 50 insertions(+), 18 deletions(-)
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 06f6b073240ba..6a2cdcd4ebc8e 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -5144,6 +5144,14 @@ class SpellingList {
Spellings[(size_t)Kind].push_back(Name);
}
+
+ void merge(const SpellingList &Other) {
+ for (size_t Kind = 0; Kind < NumSpellingKinds; ++Kind) {
+ Spellings[Kind].insert(Spellings[Kind].end(),
+ Other.Spellings[Kind].begin(),
+ Other.Spellings[Kind].end());
+ }
+ }
};
class DocumentationData {
@@ -5301,44 +5309,68 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
return L->getValueAsString("Name") < R->getValueAsString("Name");
}
};
- std::map<const Record *, std::vector<DocumentationData>, CategoryLess>
+
+ std::map<const Record *, std::map<std::string, DocumentationData>,
+ CategoryLess>
SplitDocs;
+
+ // Collect documentation data, grouping by category and heading.
for (const auto *A : Records.getAllDerivedDefinitions("Attr")) {
const Record &Attr = *A;
std::vector<const Record *> Docs =
Attr.getValueAsListOfDefs("Documentation");
+
for (const auto *D : Docs) {
const Record &Doc = *D;
const Record *Category = Doc.getValueAsDef("Category");
// If the category is "InternalOnly", then there cannot be any other
// documentation categories (otherwise, the attribute would be
// emitted into the docs).
- const StringRef Cat = Category->getValueAsString("Name");
- bool InternalOnly = Cat == "InternalOnly";
- if (InternalOnly && Docs.size() > 1)
+ StringRef Cat = Category->getValueAsString("Name");
+ if (Cat == "InternalOnly" && Docs.size() > 1)
PrintFatalError(Doc.getLoc(),
"Attribute is \"InternalOnly\", but has multiple "
"documentation categories");
- if (!InternalOnly)
- SplitDocs[Category].push_back(DocumentationData(
- Doc, Attr, GetAttributeHeadingAndSpellings(Doc, Attr, Cat)));
+ if (Cat == "InternalOnly")
+ continue;
+
+ // Generate Heading and Spellings.
+ auto HeadingAndSpellings =
+ GetAttributeHeadingAndSpellings(Doc, Attr, Cat);
+
+ auto &CategoryDocs = SplitDocs[Category];
+
+ // If the heading already exists, merge the documentation.
+ auto It = CategoryDocs.find(HeadingAndSpellings.first);
+ if (It != CategoryDocs.end()) {
+ // Merge spellings
+ It->second.SupportedSpellings.merge(HeadingAndSpellings.second);
+ // Merge content
+ It->second.Documentation = &Doc; // Update reference
+ } else {
+ // Otherwise, add a new entry.
+ CategoryDocs.emplace(HeadingAndSpellings.first,
+ DocumentationData(Doc, Attr, HeadingAndSpellings));
+ }
}
}
- // Having split the attributes out based on what documentation goes where,
- // we can begin to generate sections of documentation.
- for (auto &I : SplitDocs) {
- WriteCategoryHeader(I.first, OS);
+ // Write out documentation, merging attributes with the same heading.
+ for (auto &CategoryPair : SplitDocs) {
+ WriteCategoryHeader(CategoryPair.first, OS);
+
+ std::vector<DocumentationData> MergedDocs;
+ for (auto &DocPair : CategoryPair.second)
+ MergedDocs.push_back(std::move(DocPair.second));
- sort(I.second,
- [](const DocumentationData &D1, const DocumentationData &D2) {
- return D1.Heading < D2.Heading;
- });
+ std::sort(MergedDocs.begin(), MergedDocs.end(),
+ [](const DocumentationData &D1, const DocumentationData &D2) {
+ return D1.Heading < D2.Heading;
+ });
- // Walk over each of the attributes in the category and write out their
- // documentation.
- for (const auto &Doc : I.second)
+ // Output each documentation entry.
+ for (const auto &Doc : MergedDocs)
WriteDocumentation(Records, Doc, OS);
}
}
>From 24307e5587a9f71c05fb03b9ea4c8f7e539876c3 Mon Sep 17 00:00:00 2001
From: YLChenZ <chentongyongcz at gmail.com>
Date: Fri, 4 Apr 2025 09:29:59 +0800
Subject: [PATCH 2/5] merge with same content
---
clang/utils/TableGen/ClangAttrEmitter.cpp | 36 +++++++++++------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 6a2cdcd4ebc8e..3d119f6be4131 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -5144,12 +5144,11 @@ class SpellingList {
Spellings[(size_t)Kind].push_back(Name);
}
-
+
void merge(const SpellingList &Other) {
for (size_t Kind = 0; Kind < NumSpellingKinds; ++Kind) {
Spellings[Kind].insert(Spellings[Kind].end(),
- Other.Spellings[Kind].begin(),
- Other.Spellings[Kind].end());
+ Other.Spellings[Kind].begin(), Other.Spellings[Kind].end());
}
}
};
@@ -5309,16 +5308,13 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
return L->getValueAsString("Name") < R->getValueAsString("Name");
}
};
-
- std::map<const Record *, std::map<std::string, DocumentationData>,
- CategoryLess>
- SplitDocs;
+
+ std::map<const Record *, std::map<uint32_t, DocumentationData>, CategoryLess> SplitDocs;
// Collect documentation data, grouping by category and heading.
for (const auto *A : Records.getAllDerivedDefinitions("Attr")) {
const Record &Attr = *A;
- std::vector<const Record *> Docs =
- Attr.getValueAsListOfDefs("Documentation");
+ std::vector<const Record *> Docs = Attr.getValueAsListOfDefs("Documentation");
for (const auto *D : Docs) {
const Record &Doc = *D;
@@ -5336,27 +5332,31 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
continue;
// Generate Heading and Spellings.
- auto HeadingAndSpellings =
- GetAttributeHeadingAndSpellings(Doc, Attr, Cat);
+ auto HeadingAndSpellings = GetAttributeHeadingAndSpellings(Doc, Attr, Cat);
auto &CategoryDocs = SplitDocs[Category];
- // If the heading already exists, merge the documentation.
- auto It = CategoryDocs.find(HeadingAndSpellings.first);
+ std::string key = Doc.getValueAsString("Content").str();
+ uint32_t keyHash = llvm::hash_value(key);
+ // If the content already exists, merge the documentation.
+ auto It = CategoryDocs.find(keyHash);
if (It != CategoryDocs.end()) {
+ //Merge heading
+ if (It->second.Heading != HeadingAndSpellings.first)
+ It->second.Heading += ", " + HeadingAndSpellings.first;
// Merge spellings
It->second.SupportedSpellings.merge(HeadingAndSpellings.second);
// Merge content
It->second.Documentation = &Doc; // Update reference
- } else {
- // Otherwise, add a new entry.
- CategoryDocs.emplace(HeadingAndSpellings.first,
- DocumentationData(Doc, Attr, HeadingAndSpellings));
+ }
+ else {
+ // Otherwise, add a new entry.
+ CategoryDocs.emplace(keyHash, DocumentationData(Doc, Attr, HeadingAndSpellings));
}
}
}
- // Write out documentation, merging attributes with the same heading.
+ // Write out documentation, merging attributes with the same content.
for (auto &CategoryPair : SplitDocs) {
WriteCategoryHeader(CategoryPair.first, OS);
>From 324d4064c8c27521d9d3043b3040ce7c781e6386 Mon Sep 17 00:00:00 2001
From: YLChenZ <chentongyongcz at gmail.com>
Date: Fri, 4 Apr 2025 09:30:57 +0800
Subject: [PATCH 3/5] merge with same content
---
clang/utils/TableGen/ClangAttrEmitter.cpp | 26 +++++++++++++----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 3d119f6be4131..0ea12eeba1d5d 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -5144,11 +5144,12 @@ class SpellingList {
Spellings[(size_t)Kind].push_back(Name);
}
-
+
void merge(const SpellingList &Other) {
for (size_t Kind = 0; Kind < NumSpellingKinds; ++Kind) {
Spellings[Kind].insert(Spellings[Kind].end(),
- Other.Spellings[Kind].begin(), Other.Spellings[Kind].end());
+ Other.Spellings[Kind].begin(),
+ Other.Spellings[Kind].end());
}
}
};
@@ -5308,13 +5309,15 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
return L->getValueAsString("Name") < R->getValueAsString("Name");
}
};
-
- std::map<const Record *, std::map<uint32_t, DocumentationData>, CategoryLess> SplitDocs;
+
+ std::map<const Record *, std::map<uint32_t, DocumentationData>, CategoryLess>
+ SplitDocs;
// Collect documentation data, grouping by category and heading.
for (const auto *A : Records.getAllDerivedDefinitions("Attr")) {
const Record &Attr = *A;
- std::vector<const Record *> Docs = Attr.getValueAsListOfDefs("Documentation");
+ std::vector<const Record *> Docs =
+ Attr.getValueAsListOfDefs("Documentation");
for (const auto *D : Docs) {
const Record &Doc = *D;
@@ -5332,7 +5335,8 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
continue;
// Generate Heading and Spellings.
- auto HeadingAndSpellings = GetAttributeHeadingAndSpellings(Doc, Attr, Cat);
+ auto HeadingAndSpellings =
+ GetAttributeHeadingAndSpellings(Doc, Attr, Cat);
auto &CategoryDocs = SplitDocs[Category];
@@ -5341,17 +5345,17 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
// If the content already exists, merge the documentation.
auto It = CategoryDocs.find(keyHash);
if (It != CategoryDocs.end()) {
- //Merge heading
+ // Merge heading
if (It->second.Heading != HeadingAndSpellings.first)
It->second.Heading += ", " + HeadingAndSpellings.first;
// Merge spellings
It->second.SupportedSpellings.merge(HeadingAndSpellings.second);
// Merge content
It->second.Documentation = &Doc; // Update reference
- }
- else {
- // Otherwise, add a new entry.
- CategoryDocs.emplace(keyHash, DocumentationData(Doc, Attr, HeadingAndSpellings));
+ } else {
+ // Otherwise, add a new entry.
+ CategoryDocs.emplace(keyHash,
+ DocumentationData(Doc, Attr, HeadingAndSpellings));
}
}
}
>From 50c9e4bc1f4e0b9c413c94aeaeebbece568685dc Mon Sep 17 00:00:00 2001
From: YLChenZ <chentongyongcz at gmail.com>
Date: Sat, 5 Apr 2025 16:33:14 +0800
Subject: [PATCH 4/5] Do not merge entries in Undocumented
---
clang/utils/TableGen/ClangAttrEmitter.cpp | 56 +++++++++++++++++------
1 file changed, 42 insertions(+), 14 deletions(-)
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 0ea12eeba1d5d..f960bd87d00cd 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -5311,7 +5311,10 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
};
std::map<const Record *, std::map<uint32_t, DocumentationData>, CategoryLess>
- SplitDocs;
+ MergedDocs;
+
+ std::vector<DocumentationData> UndocumentedDocs;
+ const Record *UndocumentedCategory = nullptr;
// Collect documentation data, grouping by category and heading.
for (const auto *A : Records.getAllDerivedDefinitions("Attr")) {
@@ -5333,15 +5336,26 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
if (Cat == "InternalOnly")
continue;
+
+ // Track the Undocumented category Record for later grouping
+ if (Cat == "Undocumented" && !UndocumentedCategory)
+ UndocumentedCategory = Category;
// Generate Heading and Spellings.
auto HeadingAndSpellings =
GetAttributeHeadingAndSpellings(Doc, Attr, Cat);
+
+ // Handle Undocumented category separately - no content merging
+ if (Cat == "Undocumented" && UndocumentedCategory) {
+ UndocumentedDocs.push_back(DocumentationData(Doc, Attr, HeadingAndSpellings));
+ continue;
+ }
- auto &CategoryDocs = SplitDocs[Category];
+ auto &CategoryDocs = MergedDocs[Category];
std::string key = Doc.getValueAsString("Content").str();
uint32_t keyHash = llvm::hash_value(key);
+
// If the content already exists, merge the documentation.
auto It = CategoryDocs.find(keyHash);
if (It != CategoryDocs.end()) {
@@ -5353,28 +5367,42 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
// Merge content
It->second.Documentation = &Doc; // Update reference
} else {
- // Otherwise, add a new entry.
+ // Create new entry for unique content
CategoryDocs.emplace(keyHash,
DocumentationData(Doc, Attr, HeadingAndSpellings));
}
}
}
- // Write out documentation, merging attributes with the same content.
- for (auto &CategoryPair : SplitDocs) {
- WriteCategoryHeader(CategoryPair.first, OS);
+ std::map<const Record *, std::vector<DocumentationData>, CategoryLess> SplitDocs;
- std::vector<DocumentationData> MergedDocs;
+ for (auto &CategoryPair : MergedDocs) {
+
+ std::vector<DocumentationData> MD;
for (auto &DocPair : CategoryPair.second)
- MergedDocs.push_back(std::move(DocPair.second));
+ MD.push_back(std::move(DocPair.second));
+
+ SplitDocs.emplace(CategoryPair.first, MD);
+ }
+
+ // Append Undocumented category entries
+ if (!UndocumentedDocs.empty() && UndocumentedCategory) {
+ SplitDocs.emplace(UndocumentedCategory, UndocumentedDocs);
+ }
+
+ // Having split the attributes out based on what documentation goes where,
+ // we can begin to generate sections of documentation.
+ for (auto &I : SplitDocs) {
+ WriteCategoryHeader(I.first, OS);
- std::sort(MergedDocs.begin(), MergedDocs.end(),
- [](const DocumentationData &D1, const DocumentationData &D2) {
- return D1.Heading < D2.Heading;
- });
+ sort(I.second,
+ [](const DocumentationData &D1, const DocumentationData &D2) {
+ return D1.Heading < D2.Heading;
+ });
- // Output each documentation entry.
- for (const auto &Doc : MergedDocs)
+ // Walk over each of the attributes in the category and write out their
+ // documentation.
+ for (const auto &Doc : I.second)
WriteDocumentation(Records, Doc, OS);
}
}
>From 59a3883020498cd70731bc99fcbca0f08be7b147 Mon Sep 17 00:00:00 2001
From: YLChenZ <chentongyongcz at gmail.com>
Date: Sat, 5 Apr 2025 16:34:08 +0800
Subject: [PATCH 5/5] clang-format
---
clang/utils/TableGen/ClangAttrEmitter.cpp | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index f960bd87d00cd..07844c8f0967b 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -5311,7 +5311,7 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
};
std::map<const Record *, std::map<uint32_t, DocumentationData>, CategoryLess>
- MergedDocs;
+ MergedDocs;
std::vector<DocumentationData> UndocumentedDocs;
const Record *UndocumentedCategory = nullptr;
@@ -5336,7 +5336,7 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
if (Cat == "InternalOnly")
continue;
-
+
// Track the Undocumented category Record for later grouping
if (Cat == "Undocumented" && !UndocumentedCategory)
UndocumentedCategory = Category;
@@ -5344,10 +5344,11 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
// Generate Heading and Spellings.
auto HeadingAndSpellings =
GetAttributeHeadingAndSpellings(Doc, Attr, Cat);
-
+
// Handle Undocumented category separately - no content merging
if (Cat == "Undocumented" && UndocumentedCategory) {
- UndocumentedDocs.push_back(DocumentationData(Doc, Attr, HeadingAndSpellings));
+ UndocumentedDocs.push_back(
+ DocumentationData(Doc, Attr, HeadingAndSpellings));
continue;
}
@@ -5374,17 +5375,18 @@ void EmitClangAttrDocs(const RecordKeeper &Records, raw_ostream &OS) {
}
}
- std::map<const Record *, std::vector<DocumentationData>, CategoryLess> SplitDocs;
+ std::map<const Record *, std::vector<DocumentationData>, CategoryLess>
+ SplitDocs;
for (auto &CategoryPair : MergedDocs) {
std::vector<DocumentationData> MD;
for (auto &DocPair : CategoryPair.second)
- MD.push_back(std::move(DocPair.second));
-
+ MD.push_back(std::move(DocPair.second));
+
SplitDocs.emplace(CategoryPair.first, MD);
}
-
+
// Append Undocumented category entries
if (!UndocumentedDocs.empty() && UndocumentedCategory) {
SplitDocs.emplace(UndocumentedCategory, UndocumentedDocs);
More information about the cfe-commits
mailing list