[llvm-branch-commits] [clang-tools-extra] [clang-doc] Use distinct APIs for fixed arena allocation sites (PR #190426)
Paul Kirth via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Apr 3 16:16:23 PDT 2026
https://github.com/ilovepi created https://github.com/llvm/llvm-project/pull/190426
Typically, code either always emits data into the TransientArena or the
PersistentArena. Use more explicit APIs to convey the intent directly
instead of relying on parameters or defaults.
>From f507946f978e92d0e2c91e32c2e9a6a3786d9cae Mon Sep 17 00:00:00 2001
From: Paul Kirth <paulkirth at google.com>
Date: Fri, 3 Apr 2026 22:13:39 +0000
Subject: [PATCH] [clang-doc] Use distinct APIs for fixed arena allocation
sites
Typically, code either always emits data into the TransientArena or the
PersistentArena. Use more explicit APIs to convey the intent directly
instead of relying on parameters or defaults.
---
clang-tools-extra/clang-doc/BitcodeReader.cpp | 14 ++++----
.../clang-doc/Representation.cpp | 15 ++++----
clang-tools-extra/clang-doc/Representation.h | 11 ++++--
clang-tools-extra/clang-doc/Serialize.cpp | 35 ++++++++++---------
.../benchmarks/ClangDocBenchmark.cpp | 6 ++--
5 files changed, 43 insertions(+), 38 deletions(-)
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp
index 6868eb533d75c..3193ff77279de 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -135,9 +135,9 @@ static llvm::Error decodeRecord(const Record &R, DocList<Location> &Field,
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"integer too large to parse");
- Field.push_back(*allocatePtr<Location>(static_cast<int>(R[0]),
- static_cast<int>(R[1]), Blob,
- static_cast<bool>(R[2])));
+ Field.push_back(*allocateTransient<Location>(static_cast<int>(R[0]),
+ static_cast<int>(R[1]), Blob,
+ static_cast<bool>(R[2])));
return llvm::Error::success();
}
@@ -884,7 +884,7 @@ template <typename T> static llvm::Expected<CommentInfo *> getCommentInfo(T I) {
if constexpr (std::is_pointer_v<T>) {
using Pointee = std::remove_pointer_t<T>;
if constexpr (has_description<Pointee>::value) {
- auto *NewComment = allocatePtr<CommentInfo>();
+ auto *NewComment = allocateTransient<CommentInfo>();
I->Description.push_back(*NewComment);
return NewComment;
}
@@ -1080,7 +1080,7 @@ static void addChild(Target I, Child &&R) {
if constexpr (has_children<Pointee>::value) {
using BareChild = std::remove_cv_t<std::remove_reference_t<Child>>;
if constexpr (is_valid_child<BareChild>::value) {
- auto *Node = allocatePtr<BareChild>(std::move(R));
+ auto *Node = allocateTransient<BareChild>(std::move(R));
getList(I->Children, Node).push_back(*Node);
return;
}
@@ -1409,10 +1409,10 @@ llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() {
template <typename T>
llvm::Expected<OwnedPtr<Info>> ClangDocBitcodeReader::createInfo(unsigned ID) {
llvm::TimeTraceScope("Reducing infos", "createInfo");
- OwnedPtr<Info> I = doc::allocatePtr<T>();
+ auto *I = doc::allocateTransient<T>();
if (auto Err = readBlock(ID, static_cast<T *>(getPtr(I))))
return std::move(Err);
- return OwnedPtr<Info>{std::move(I)};
+ return I;
}
llvm::Expected<OwnedPtr<Info>>
diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp
index 0b830eede7949..c929265da4959 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -98,11 +98,10 @@ static llvm::Expected<Info *> reduce(SmallVectorImpl<Info *> &Values) {
if (Values.empty() || !Values[0])
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"no value to reduce");
- OwnedPtr<Info> Merged = allocatePtr<T>(Values[0]->USR);
- T *Tmp = static_cast<T *>(getPtr(Merged));
+ T *Merged = allocateTransient<T>(Values[0]->USR);
for (auto &I : Values)
- Tmp->merge(std::move(*static_cast<T *>(getPtr(I))));
- return std::move(Merged);
+ Merged->merge(std::move(*static_cast<T *>(I)));
+ return Merged;
}
template <typename T>
@@ -115,7 +114,7 @@ static void reduceChildren(llvm::simple_ilist<T> &Children,
auto It = llvm::find_if(
Children, [&](const T &C) { return C.USR == ChildToMerge->USR; });
if (It == Children.end()) {
- T *NewChild = allocatePtr<T>(PersistentArena, ChildToMerge->USR);
+ T *NewChild = allocatePersistent<T>(ChildToMerge->USR);
NewChild->merge(std::move(*ChildToMerge));
Children.push_back(*NewChild);
} else {
@@ -136,7 +135,7 @@ void reduceChildren<Reference>(
return C.USR == ChildToMerge->USR;
});
if (It == Children.end()) {
- Reference *NewChild = allocatePtr<Reference>(PersistentArena);
+ Reference *NewChild = allocatePersistent<Reference>();
NewChild->USR = ChildToMerge->USR;
NewChild->RefType = ChildToMerge->RefType;
NewChild->merge(std::move(*ChildToMerge));
@@ -154,7 +153,7 @@ static void mergeUnkeyed(Container &Target, Container &&Source) {
auto &Item = Source.front();
Source.pop_front();
if (llvm::none_of(Target, [&](const auto &E) { return E == Item; })) {
- T *NewItem = allocatePtr<T>(PersistentArena, Item);
+ T *NewItem = allocatePersistent<T>(Item);
Target.push_back(*NewItem);
}
}
@@ -168,7 +167,7 @@ void mergeUnkeyed<DocList<CommentInfo>>(DocList<CommentInfo> &Target,
Source.pop_front();
if (llvm::none_of(Target, [&](const auto &E) { return E == Item; })) {
CommentInfo *NewItem =
- allocatePtr<CommentInfo>(PersistentArena, Item, PersistentArena);
+ allocatePersistent<CommentInfo>(Item, PersistentArena);
Target.push_back(*NewItem);
}
}
diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h
index b656ada26110a..048e61f9a223d 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -112,13 +112,18 @@ template <typename T> using OwnedPtr = T *;
// To be eventually transitioned to llvm::simple_ilist.
template <typename T> using DocList = llvm::simple_ilist<T>;
-// A helper function to create an owned pointer, abstracting away the memory
-// allocation mechanism.
+// A helper function to create memory allocated in the TransientArena.
template <typename T, typename... Args>
-OwnedPtr<T> allocatePtr(Args &&...args) {
+OwnedPtr<T> allocateTransient(Args &&...args) {
return new (TransientArena.Allocate<T>()) T(std::forward<Args>(args)...);
}
+// A helper function to create memory allocated in the TransientArena.
+template <typename T, typename... Args>
+OwnedPtr<T> allocatePersistent(Args &&...args) {
+ return new (PersistentArena.Allocate<T>()) T(std::forward<Args>(args)...);
+}
+
// An overload to explicitly allocate on an arena, returning a bare pointer.
template <typename T, typename... Args>
T *allocatePtr(llvm::BumpPtrAllocator &Alloc, Args &&...args) {
diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp
index 4b2f0b5eac3a4..4e804cfc463bc 100644
--- a/clang-tools-extra/clang-doc/Serialize.cpp
+++ b/clang-tools-extra/clang-doc/Serialize.cpp
@@ -465,34 +465,34 @@ void Serializer::InsertChild(ScopeChildren &Scope, const NamespaceInfo &Info) {
}
void Serializer::InsertChild(ScopeChildren &Scope, const RecordInfo &Info) {
- Reference *R = allocatePtr<Reference>(
+ Reference *R = allocateTransient<Reference>(
Info.USR, Info.Name, InfoType::IT_record, Info.Name,
getInfoRelativePath(Info.Namespace), Info.MangledName);
Scope.Records.push_back(*R);
}
void Serializer::InsertChild(ScopeChildren &Scope, EnumInfo Info) {
- EnumInfo *E = allocatePtr<EnumInfo>(std::move(Info));
+ EnumInfo *E = allocateTransient<EnumInfo>(std::move(Info));
Scope.Enums.push_back(*E);
}
void Serializer::InsertChild(ScopeChildren &Scope, FunctionInfo Info) {
- FunctionInfo *F = allocatePtr<FunctionInfo>(std::move(Info));
+ FunctionInfo *F = allocateTransient<FunctionInfo>(std::move(Info));
Scope.Functions.push_back(*F);
}
void Serializer::InsertChild(ScopeChildren &Scope, TypedefInfo Info) {
- TypedefInfo *T = allocatePtr<TypedefInfo>(std::move(Info));
+ TypedefInfo *T = allocateTransient<TypedefInfo>(std::move(Info));
Scope.Typedefs.push_back(*T);
}
void Serializer::InsertChild(ScopeChildren &Scope, ConceptInfo Info) {
- ConceptInfo *C = allocatePtr<ConceptInfo>(std::move(Info));
+ ConceptInfo *C = allocateTransient<ConceptInfo>(std::move(Info));
Scope.Concepts.push_back(*C);
}
void Serializer::InsertChild(ScopeChildren &Scope, VarInfo Info) {
- VarInfo *V = allocatePtr<VarInfo>(std::move(Info));
+ VarInfo *V = allocateTransient<VarInfo>(std::move(Info));
Scope.Variables.push_back(*V);
}
@@ -514,20 +514,20 @@ template <typename ChildType>
OwnedPtr<Info> Serializer::makeAndInsertIntoParent(ChildType Child) {
if (Child.Namespace.empty()) {
// Insert into unnamed parent namespace.
- auto ParentNS = allocatePtr<NamespaceInfo>();
+ auto *ParentNS = allocateTransient<NamespaceInfo>();
InsertChild(ParentNS->Children, std::forward<ChildType>(Child));
return ParentNS;
}
switch (Child.Namespace[0].RefType) {
case InfoType::IT_namespace: {
- auto ParentNS = allocatePtr<NamespaceInfo>();
+ auto *ParentNS = allocateTransient<NamespaceInfo>();
ParentNS->USR = Child.Namespace[0].USR;
InsertChild(ParentNS->Children, std::forward<ChildType>(Child));
return ParentNS;
}
case InfoType::IT_record: {
- auto ParentRec = allocatePtr<RecordInfo>();
+ auto *ParentRec = allocateTransient<RecordInfo>();
ParentRec->USR = Child.Namespace[0].USR;
InsertChild(ParentRec->Children, std::forward<ChildType>(Child));
return ParentRec;
@@ -617,7 +617,7 @@ void Serializer::parseEnumerators(EnumInfo &I, const EnumDecl *D) {
E->getASTContext().getRawCommentForDeclNoCache(E)) {
Comment->setAttached();
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, E)) {
- CommentInfo *NewCI = allocatePtr<CommentInfo>();
+ CommentInfo *NewCI = allocateTransient<CommentInfo>();
Member.Description.push_back(*NewCI);
parseFullComment(Fc, Member.Description.back());
}
@@ -800,7 +800,7 @@ void Serializer::populateInfo(Info &I, const T *D, const FullComment *C,
I.Namespace = allocateArray<Reference>(LocalNamespaces, TransientArena);
if (C) {
- CommentInfo *NewCI = allocatePtr<CommentInfo>();
+ CommentInfo *NewCI = allocateTransient<CommentInfo>();
I.Description.push_back(*NewCI);
parseFullComment(C, I.Description.back());
}
@@ -814,7 +814,7 @@ void Serializer::populateSymbolInfo(SymbolInfo &I, const T *D,
if (D->isThisDeclarationADefinition())
I.DefLoc = Loc;
else {
- Location *NewL = allocatePtr<Location>(Loc);
+ Location *NewL = allocateTransient<Location>(Loc);
I.Loc.push_back(*NewL);
}
@@ -937,7 +937,7 @@ void Serializer::populateMemberTypeInfo(T &I, const Decl *D) {
Comment->setAttached();
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) {
- CommentInfo *NewCI = allocatePtr<CommentInfo>();
+ CommentInfo *NewCI = allocateTransient<CommentInfo>();
I.Description.push_back(*NewCI);
parseFullComment(Fc, I.Description.back());
}
@@ -997,7 +997,8 @@ void Serializer::parseBases(llvm::SmallVectorImpl<BaseRecordInfo> &Bases,
IsInAnonymousNamespace);
FI.Access =
getFinalAccessSpecifier(BI.Access, MD->getAccessUnsafe());
- FunctionInfo *FIPtr = allocatePtr<FunctionInfo>(std::move(FI));
+ FunctionInfo *FIPtr =
+ allocateTransient<FunctionInfo>(std::move(FI));
BI.Children.Functions.push_back(*FIPtr);
}
Bases.emplace_back(std::move(BI));
@@ -1014,7 +1015,7 @@ void Serializer::parseBases(llvm::SmallVectorImpl<BaseRecordInfo> &Bases,
std::pair<OwnedPtr<Info>, OwnedPtr<Info>>
Serializer::emitInfo(const NamespaceDecl *D, const FullComment *FC,
Location Loc, bool PublicOnly) {
- auto NSI = allocatePtr<NamespaceInfo>();
+ auto *NSI = allocateTransient<NamespaceInfo>();
bool IsInAnonymousNamespace = false;
populateInfo(*NSI, D, FC, IsInAnonymousNamespace);
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
@@ -1090,7 +1091,7 @@ std::pair<OwnedPtr<Info>, OwnedPtr<Info>>
Serializer::emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc,
bool PublicOnly) {
- auto RI = allocatePtr<RecordInfo>();
+ auto *RI = allocateTransient<RecordInfo>();
bool IsInAnonymousNamespace = false;
populateSymbolInfo(*RI, D, FC, Loc, IsInAnonymousNamespace);
@@ -1222,7 +1223,7 @@ void Serializer::extractCommentFromDecl(const Decl *D, TypedefInfo &Info) {
Comment->setAttached();
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) {
- CommentInfo *NewCI = allocatePtr<CommentInfo>();
+ CommentInfo *NewCI = allocateTransient<CommentInfo>();
Info.Description.push_back(*NewCI);
parseFullComment(Fc, *NewCI);
}
diff --git a/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp b/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp
index 3a0f7561a4740..5f987672b745e 100644
--- a/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp
+++ b/clang-tools-extra/clang-doc/benchmarks/ClangDocBenchmark.cpp
@@ -92,7 +92,7 @@ BENCHMARK(BM_Mapper_Scale)->Range(10, 10000);
// --- Reducer Benchmarks ---
static void BM_SerializeFunctionInfo(benchmark::State &State) {
- auto I = allocatePtr<FunctionInfo>();
+ auto I = allocateTransient<FunctionInfo>();
I->Name = "f";
I->DefLoc = Location(0, 0, "test.cpp");
I->ReturnType = TypeInfo("void");
@@ -120,7 +120,7 @@ static void BM_MergeInfos_Scale(benchmark::State &State) {
SmallVector<Info *> Input;
Input.reserve(State.range(0));
for (int Idx = 0; Idx < State.range(0); ++Idx) {
- auto *I = allocatePtr<FunctionInfo>();
+ auto *I = allocateTransient<FunctionInfo>();
I->Name = "f";
I->USR = USR;
I->DefLoc = Location(10, Idx, "test.cpp");
@@ -181,7 +181,7 @@ static void BM_JSONGenerator_Scale(benchmark::State &State) {
return;
}
int NumRecords = State.range(0);
- auto NI = allocatePtr<NamespaceInfo>();
+ auto NI = allocateTransient<NamespaceInfo>();
NI->Name = "GlobalNamespace";
for (int i = 0; i < NumRecords; ++i) {
Reference *R = new (TransientArena.Allocate<Reference>())
More information about the llvm-branch-commits
mailing list