[clang-tools-extra] [clang-doc] mangle specialization file names (PR #144617)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 18 09:47:45 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tools-extra
Author: Erick Velez (evelez7)
<details>
<summary>Changes</summary>
Currently, class template specializations are written to the same file as the template. This presents a problem in JSON since only one JSON object should be written per file. This patch adds a mangled name field to TemplateSpecializationInfo to distinguish files during documentation generation.
---
Full diff: https://github.com/llvm/llvm-project/pull/144617.diff
7 Files Affected:
- (modified) clang-tools-extra/clang-doc/BitcodeReader.cpp (+9)
- (modified) clang-tools-extra/clang-doc/BitcodeWriter.cpp (+6-1)
- (modified) clang-tools-extra/clang-doc/BitcodeWriter.h (+1)
- (modified) clang-tools-extra/clang-doc/JSONGenerator.cpp (+8-1)
- (modified) clang-tools-extra/clang-doc/Representation.h (+3)
- (modified) clang-tools-extra/clang-doc/Serialize.cpp (+8)
- (added) clang-tools-extra/test/clang-doc/json/specialization-mangled-name.cpp (+15)
``````````diff
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp
index 35058abab0663..9227cf2bf51a2 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -83,6 +83,13 @@ static llvm::Error decodeRecord(const Record &R, std::optional<Location> &Field,
return llvm::Error::success();
}
+static llvm::Error decodeRecord(const Record &R,
+ std::optional<SmallString<16>> &Field,
+ llvm::StringRef Blob) {
+ Field.emplace(Blob);
+ return llvm::Error::success();
+}
+
static llvm::Error decodeRecord(const Record &R, InfoType &Field,
llvm::StringRef Blob) {
switch (auto IT = static_cast<InfoType>(R[0])) {
@@ -379,6 +386,8 @@ static llvm::Error parseRecord(const Record &R, unsigned ID,
TemplateSpecializationInfo *I) {
if (ID == TEMPLATE_SPECIALIZATION_OF)
return decodeRecord(R, I->SpecializationOf, Blob);
+ if (ID == TEMPLATE_SPECIALIZATION_MANGLED_NAME)
+ return decodeRecord(R, I->MangledName, Blob);
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"invalid field for TemplateParamInfo");
}
diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
index f8a6859169b01..e2c58731fbc67 100644
--- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
@@ -202,6 +202,8 @@ static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
{TEMPLATE_PARAM_CONTENTS, {"Contents", &genStringAbbrev}},
{TEMPLATE_SPECIALIZATION_OF,
{"SpecializationOf", &genSymbolIdAbbrev}},
+ {TEMPLATE_SPECIALIZATION_MANGLED_NAME,
+ {"MangledName", &genStringAbbrev}},
{TYPEDEF_USR, {"USR", &genSymbolIdAbbrev}},
{TYPEDEF_NAME, {"Name", &genStringAbbrev}},
{TYPEDEF_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
@@ -263,7 +265,8 @@ static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
// Template Blocks.
{BI_TEMPLATE_BLOCK_ID, {}},
{BI_TEMPLATE_PARAM_BLOCK_ID, {TEMPLATE_PARAM_CONTENTS}},
- {BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, {TEMPLATE_SPECIALIZATION_OF}}};
+ {BI_TEMPLATE_SPECIALIZATION_BLOCK_ID,
+ {TEMPLATE_SPECIALIZATION_OF, TEMPLATE_SPECIALIZATION_MANGLED_NAME}}};
// AbbreviationMap
@@ -638,6 +641,8 @@ void ClangDocBitcodeWriter::emitBlock(const TemplateInfo &T) {
void ClangDocBitcodeWriter::emitBlock(const TemplateSpecializationInfo &T) {
StreamSubBlockGuard Block(Stream, BI_TEMPLATE_SPECIALIZATION_BLOCK_ID);
emitRecord(T.SpecializationOf, TEMPLATE_SPECIALIZATION_OF);
+ if (T.MangledName)
+ emitRecord(T.MangledName->str(), TEMPLATE_SPECIALIZATION_MANGLED_NAME);
for (const auto &P : T.Params)
emitBlock(P);
}
diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.h b/clang-tools-extra/clang-doc/BitcodeWriter.h
index e33a1aece883c..c0b879af59194 100644
--- a/clang-tools-extra/clang-doc/BitcodeWriter.h
+++ b/clang-tools-extra/clang-doc/BitcodeWriter.h
@@ -131,6 +131,7 @@ enum RecordId {
REFERENCE_FIELD,
TEMPLATE_PARAM_CONTENTS,
TEMPLATE_SPECIALIZATION_OF,
+ TEMPLATE_SPECIALIZATION_MANGLED_NAME,
TYPEDEF_USR,
TYPEDEF_NAME,
TYPEDEF_DEFLOCATION,
diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp
index 0f7cbafcf5135..ca56e669038b4 100644
--- a/clang-tools-extra/clang-doc/JSONGenerator.cpp
+++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp
@@ -491,7 +491,14 @@ Error JSONGenerator::generateDocs(
CreatedDirs.insert(Path);
}
- sys::path::append(Path, Info->getFileBaseName() + ".json");
+ SmallString<16> FileBaseName = Info->getFileBaseName();
+ if (Info->IT == InfoType::IT_record) {
+ if (auto Template = static_cast<RecordInfo *>(Info)->Template;
+ Template && Template->Specialization &&
+ Template->Specialization->MangledName)
+ FileBaseName = Template->Specialization->MangledName.value();
+ }
+ sys::path::append(Path, FileBaseName + ".json");
FileToInfos[Path].push_back(Info);
}
diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h
index 75da500645819..6c88712706dc0 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -209,6 +209,9 @@ struct TemplateSpecializationInfo {
// Template parameters applying to the specialized record/function.
std::vector<TemplateParamInfo> Params;
+
+ // Used to distinguish class specialization file names.
+ std::optional<SmallString<16>> MangledName;
};
// Records the template information for a struct or function that is a template
diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp
index e8f1a9cee2675..d82d2cd2c9eeb 100644
--- a/clang-tools-extra/clang-doc/Serialize.cpp
+++ b/clang-tools-extra/clang-doc/Serialize.cpp
@@ -10,6 +10,7 @@
#include "BitcodeWriter.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Comment.h"
+#include "clang/AST/Mangle.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/StringExtras.h"
@@ -909,6 +910,13 @@ emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc,
RI->Template.emplace();
RI->Template->Specialization.emplace();
auto &Specialization = *RI->Template->Specialization;
+ auto *Mangler = ItaniumMangleContext::create(
+ D->getASTContext(), D->getASTContext().getDiagnostics());
+ std::string MangledName;
+ llvm::raw_string_ostream Stream(MangledName);
+ Mangler->mangleCXXVTT(dyn_cast<CXXRecordDecl>(D), Stream);
+ Specialization.MangledName.emplace(MangledName);
+ delete Mangler;
// What this is a specialization of.
auto SpecOf = CTSD->getSpecializedTemplateOrPartial();
diff --git a/clang-tools-extra/test/clang-doc/json/specialization-mangled-name.cpp b/clang-tools-extra/test/clang-doc/json/specialization-mangled-name.cpp
new file mode 100644
index 0000000000000..5d25c53f37a36
--- /dev/null
+++ b/clang-tools-extra/test/clang-doc/json/specialization-mangled-name.cpp
@@ -0,0 +1,15 @@
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: clang-doc --output=%t --format=json --executor=standalone %s
+// RUN: FileCheck %s < %t/GlobalNamespace/_ZTT7MyClassIiE.json
+
+template<typename T> class MyClass;
+
+template<> class MyClass<int>;
+
+// CHECK: "Name": "MyClass",
+// CHECK: "Template": {
+// CHECK-NEXT: "Specialization": {
+// CHECK-NEXT: "Parameters": [
+// CHECK-NEXT: "int"
+// CHECK-NEXT: ],
+// CHECK-NEXT: "SpecializationOf": "{{[0-9A-F]*}}"
``````````
</details>
https://github.com/llvm/llvm-project/pull/144617
More information about the cfe-commits
mailing list