summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuanqi Xu <yedeng.yd@linux.alibaba.com>2024-04-28 17:50:49 +0800
committerChuanqi Xu <yedeng.yd@linux.alibaba.com>2024-04-28 18:31:10 +0800
commit367efa0b0542e6f4171e8c914728946c302ab24b (patch)
treecf4c28aa041ee4876b7d36a3626552777550ff21
parente3dea5e3410fd6a1e549cfa7021c4f8652b36095 (diff)
[NFC] [Modules] Avoid scanning the stored decl list twice when replace
external decls This patch fixes a FIXME in StoredDeclList::replaceExternalDecls. StoredDeclList::replaceExternalDecls will iterate the list first to remove some declarations and iterate the list again to get the tail of the list. It should be better to avoid the second iterations.
-rw-r--r--clang/include/clang/AST/DeclContextInternals.h31
1 files changed, 17 insertions, 14 deletions
diff --git a/clang/include/clang/AST/DeclContextInternals.h b/clang/include/clang/AST/DeclContextInternals.h
index 42cc677f8213..e169c4859219 100644
--- a/clang/include/clang/AST/DeclContextInternals.h
+++ b/clang/include/clang/AST/DeclContextInternals.h
@@ -42,11 +42,12 @@ class StoredDeclsList {
/// external declarations.
DeclsAndHasExternalTy Data;
- template<typename Fn>
- void erase_if(Fn ShouldErase) {
+ template <typename Fn> DeclListNode::Decls *erase_if(Fn ShouldErase) {
Decls List = Data.getPointer();
+
if (!List)
- return;
+ return nullptr;
+
ASTContext &C = getASTContext();
DeclListNode::Decls NewHead = nullptr;
DeclListNode::Decls *NewLast = nullptr;
@@ -79,6 +80,17 @@ class StoredDeclsList {
Data.setPointer(NewHead);
assert(llvm::none_of(getLookupResult(), ShouldErase) && "Still exists!");
+
+ if (!Data.getPointer())
+ // All declarations are erased.
+ return nullptr;
+ else if (NewHead.is<NamedDecl *>())
+ // The list only contains a declaration, the header itself.
+ return (DeclListNode::Decls *)&Data;
+ else {
+ assert(NewLast && NewLast->is<NamedDecl *>() && "Not the tail?");
+ return NewLast;
+ }
}
void erase(NamedDecl *ND) {
@@ -161,7 +173,7 @@ public:
void replaceExternalDecls(ArrayRef<NamedDecl*> Decls) {
// Remove all declarations that are either external or are replaced with
// external declarations with higher visibilities.
- erase_if([Decls](NamedDecl *ND) {
+ DeclListNode::Decls *Tail = erase_if([Decls](NamedDecl *ND) {
if (ND->isFromASTFile())
return true;
// FIXME: Can we get rid of this loop completely?
@@ -189,24 +201,15 @@ public:
DeclsAsList = Node;
}
- DeclListNode::Decls Head = Data.getPointer();
- if (Head.isNull()) {
+ if (!Data.getPointer()) {
Data.setPointer(DeclsAsList);
return;
}
- // Find the end of the existing list.
- // FIXME: It would be possible to preserve information from erase_if to
- // avoid this rescan looking for the end of the list.
- DeclListNode::Decls *Tail = &Head;
- while (DeclListNode *Node = Tail->dyn_cast<DeclListNode *>())
- Tail = &Node->Rest;
-
// Append the Decls.
DeclListNode *Node = C.AllocateDeclListNode(Tail->get<NamedDecl *>());
Node->Rest = DeclsAsList;
*Tail = Node;
- Data.setPointer(Head);
}
/// Return the list of all the decls.