[clang-tools-extra] [clang-doc] Wrap per thread arenas in an accessor for BUILD_SHARED (PR #201388)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 3 08:51:59 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tools-extra
Author: Paul Kirth (ilovepi)
<details>
<summary>Changes</summary>
It seems like for BUILD_SHARED builds of the toolchain on Windows,
specifically aarch64-windows-gnu hosts, the use of the `thread_local`
variables in Representation.cpp causes an issue at link time due to
non-explicit export. Instead, just wrap them in an accessor function,
which should solve the issue in a cross platform way.
Fixes #<!-- -->200915
---
Patch is 25.38 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/201388.diff
7 Files Affected:
- (modified) clang-tools-extra/clang-doc/BitcodeReader.cpp (+25-24)
- (modified) clang-tools-extra/clang-doc/Mapper.cpp (+1-1)
- (modified) clang-tools-extra/clang-doc/Representation.cpp (+24-16)
- (modified) clang-tools-extra/clang-doc/Representation.h (+10-9)
- (modified) clang-tools-extra/clang-doc/Serialize.cpp (+26-23)
- (modified) clang-tools-extra/clang-doc/tool/ClangDocMain.cpp (+3-2)
- (modified) clang-tools-extra/unittests/clang-doc/MergeTest.cpp (+4-2)
``````````diff
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp
index 95b3ce6843b1e..3299dedfbc3e4 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -569,13 +569,13 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I) {
[&]() -> llvm::Error {
if (!LocalChildren.empty())
I->Children =
- allocateArray<CommentInfo>(LocalChildren, TransientArena);
+ allocateArray<CommentInfo>(LocalChildren, getTransientArena());
if (!AttrKeys.empty())
- I->AttrKeys = allocateArray(AttrKeys, TransientArena);
+ I->AttrKeys = allocateArray(AttrKeys, getTransientArena());
if (!AttrValues.empty())
- I->AttrValues = allocateArray(AttrValues, TransientArena);
+ I->AttrValues = allocateArray(AttrValues, getTransientArena());
if (!Args.empty())
- I->Args = allocateArray(Args, TransientArena);
+ I->Args = allocateArray(Args, getTransientArena());
return llvm::Error::success();
},
@@ -608,9 +608,9 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FunctionInfo *I) {
return routeReferenceBlock(BlockOrCode, LocalNamespaces, I);
},
[&]() -> llvm::Error {
- I->Params = allocateArray(LocalParams, TransientArena);
+ I->Params = allocateArray(LocalParams, getTransientArena());
if (!LocalNamespaces.empty())
- I->Namespace = allocateArray(LocalNamespaces, TransientArena);
+ I->Namespace = allocateArray(LocalNamespaces, getTransientArena());
return llvm::Error::success();
});
}
@@ -632,9 +632,9 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, EnumInfo *I) {
return routeReferenceBlock(BlockOrCode, LocalNamespaces, I);
},
[&]() -> llvm::Error {
- I->Members = allocateArray(LocalMembers, TransientArena);
+ I->Members = allocateArray(LocalMembers, getTransientArena());
if (!LocalNamespaces.empty())
- I->Namespace = allocateArray(LocalNamespaces, TransientArena);
+ I->Namespace = allocateArray(LocalNamespaces, getTransientArena());
return llvm::Error::success();
});
}
@@ -679,14 +679,14 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, BaseRecordInfo *I) {
},
[&]() -> llvm::Error {
if (!LocalMembers.empty())
- I->Members = allocateArray(LocalMembers, TransientArena);
+ I->Members = allocateArray(LocalMembers, getTransientArena());
if (!LocalParents.empty())
- I->Parents = allocateArray(LocalParents, TransientArena);
+ I->Parents = allocateArray(LocalParents, getTransientArena());
if (!LocalVirtualParents.empty())
I->VirtualParents =
- allocateArray(LocalVirtualParents, TransientArena);
- I->Bases = allocateArray(LocalBases, TransientArena);
- I->Friends = allocateArray(LocalFriends, TransientArena);
+ allocateArray(LocalVirtualParents, getTransientArena());
+ I->Bases = allocateArray(LocalBases, getTransientArena());
+ I->Friends = allocateArray(LocalFriends, getTransientArena());
return llvm::Error::success();
});
}
@@ -730,16 +730,16 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, RecordInfo *I) {
},
[&]() -> llvm::Error {
if (!LocalMembers.empty())
- I->Members = allocateArray(LocalMembers, TransientArena);
+ I->Members = allocateArray(LocalMembers, getTransientArena());
if (!LocalParents.empty())
- I->Parents = allocateArray(LocalParents, TransientArena);
+ I->Parents = allocateArray(LocalParents, getTransientArena());
if (!LocalVirtualParents.empty())
I->VirtualParents =
- allocateArray(LocalVirtualParents, TransientArena);
+ allocateArray(LocalVirtualParents, getTransientArena());
if (!LocalNamespaces.empty())
- I->Namespace = allocateArray(LocalNamespaces, TransientArena);
- I->Bases = allocateArray(LocalBases, TransientArena);
- I->Friends = allocateArray(LocalFriends, TransientArena);
+ I->Namespace = allocateArray(LocalNamespaces, getTransientArena());
+ I->Bases = allocateArray(LocalBases, getTransientArena());
+ I->Friends = allocateArray(LocalFriends, getTransientArena());
return llvm::Error::success();
});
}
@@ -769,8 +769,8 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TemplateInfo *I) {
return false;
},
[&]() -> llvm::Error {
- I->Params = allocateArray(LocalParams, TransientArena);
- I->Constraints = allocateArray(LocalConstraints, TransientArena);
+ I->Params = allocateArray(LocalParams, getTransientArena());
+ I->Constraints = allocateArray(LocalConstraints, getTransientArena());
return llvm::Error::success();
},
[&](unsigned BlockOrCode) -> llvm::Error {
@@ -796,7 +796,7 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID,
return false;
},
[&]() -> llvm::Error {
- I->Params = allocateArray(LocalParams, TransientArena);
+ I->Params = allocateArray(LocalParams, getTransientArena());
return llvm::Error::success();
},
[&](unsigned BlockOrCode) -> llvm::Error {
@@ -1221,7 +1221,7 @@ llvm::Error ClangDocBitcodeReader::readBlockWithNamespace(unsigned ID, T I) {
},
[&]() -> llvm::Error {
if (!LocalNamespaces.empty())
- I->Namespace = allocateArray(LocalNamespaces, TransientArena);
+ I->Namespace = allocateArray(LocalNamespaces, getTransientArena());
return llvm::Error::success();
});
}
@@ -1254,7 +1254,8 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FriendInfo *I) {
},
[&]() -> llvm::Error {
if (!LocalParams.empty())
- I->Params = allocateArray<FieldTypeInfo>(LocalParams, TransientArena);
+ I->Params =
+ allocateArray<FieldTypeInfo>(LocalParams, getTransientArena());
return llvm::Error::success();
},
[&](unsigned BlockOrCode) -> llvm::Error {
diff --git a/clang-tools-extra/clang-doc/Mapper.cpp b/clang-tools-extra/clang-doc/Mapper.cpp
index 3c4c17e2b0279..911d97ba89c2e 100644
--- a/clang-tools-extra/clang-doc/Mapper.cpp
+++ b/clang-tools-extra/clang-doc/Mapper.cpp
@@ -44,7 +44,7 @@ void MapASTVisitor::HandleTranslationUnit(ASTContext &Context) {
llvm::timeTraceProfilerInitialize(200, "clang-doc");
TraverseDecl(Context.getTranslationUnitDecl());
- TransientArena.Reset();
+ getTransientArena().Reset();
if (CDCtx.FTimeTrace)
llvm::timeTraceProfilerFinishThread();
diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp
index ea4f35f7bb2f5..bfa1150f9bc35 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -29,8 +29,15 @@ namespace clang {
namespace doc {
// Thread local arenas usable in each thread pool
-thread_local llvm::BumpPtrAllocator TransientArena;
-thread_local llvm::BumpPtrAllocator PersistentArena;
+llvm::BumpPtrAllocator &getTransientArena() {
+ thread_local llvm::BumpPtrAllocator TransientArena;
+ return TransientArena;
+}
+
+llvm::BumpPtrAllocator &getPersistentArena() {
+ thread_local llvm::BumpPtrAllocator PersistentArena;
+ return PersistentArena;
+}
ConcurrentStringPool &getGlobalStringPool() {
static ConcurrentStringPool GlobalPool;
@@ -168,7 +175,7 @@ void mergeUnkeyed<CommentInfo>(DocList<CommentInfo> &Target,
if (llvm::none_of(Target,
[Ptr](const auto &E) { return *E.Ptr == *Ptr; })) {
Target.push_back(
- *allocateListNodePersistent<CommentInfo>(*Ptr, PersistentArena));
+ *allocateListNodePersistent<CommentInfo>(*Ptr, getPersistentArena()));
}
}
}
@@ -461,7 +468,7 @@ void Info::mergeBase(Info &&Other) {
if (Path == "")
Path = Other.Path;
if (Namespace.empty() && !Other.Namespace.empty())
- Namespace = allocateArray(Other.Namespace, PersistentArena);
+ Namespace = allocateArray(Other.Namespace, getPersistentArena());
// Unconditionally extend the description, since each decl may have a comment.
mergeUnkeyed(Description, std::move(Other.Description));
if (ParentUSR == EmptySID)
@@ -549,22 +556,22 @@ void RecordInfo::merge(RecordInfo &&Other) {
TagType = Other.TagType;
IsTypeDef = IsTypeDef || Other.IsTypeDef;
if (Members.empty() && !Other.Members.empty())
- Members = deepCopyArray(Other.Members, PersistentArena);
+ Members = deepCopyArray(Other.Members, getPersistentArena());
if (Bases.empty() && !Other.Bases.empty())
- Bases = deepCopyArray(Other.Bases, PersistentArena);
+ Bases = deepCopyArray(Other.Bases, getPersistentArena());
if (Parents.empty() && !Other.Parents.empty())
- Parents = allocateArray(Other.Parents, PersistentArena);
+ Parents = allocateArray(Other.Parents, getPersistentArena());
if (VirtualParents.empty() && !Other.VirtualParents.empty())
- VirtualParents = allocateArray(Other.VirtualParents, PersistentArena);
+ VirtualParents = allocateArray(Other.VirtualParents, getPersistentArena());
if (Friends.empty() && !Other.Friends.empty())
- Friends = deepCopyArray(Other.Friends, PersistentArena);
+ Friends = deepCopyArray(Other.Friends, getPersistentArena());
// Reduce children if necessary.
reduceChildren(Children.Records, std::move(Other.Children.Records));
reduceChildren(Children.Functions, std::move(Other.Children.Functions));
reduceChildren(Children.Enums, std::move(Other.Children.Enums));
reduceChildren(Children.Typedefs, std::move(Other.Children.Typedefs));
if (!Template && Other.Template)
- Template = TemplateInfo(*Other.Template, PersistentArena);
+ Template = TemplateInfo(*Other.Template, getPersistentArena());
SymbolInfo::merge(std::move(Other));
}
@@ -586,7 +593,7 @@ void EnumInfo::merge(EnumInfo &&Other) {
if (!BaseType && Other.BaseType)
BaseType = std::move(Other.BaseType);
if (Members.empty() && !Other.Members.empty())
- Members = deepCopyArray(Other.Members, PersistentArena);
+ Members = deepCopyArray(Other.Members, getPersistentArena());
SymbolInfo::merge(std::move(Other));
}
@@ -601,9 +608,9 @@ void FunctionInfo::merge(FunctionInfo &&Other) {
if (Parent.USR == EmptySID && Parent.Name == "")
Parent = std::move(Other.Parent);
if (Params.empty() && !Other.Params.empty())
- Params = allocateArray(Other.Params, PersistentArena);
+ Params = allocateArray(Other.Params, getPersistentArena());
if (!Template && Other.Template)
- Template = TemplateInfo(*Other.Template, PersistentArena);
+ Template = TemplateInfo(*Other.Template, getPersistentArena());
SymbolInfo::merge(std::move(Other));
}
@@ -614,7 +621,7 @@ void TypedefInfo::merge(TypedefInfo &&Other) {
if (Underlying.Type.Name == "")
Underlying = Other.Underlying;
if (!Template && Other.Template)
- Template = TemplateInfo(*Other.Template, PersistentArena);
+ Template = TemplateInfo(*Other.Template, getPersistentArena());
SymbolInfo::merge(std::move(Other));
}
@@ -626,9 +633,10 @@ void ConceptInfo::merge(ConceptInfo &&Other) {
ConstraintExpression = std::move(Other.ConstraintExpression);
if (Template.Constraints.empty() && !Other.Template.Constraints.empty())
Template.Constraints =
- allocateArray(Other.Template.Constraints, PersistentArena);
+ allocateArray(Other.Template.Constraints, getPersistentArena());
if (Template.Params.empty() && !Other.Template.Params.empty())
- Template.Params = allocateArray(Other.Template.Params, PersistentArena);
+ Template.Params =
+ allocateArray(Other.Template.Params, getPersistentArena());
SymbolInfo::merge(std::move(Other));
}
diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h
index 5e30264cd0303..ef71c8327bf4c 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -51,8 +51,8 @@ class ConcurrentStringPool {
ConcurrentStringPool &getGlobalStringPool();
-extern thread_local llvm::BumpPtrAllocator TransientArena;
-extern thread_local llvm::BumpPtrAllocator PersistentArena;
+llvm::BumpPtrAllocator &getTransientArena();
+llvm::BumpPtrAllocator &getPersistentArena();
inline StringRef internString(const Twine &T) {
if (T.isTriviallyEmpty())
@@ -107,12 +107,13 @@ llvm::ArrayRef<T> deepCopyArray(llvm::ArrayRef<T> V,
// A helper function to create an owned pointer, abstracting away the memory
// allocation mechanism.
template <typename T, typename... Args> T *allocateTransient(Args &&...args) {
- return new (TransientArena.Allocate<T>()) T(std::forward<Args>(args)...);
+ return new (getTransientArena().Allocate<T>()) T(std::forward<Args>(args)...);
}
-// A helper function to create memory allocated in the TransientArena.
+// A helper function to create memory allocated in the getTransientArena().
template <typename T, typename... Args> T *allocatePersistent(Args &&...args) {
- return new (PersistentArena.Allocate<T>()) T(std::forward<Args>(args)...);
+ return new (getPersistentArena().Allocate<T>())
+ T(std::forward<Args>(args)...);
}
// An overload to explicitly allocate on an arena, returning a bare pointer.
@@ -156,7 +157,7 @@ InfoNode<T> *allocateListNode(llvm::BumpPtrAllocator &Alloc, Args &&...args) {
template <typename T, typename... Args>
InfoNode<T> *allocateListNodeTransient(Args &&...args) {
- return allocateListNode<T>(TransientArena, std::forward<Args>(args)...);
+ return allocateListNode<T>(getTransientArena(), std::forward<Args>(args)...);
}
template <typename T>
@@ -165,16 +166,16 @@ InfoNode<T> *allocateListNode(llvm::BumpPtrAllocator &Alloc, T *Item) {
}
template <typename T> InfoNode<T> *allocateListNodeTransient(T *Item) {
- return allocateListNode<T>(TransientArena, Item);
+ return allocateListNode<T>(getTransientArena(), Item);
}
template <typename T, typename... Args>
InfoNode<T> *allocateListNodePersistent(Args &&...args) {
- return allocateListNode<T>(PersistentArena, std::forward<Args>(args)...);
+ return allocateListNode<T>(getPersistentArena(), std::forward<Args>(args)...);
}
template <typename T> InfoNode<T> *allocateListNodePersistent(T *Item) {
- return allocateListNode<T>(PersistentArena, Item);
+ return allocateListNode<T>(getPersistentArena(), Item);
}
// An abstraction for lists that are dynamically managed (inserted/removed).
diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp
index ed850e04fc258..c7481fa5bada6 100644
--- a/clang-tools-extra/clang-doc/Serialize.cpp
+++ b/clang-tools-extra/clang-doc/Serialize.cpp
@@ -230,7 +230,7 @@ void ClangDocCommentVisitor::parseComment(const comments::Comment *C) {
unsigned NumChildren = C->child_count();
if (NumChildren > 0) {
CommentInfo *ChildrenArray =
- TransientArena.Allocate<CommentInfo>(NumChildren);
+ getTransientArena().Allocate<CommentInfo>(NumChildren);
unsigned Idx = 0;
for (comments::Comment *Child :
llvm::make_range(C->child_begin(), C->child_end())) {
@@ -258,7 +258,7 @@ void ClangDocCommentVisitor::visitInlineCommandComment(
for (unsigned I = 0, E = C->getNumArgs(); I != E; ++I)
Args.push_back(internString(C->getArgText(I).trim()));
if (!Args.empty()) {
- CurrentCI.Args = allocateArray(Args, TransientArena);
+ CurrentCI.Args = allocateArray(Args, getTransientArena());
}
}
@@ -274,10 +274,10 @@ void ClangDocCommentVisitor::visitHTMLStartTagComment(
AttrValues.push_back(internString(Attr.Value));
}
if (!AttrKeys.empty()) {
- CurrentCI.AttrKeys = allocateArray(AttrKeys, TransientArena);
+ CurrentCI.AttrKeys = allocateArray(AttrKeys, getTransientArena());
}
if (!AttrValues.empty()) {
- CurrentCI.AttrValues = allocateArray(AttrValues, TransientArena);
+ CurrentCI.AttrValues = allocateArray(AttrValues, getTransientArena());
}
}
@@ -294,7 +294,7 @@ void ClangDocCommentVisitor::visitBlockCommandComment(
for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
Args.push_back(internString(C->getArgText(I).trim()));
if (!Args.empty()) {
- CurrentCI.Args = allocateArray(Args, TransientArena);
+ CurrentCI.Args = allocateArray(Args, getTransientArena());
}
}
@@ -579,7 +579,7 @@ void Serializer::parseFields(RecordInfo &I, const RecordDecl *D,
const auto *CxxRD = dyn_cast<CXXRecordDecl>(D);
if (!CxxRD) {
if (!Members.empty())
- I.Members = allocateArray<MemberTypeInfo>(Members, TransientArena);
+ I.Members = allocateArray<MemberTypeInfo>(Members, getTransientArena());
return;
}
for (Decl *CxxDecl : CxxRD->decls()) {
@@ -592,7 +592,7 @@ void Serializer::parseFields(RecordInfo &I, const RecordDecl *D,
populateMemberTypeInfo(Members, Access, VD, /*IsStatic=*/true);
}
if (!Members.empty())
- I.Members = allocateArray<MemberTypeInfo>(Members, TransientArena);
+ I.Members = allocateArray<MemberTypeInfo>(Members, getTransientArena());
}
void Serializer::parseEnumerators(EnumInfo &I, const EnumDecl *D) {
@@ -616,7 +616,7 @@ void Serializer::parseEnumerators(EnumInfo &I, const EnumDecl *D) {
}
}
if (!LocalMembers.empty())
- I.Members = allocateArray<EnumValueInfo>(LocalMembers, TransientArena);
+ I.Members = allocateArray<EnumValueInfo>(LocalMembers, getTransientArena());
}
void Serializer::parseParameters(FunctionInfo &I, const FunctionDecl *D) {
@@ -630,7 +630,7 @@ void Serializer::parseParameters(FunctionInfo &I, const FunctionDecl *D) {
FieldInfo.DefaultValue = *DefaultValue;
}
if (!LocalParams.empty())
- I.Params = allocateArray<FieldTypeInfo>(LocalParams, TransientArena);
+ I.Params = allocateArray<FieldTypeInfo>(LocalParams, getTransientArena());
}
// TODO: Remove the serialization of Parents and VirtualParents, this
@@ -656,7 +656,7 @@ void Serializer::parseBases(RecordInfo &I, const CXXRecordDecl *D) {
LocalParents.emplace_back(SymbolID(), B.getType().getAsString());
}
if (!LocalParents.empty())
- I.Parents = allocateArray<Reference>(LocalParents, TransientArena);
+ I.Parents = allocateArray<Reference>(LocalParents, getTransientArena());
llvm::SmallVector<Reference, 4> LocalVirtualParents;
for (const CXXBaseSpecifier &B : D->vbases()) {
@@ -669,7 +669,7 @@ void Serializer::parseBases(RecordInfo &I, const CXXRecordDecl *D) {
}
if (!LocalVirtualParents.empty())
I.VirtualParents =
- allocateArray<Reference>(LocalVirtualParents, TransientArena);
+ allocateArray<Reference>(LocalVirtualParents, getTransientArena());
}
template <typename T>
@@ -723,7 +723,7 @@ void Serializer::populateTemplateParameters(
}
if (!LocalParams.empty())
TemplateInfo->Params =
- allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
+ allocateArray<TemplateParamInfo>(LocalParams, getTransientArena());
}
}
@@ -789,7 +789,8 @@ void Serializer::populateInfo(Info &I, const T *D, const FullComment *C,
llvm::SmallVector<Reference, 4> LocalNamespaces;
populateParentNamespaces(LocalNamespaces, D, IsInAnonymousNamespace);
if (!LocalNamespaces.empty())
- I.Namespace = allocateArray<Reference>(LocalNamespaces, TransientArena);
+ I.Namespace =
+ allocateArray<Reference>(LocalNamespaces, getTransientArena());
if (C) {
auto *NewCI = allocateListNodeTransient<CommentInfo>();
@@ -873,7 +874,7 @@ void Serializer::populateConstraints(TemplateInfo &I, const TemplateDecl *D) {
}
if (!LocalConstraints.empty())
I.Constraints =
- allocateArray<ConstraintInfo>(LocalConstraints, TransientArena);
+ allocateArray<ConstraintInfo>(LocalConstraints, getTransientArena());
}
void Serializer::populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
@@ -908,7 +909,7 @@ void Serializer::populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
}
if (!LocalParams.empty())
Specialization.Params =
- ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/201388
More information about the cfe-commits
mailing list