diff options
author | Chuanqi Xu <yedeng.yd@linux.alibaba.com> | 2024-04-28 17:50:49 +0800 |
---|---|---|
committer | Chuanqi Xu <yedeng.yd@linux.alibaba.com> | 2024-04-28 18:31:10 +0800 |
commit | 367efa0b0542e6f4171e8c914728946c302ab24b (patch) | |
tree | cf4c28aa041ee4876b7d36a3626552777550ff21 | |
parent | e3dea5e3410fd6a1e549cfa7021c4f8652b36095 (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.h | 31 |
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. |