diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1421,19 +1421,48 @@ class GlobalMethodPool { public: + GlobalMethodPool(Sema &S) : SemaRef(S) {} + GlobalMethodPool() = delete; using Lists = std::pair; using iterator = llvm::DenseMap::iterator; iterator begin() { return Methods.begin(); } iterator end() { return Methods.end(); } iterator find(Selector Sel) { return Methods.find(Sel); } - std::pair insert(std::pair &&Val) { - return Methods.insert(Val); - } int count(Selector Sel) const { return Methods.count(Sel); } bool empty() const { return Methods.empty(); } + void addMethodsForSelector(Selector Sel, ArrayRef Decls, + bool Instance, unsigned Bits, + bool HasMoreThanOneDecl) { + auto Pos = Methods.insert(std::make_pair(Sel, Lists())).first; + auto &List = Instance ? Pos->second.first : Pos->second.second; + List.setBits(Bits); + List.setHasMoreThanOneDecl(HasMoreThanOneDecl); + + // Add methods to the global list *after* setting hasMoreThanOneDecl, + // since when building a module we keep every method individually and may + // need to update hasMoreThanOneDecl as we add the methods. + for (auto *D : Decls) { + addMethodToGlobalList(&List, D); + } + } + + void addMethod(ObjCMethodDecl *Method) { + auto Pos = Methods.find(Method->getSelector()); + if (Pos == Methods.end()) { + Pos = Methods.insert(std::make_pair(Method->getSelector(), Lists())) + .first; + } + + auto &List = + Method->isInstanceMethod() ? Pos->second.first : Pos->second.second; + addMethodToGlobalList(&List, Method); + } + private: + Sema &SemaRef; llvm::DenseMap Methods; + void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method); }; /// Method Pool - allows efficient lookup when typechecking messages to "id". @@ -4505,9 +4534,6 @@ /// warns each time an exact match is found. void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP); - /// Add the given method to the list of globally-known methods. - void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method); - /// Returns default addr space for method qualifiers. LangAS getDefaultCXXMethodAddrSpace() const; diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -196,7 +196,7 @@ ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false), - TUKind(TUKind), NumSFINAEErrors(0), + TUKind(TUKind), NumSFINAEErrors(0), MethodPool(*this), FullyCheckedComparisonCategories( static_cast(ComparisonCategoryType::Last) + 1), SatisfactionCache(Context), AccessCheckingSFINAE(false), diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -3300,8 +3300,8 @@ return MethodInterface == MethodInListInterface; } -void Sema::addMethodToGlobalList(ObjCMethodList *List, - ObjCMethodDecl *Method) { +void Sema::GlobalMethodPool::addMethodToGlobalList(ObjCMethodList *List, + ObjCMethodDecl *Method) { // Record at the head of the list whether there were 0, 1, or >= 2 methods // inside categories. if (ObjCCategoryDecl *CD = @@ -3322,11 +3322,11 @@ ObjCMethodList *ListWithSameDeclaration = nullptr; for (; List; Previous = List, List = List->getNext()) { // If we are building a module, keep all of the methods. - if (getLangOpts().isCompilingModule()) + if (SemaRef.getLangOpts().isCompilingModule()) continue; - bool SameDeclaration = MatchTwoMethodDeclarations(Method, - List->getMethod()); + bool SameDeclaration = + SemaRef.MatchTwoMethodDeclarations(Method, List->getMethod()); // Looking for method with a type bound requires the correct context exists. // We need to insert a method into the list if the context is different. // If the method's declaration matches the list @@ -3389,7 +3389,7 @@ // We have a new signature for an existing method - add it. // This is extremely rare. Only 1% of Cocoa selectors are "overloaded". - ObjCMethodList *Mem = BumpAlloc.Allocate(); + ObjCMethodList *Mem = SemaRef.BumpAlloc.Allocate(); // We insert it right before ListWithSameDeclaration. if (ListWithSameDeclaration) { @@ -3425,17 +3425,9 @@ if (ExternalSource) ReadMethodPool(Method->getSelector()); - GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector()); - if (Pos == MethodPool.end()) - Pos = MethodPool - .insert(std::make_pair(Method->getSelector(), - GlobalMethodPool::Lists())) - .first; - Method->setDefined(impl); - - ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second; - addMethodToGlobalList(&Entry, Method); + assert(Method->isInstanceMethod() == instance); + MethodPool.addMethod(Method); } /// Determines if this is an "acceptable" loose mismatch in the global diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -8178,14 +8178,6 @@ } // namespace serialization } // namespace clang -/// Add the given set of methods to the method list. -static void addMethodsToPool(Sema &S, ArrayRef Methods, - ObjCMethodList &List) { - for (unsigned I = 0, N = Methods.size(); I != N; ++I) { - S.addMethodToGlobalList(&List, Methods[I]); - } -} - void ASTReader::ReadMethodPool(Selector Sel) { // Get the selector generation and update it to the current generation. unsigned &Generation = SelectorGeneration[Sel]; @@ -8208,20 +8200,12 @@ return; Sema &S = *getSema(); - Sema::GlobalMethodPool::iterator Pos = - S.MethodPool.insert(std::make_pair(Sel, Sema::GlobalMethodPool::Lists())) - .first; - - Pos->second.first.setBits(Visitor.getInstanceBits()); - Pos->second.first.setHasMoreThanOneDecl(Visitor.instanceHasMoreThanOneDecl()); - Pos->second.second.setBits(Visitor.getFactoryBits()); - Pos->second.second.setHasMoreThanOneDecl(Visitor.factoryHasMoreThanOneDecl()); - - // Add methods to the global pool *after* setting hasMoreThanOneDecl, since - // when building a module we keep every method individually and may need to - // update hasMoreThanOneDecl as we add the methods. - addMethodsToPool(S, Visitor.getInstanceMethods(), Pos->second.first); - addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second); + S.MethodPool.addMethodsForSelector(Sel, Visitor.getInstanceMethods(), true, + Visitor.getInstanceBits(), + Visitor.instanceHasMoreThanOneDecl()); + S.MethodPool.addMethodsForSelector(Sel, Visitor.getFactoryMethods(), false, + Visitor.getFactoryBits(), + Visitor.factoryHasMoreThanOneDecl()); } void ASTReader::updateOutOfDateSelector(Selector Sel) {