[llvm-branch-commits] [clang-tools-extra] [clang-doc] Introduce abstractions for pointer operations (PR #184872)
Paul Kirth via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Mar 6 14:49:19 PST 2026
https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/184872
>From 00571fb58b05fcb517d88e9d311119383ebc629e Mon Sep 17 00:00:00 2001
From: Paul Kirth <paulkirth at google.com>
Date: Thu, 5 Mar 2026 00:28:30 +0000
Subject: [PATCH] [clang-doc] Introduce abstractions for pointer operations
Since we're migrating from std::unique_ptr to raw pointers via
arena allocation, we want to have some interfaces that abstract
these operations away, and can be changed to keep the system working
without introducing a lot of unnecessary chrun in the code.
---
clang-tools-extra/clang-doc/BitcodeReader.cpp | 8 +++----
clang-tools-extra/clang-doc/JSONGenerator.cpp | 2 +-
clang-tools-extra/clang-doc/MDGenerator.cpp | 2 +-
.../clang-doc/Representation.cpp | 6 ++---
clang-tools-extra/clang-doc/Representation.h | 11 +++++++++
clang-tools-extra/clang-doc/Serialize.cpp | 24 +++++++++----------
clang-tools-extra/clang-doc/YAMLGenerator.cpp | 2 +-
.../benchmarks/ClangDocBenchmark.cpp | 8 +++----
.../clang-doc/tool/ClangDocMain.cpp | 6 ++---
9 files changed, 40 insertions(+), 29 deletions(-)
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp
index 6cd0cb06871de..1589e20064889 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -507,8 +507,8 @@ template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumValueInfo *I) {
}
template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) {
- I->Children.emplace_back(std::make_unique<CommentInfo>());
- return I->Children.back().get();
+ I->Children.emplace_back(allocatePtr<CommentInfo>());
+ return getPtr(I->Children.back());
}
template <> llvm::Expected<CommentInfo *> getCommentInfo(ConceptInfo *I) {
@@ -1078,8 +1078,8 @@ llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
template <typename T>
llvm::Expected<OwnedPtr<Info>> ClangDocBitcodeReader::createInfo(unsigned ID) {
llvm::TimeTraceScope("Reducing infos", "createInfo");
- OwnedPtr<Info> I = std::make_unique<T>();
- if (auto Err = readBlock(ID, static_cast<T *>(I.get())))
+ OwnedPtr<Info> I = doc::allocatePtr<T>();
+ if (auto Err = readBlock(ID, static_cast<T *>(getPtr(I))))
return std::move(Err);
return OwnedPtr<Info>{std::move(I)};
}
diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp
index efdff7f5b2cb1..05ff399f4cebb 100644
--- a/clang-tools-extra/clang-doc/JSONGenerator.cpp
+++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp
@@ -953,7 +953,7 @@ Error JSONGenerator::generateDocumentation(
StringSet<> CreatedDirs;
StringMap<std::vector<doc::Info *>> FileToInfos;
for (const auto &Group : Infos) {
- Info *Info = Group.getValue().get();
+ Info *Info = getPtr(Group.getValue());
SmallString<128> Path;
auto RootDirStr = RootDir.str() + "/json";
diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp
index c72dd11bc9df8..172ec9b524db8 100644
--- a/clang-tools-extra/clang-doc/MDGenerator.cpp
+++ b/clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -423,7 +423,7 @@ llvm::Error MDGenerator::generateDocumentation(
// Collect all output by file name and create the necessary directories.
llvm::StringMap<std::vector<doc::Info *>> FileToInfos;
for (const auto &Group : Infos) {
- doc::Info *Info = Group.getValue().get();
+ doc::Info *Info = getPtr(Group.getValue());
llvm::SmallString<128> Path;
llvm::sys::path::native(RootDir, Path);
diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp
index c9bfd419d622b..a8b221f94f4b9 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -89,10 +89,10 @@ static llvm::Expected<OwnedPtr<Info>> reduce(OwningPtrArray<Info> &Values) {
if (Values.empty() || !Values[0])
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"no value to reduce");
- OwnedPtr<Info> Merged = std::make_unique<T>(Values[0]->USR);
- T *Tmp = static_cast<T *>(Merged.get());
+ OwnedPtr<Info> Merged = allocatePtr<T>(Values[0]->USR);
+ T *Tmp = static_cast<T *>(getPtr(Merged));
for (auto &I : Values)
- Tmp->merge(std::move(*static_cast<T *>(I.get())));
+ Tmp->merge(std::move(*static_cast<T *>(getPtr(I))));
return std::move(Merged);
}
diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h
index 6cae3c017d583..b09ee6dd7b36d 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -48,6 +48,17 @@ template <typename T> using OwningPtrVec = std::vector<OwnedPtr<T>>;
// To be eventually transitioned to arena-allocated arrays of bare pointers.
template <typename T> using OwningPtrArray = std::vector<OwnedPtr<T>>;
+// A helper function to create an owned pointer, abstracting away the memory
+// allocation mechanism.
+template <typename T, typename... Args>
+OwnedPtr<T> allocatePtr(Args &&...args) {
+ return std::make_unique<T>(std::forward<Args>(args)...);
+}
+
+// A helper function to access the underlying pointer from an owned pointer,
+// abstracting away the pointer dereferencing mechanism.
+template <typename T> T *getPtr(const OwnedPtr<T> &O) { return O.get(); }
+
// SHA1'd hash of a USR.
using SymbolID = std::array<uint8_t, 20>;
diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp
index afd2ffd391ba9..b6e963bd5fd74 100644
--- a/clang-tools-extra/clang-doc/Serialize.cpp
+++ b/clang-tools-extra/clang-doc/Serialize.cpp
@@ -241,7 +241,7 @@ void ClangDocCommentVisitor::parseComment(const comments::Comment *C) {
ConstCommentVisitor<ClangDocCommentVisitor>::visit(C);
for (comments::Comment *Child :
llvm::make_range(C->child_begin(), C->child_end())) {
- CurrentCI.Children.emplace_back(std::make_unique<CommentInfo>());
+ CurrentCI.Children.emplace_back(allocatePtr<CommentInfo>());
ClangDocCommentVisitor Visitor(*CurrentCI.Children.back());
Visitor.parseComment(Child);
}
@@ -349,17 +349,17 @@ static std::string serialize(T &I, DiagnosticsEngine &Diags) {
std::string serialize(OwnedPtr<Info> &I, DiagnosticsEngine &Diags) {
switch (I->IT) {
case InfoType::IT_namespace:
- return serialize(*static_cast<NamespaceInfo *>(I.get()), Diags);
+ return serialize(*static_cast<NamespaceInfo *>(getPtr(I)), Diags);
case InfoType::IT_record:
- return serialize(*static_cast<RecordInfo *>(I.get()), Diags);
+ return serialize(*static_cast<RecordInfo *>(getPtr(I)), Diags);
case InfoType::IT_enum:
- return serialize(*static_cast<EnumInfo *>(I.get()), Diags);
+ return serialize(*static_cast<EnumInfo *>(getPtr(I)), Diags);
case InfoType::IT_function:
- return serialize(*static_cast<FunctionInfo *>(I.get()), Diags);
+ return serialize(*static_cast<FunctionInfo *>(getPtr(I)), Diags);
case InfoType::IT_concept:
- return serialize(*static_cast<ConceptInfo *>(I.get()), Diags);
+ return serialize(*static_cast<ConceptInfo *>(getPtr(I)), Diags);
case InfoType::IT_variable:
- return serialize(*static_cast<VarInfo *>(I.get()), Diags);
+ return serialize(*static_cast<VarInfo *>(getPtr(I)), Diags);
case InfoType::IT_friend:
case InfoType::IT_typedef:
case InfoType::IT_default:
@@ -491,20 +491,20 @@ template <typename ChildType>
static OwnedPtr<Info> makeAndInsertIntoParent(ChildType Child) {
if (Child.Namespace.empty()) {
// Insert into unnamed parent namespace.
- auto ParentNS = std::make_unique<NamespaceInfo>();
+ auto ParentNS = allocatePtr<NamespaceInfo>();
InsertChild(ParentNS->Children, std::forward<ChildType>(Child));
return ParentNS;
}
switch (Child.Namespace[0].RefType) {
case InfoType::IT_namespace: {
- auto ParentNS = std::make_unique<NamespaceInfo>();
+ auto ParentNS = allocatePtr<NamespaceInfo>();
ParentNS->USR = Child.Namespace[0].USR;
InsertChild(ParentNS->Children, std::forward<ChildType>(Child));
return ParentNS;
}
case InfoType::IT_record: {
- auto ParentRec = std::make_unique<RecordInfo>();
+ auto ParentRec = allocatePtr<RecordInfo>();
ParentRec->USR = Child.Namespace[0].USR;
InsertChild(ParentRec->Children, std::forward<ChildType>(Child));
return ParentRec;
@@ -944,7 +944,7 @@ std::pair<OwnedPtr<Info>, OwnedPtr<Info>> emitInfo(const NamespaceDecl *D,
const FullComment *FC,
Location Loc,
bool PublicOnly) {
- auto NSI = std::make_unique<NamespaceInfo>();
+ auto NSI = allocatePtr<NamespaceInfo>();
bool IsInAnonymousNamespace = false;
populateInfo(*NSI, D, FC, IsInAnonymousNamespace);
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
@@ -1017,7 +1017,7 @@ std::pair<OwnedPtr<Info>, OwnedPtr<Info>> emitInfo(const RecordDecl *D,
Location Loc,
bool PublicOnly) {
- auto RI = std::make_unique<RecordInfo>();
+ auto RI = allocatePtr<RecordInfo>();
bool IsInAnonymousNamespace = false;
populateSymbolInfo(*RI, D, FC, Loc, IsInAnonymousNamespace);
diff --git a/clang-tools-extra/clang-doc/YAMLGenerator.cpp b/clang-tools-extra/clang-doc/YAMLGenerator.cpp
index ac2ef1d61e4f8..72e68b2c64206 100644
--- a/clang-tools-extra/clang-doc/YAMLGenerator.cpp
+++ b/clang-tools-extra/clang-doc/YAMLGenerator.cpp
@@ -358,7 +358,7 @@ llvm::Error YAMLGenerator::generateDocumentation(
StringRef RootDir, llvm::StringMap<doc::OwnedPtr<doc::Info>> Infos,
const ClangDocContext &CDCtx, std::string DirName) {
for (const auto &Group : Infos) {
- doc::Info *Info = Group.getValue().get();
+ doc::Info *Info = getPtr(Group.getValue());
// Output file names according to the USR except the global namesapce.
// Anonymous namespaces are taken care of in serialization, so here we can
diff --git a/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp b/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp
index 18e15de8129a1..be11cc80198e8 100644
--- a/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp
+++ b/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp
@@ -91,7 +91,7 @@ BENCHMARK(BM_Mapper_Scale)->Range(10, 10000);
// --- Reducer Benchmarks ---
static void BM_SerializeFunctionInfo(benchmark::State &State) {
- auto I = std::make_unique<FunctionInfo>();
+ auto I = allocatePtr<FunctionInfo>();
I->Name = "f";
I->DefLoc = Location(0, 0, "test.cpp");
I->ReturnType = TypeInfo("void");
@@ -119,7 +119,7 @@ static void BM_MergeInfos_Scale(benchmark::State &State) {
OwningPtrArray<Info> Input;
Input.reserve(State.range(0));
for (int i = 0; i < State.range(0); ++i) {
- auto I = std::make_unique<FunctionInfo>();
+ auto I = allocatePtr<FunctionInfo>();
I->Name = "f";
I->USR = USR;
I->DefLoc = Location(10, i, "test.cpp");
@@ -181,7 +181,7 @@ static void BM_JSONGenerator_Scale(benchmark::State &State) {
}
int NumRecords = State.range(0);
- auto NI = std::make_unique<NamespaceInfo>();
+ auto NI = allocatePtr<NamespaceInfo>();
NI->Name = "GlobalNamespace";
for (int i = 0; i < NumRecords; ++i) {
NI->Children.Records.emplace_back(SymbolID{(uint8_t)(i & 0xFF)},
@@ -200,7 +200,7 @@ static void BM_JSONGenerator_Scale(benchmark::State &State) {
for (auto _ : State) {
Output.clear();
- auto Err = (*G)->generateDocForInfo(NI.get(), OS, CDCtx);
+ auto Err = (*G)->generateDocForInfo(getPtr(NI), OS, CDCtx);
if (Err) {
State.SkipWithError("generateDocForInfo failed");
llvm::consumeError(std::move(Err));
diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
index c189a414324c8..8ea1aa4b9e89f 100644
--- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -228,11 +228,11 @@ sortUsrToInfo(llvm::StringMap<doc::OwnedPtr<doc::Info>> &USRToInfo) {
for (auto &I : USRToInfo) {
auto &Info = I.second;
if (Info->IT == doc::InfoType::IT_namespace) {
- auto *Namespace = static_cast<clang::doc::NamespaceInfo *>(Info.get());
+ auto *Namespace = static_cast<clang::doc::NamespaceInfo *>(getPtr(Info));
Namespace->Children.sort();
}
if (Info->IT == doc::InfoType::IT_record) {
- auto *Record = static_cast<clang::doc::RecordInfo *>(Info.get());
+ auto *Record = static_cast<clang::doc::RecordInfo *>(getPtr(Info));
Record->Children.sort();
}
}
@@ -400,7 +400,7 @@ Example usage for a project using a compile commands database:
{
llvm::TimeTraceScope Merge("addInfoToIndex");
std::lock_guard<llvm::sys::Mutex> Guard(IndexMutex);
- clang::doc::Generator::addInfoToIndex(CDCtx.Idx, Reduced.get());
+ clang::doc::Generator::addInfoToIndex(CDCtx.Idx, getPtr(Reduced));
}
// Save in the result map (needs a lock due to threaded access).
{
More information about the llvm-branch-commits
mailing list