diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2010-08-02 23:18:59 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2010-08-02 23:18:59 +0000 |
commit | db9d2145f1d85f64dba2c9b92416621ce01090a6 (patch) | |
tree | 39357e18129698727f20fbaff48fb840adf8f15d | |
parent | f8dcf1a1d3c4f28fc96a45d7159e1a9c95484632 (diff) |
Simplify global method pool implementation in Sema. No functionality change.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110078 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 43 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 47 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 55 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 170 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 2 |
5 files changed, 110 insertions, 207 deletions
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 641492ca59..971f5e8fb2 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1654,50 +1654,17 @@ void PCHWriter::WriteMethodPool(Sema &SemaRef) { OnDiskChainedHashTableGenerator<PCHMethodPoolTrait> Generator; // Create the on-disk hash table representation. Start by - // iterating through the instance method pool. + // iterating through the method pool. PCHMethodPoolTrait::key_type Key; unsigned NumSelectorsInMethodPool = 0; - for (llvm::DenseMap<Selector, ObjCMethodList>::iterator - Instance = SemaRef.InstanceMethodPool.begin(), - InstanceEnd = SemaRef.InstanceMethodPool.end(); - Instance != InstanceEnd; ++Instance) { - // Check whether there is a factory method with the same - // selector. - llvm::DenseMap<Selector, ObjCMethodList>::iterator Factory - = SemaRef.FactoryMethodPool.find(Instance->first); - - if (Factory == SemaRef.FactoryMethodPool.end()) - Generator.insert(Instance->first, - std::make_pair(Instance->second, - ObjCMethodList())); - else - Generator.insert(Instance->first, - std::make_pair(Instance->second, Factory->second)); - + for (Sema::GlobalMethodPool::iterator I = SemaRef.MethodPool.begin(), + E = SemaRef.MethodPool.end(); + I != E; ++I) { + Generator.insert(I->first, I->second); ++NumSelectorsInMethodPool; Empty = false; } - // Now iterate through the factory method pool, to pick up any - // selectors that weren't already in the instance method pool. - for (llvm::DenseMap<Selector, ObjCMethodList>::iterator - Factory = SemaRef.FactoryMethodPool.begin(), - FactoryEnd = SemaRef.FactoryMethodPool.end(); - Factory != FactoryEnd; ++Factory) { - // Check whether there is an instance method with the same - // selector. If so, there is no work to do here. - llvm::DenseMap<Selector, ObjCMethodList>::iterator Instance - = SemaRef.InstanceMethodPool.find(Factory->first); - - if (Instance == SemaRef.InstanceMethodPool.end()) { - Generator.insert(Factory->first, - std::make_pair(ObjCMethodList(), Factory->second)); - ++NumSelectorsInMethodPool; - } - - Empty = false; - } - if (Empty && SelectorOffsets.empty()) return; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 85627b02b9..134596096d 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -609,21 +609,21 @@ public: /// \brief The number of SFINAE diagnostics that have been trapped. unsigned NumSFINAEErrors; - typedef llvm::DenseMap<Selector, ObjCMethodList> MethodPool; + typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods; + typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool; - /// Instance/Factory Method Pools - allows efficient lookup when typechecking - /// messages to "id". We need to maintain a list, since selectors can have - /// differing signatures across classes. In Cocoa, this happens to be - /// extremely uncommon (only 1% of selectors are "overloaded"). - MethodPool InstanceMethodPool; - MethodPool FactoryMethodPool; + /// Method Pool - allows efficient lookup when typechecking messages to "id". + /// We need to maintain a list, since selectors can have differing signatures + /// across classes. In Cocoa, this happens to be extremely uncommon (only 1% + /// of selectors are "overloaded"). + GlobalMethodPool MethodPool; /// Method selectors used in a @selector expression. Used for implementation /// of -Wselector. llvm::DenseMap<Selector, SourceLocation> ReferencedSelectors; - MethodPool::iterator ReadMethodPool(Selector Sel, bool isInstance); + GlobalMethodPool::iterator ReadMethodPool(Selector Sel); /// Private Helper predicate to check for 'self'. bool isSelfExpr(Expr *RExpr); @@ -1686,29 +1686,48 @@ public: bool &IncompleteImpl, bool ImmediateClass); +private: + /// AddMethodToGlobalPool - Add an instance or factory method to the global + /// pool. See descriptoin of AddInstanceMethodToGlobalPool. + void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance); + + /// LookupMethodInGlobalPool - Returns the instance or factory method and + /// optionally warns if there are multiple signatures. + ObjCMethodDecl *LookupMethodInGlobalPool(Selector Sel, SourceRange R, + bool warn, bool instance); + +public: /// AddInstanceMethodToGlobalPool - All instance methods in a translation /// unit are added to a global pool. This allows us to efficiently associate /// a selector with a method declaraation for purposes of typechecking /// messages sent to "id" (where the class of the object is unknown). - void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false); + void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) { + AddMethodToGlobalPool(Method, impl, /*instance*/true); + } + + /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods. + void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) { + AddMethodToGlobalPool(Method, impl, /*instance*/false); + } /// LookupInstanceMethodInGlobalPool - Returns the method and warns if /// there are multiple signatures. ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R, - bool warn=true); + bool warn=true) { + return LookupMethodInGlobalPool(Sel, R, warn, /*instance*/true); + } /// LookupFactoryMethodInGlobalPool - Returns the method and warns if /// there are multiple signatures. ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R, - bool warn=true); + bool warn=true) { + return LookupMethodInGlobalPool(Sel, R, warn, /*instance*/false); + } /// LookupImplementedMethodInGlobalPool - Returns the method which has an /// implementation. ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel); - /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods. - void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false); - /// CollectIvarsToConstructOrDestruct - Collect those ivars which require /// initialization. void CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI, diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index bc0335556f..476c79cc37 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -3547,20 +3547,18 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; ++I) { Selector Sel = ExternalSource->GetExternalSelector(I); - if (Sel.isNull() || FactoryMethodPool.count(Sel) || - InstanceMethodPool.count(Sel)) + if (Sel.isNull() || MethodPool.count(Sel)) continue; - ReadMethodPool(Sel, /*isInstance=*/false); + ReadMethodPool(Sel); } } - for (llvm::DenseMap<Selector, ObjCMethodList>::iterator - M = FactoryMethodPool.begin(), - MEnd = FactoryMethodPool.end(); - M != MEnd; - ++M) { - for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method; + for (GlobalMethodPool::iterator M = MethodPool.begin(), + MEnd = MethodPool.end(); + M != MEnd; ++M) { + for (ObjCMethodList *MethList = &M->second.second; + MethList && MethList->Method; MethList = MethList->Next) { if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, NumSelIdents)) @@ -3648,20 +3646,18 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; ++I) { Selector Sel = ExternalSource->GetExternalSelector(I); - if (Sel.isNull() || InstanceMethodPool.count(Sel) || - FactoryMethodPool.count(Sel)) + if (Sel.isNull() || MethodPool.count(Sel)) continue; - ReadMethodPool(Sel, /*isInstance=*/true); + ReadMethodPool(Sel); } } - for (llvm::DenseMap<Selector, ObjCMethodList>::iterator - M = InstanceMethodPool.begin(), - MEnd = InstanceMethodPool.end(); - M != MEnd; - ++M) { - for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method; + for (GlobalMethodPool::iterator M = MethodPool.begin(), + MEnd = MethodPool.end(); + M != MEnd; ++M) { + for (ObjCMethodList *MethList = &M->second.first; + MethList && MethList->Method; MethList = MethList->Next) { if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, NumSelIdents)) @@ -4174,20 +4170,16 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, TypeTy *ReturnTy, IdentifierInfo **SelIdents, unsigned NumSelIdents) { - llvm::DenseMap<Selector, ObjCMethodList> &Pool - = IsInstanceMethod? InstanceMethodPool : FactoryMethodPool; - // If we have an external source, load the entire class method // pool from the PCH file. if (ExternalSource) { for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; ++I) { Selector Sel = ExternalSource->GetExternalSelector(I); - if (Sel.isNull() || InstanceMethodPool.count(Sel) || - FactoryMethodPool.count(Sel)) + if (Sel.isNull() || MethodPool.count(Sel)) continue; - - ReadMethodPool(Sel, IsInstanceMethod); + + ReadMethodPool(Sel); } } @@ -4197,13 +4189,14 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, if (ReturnTy) Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType()); - + Results.EnterNewScope(); - for (llvm::DenseMap<Selector, ObjCMethodList>::iterator M = Pool.begin(), - MEnd = Pool.end(); - M != MEnd; - ++M) { - for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method; + for (GlobalMethodPool::iterator M = MethodPool.begin(), + MEnd = MethodPool.end(); + M != MEnd; ++M) { + for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first : + &M->second.second; + MethList && MethList->Method; MethList = MethList->Next) { if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, NumSelIdents)) diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 8f3ff5ddd0..06f3642c27 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1100,47 +1100,34 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, return true; } -/// \brief Read the contents of the instance and factory method pools -/// for a given selector from external storage. +/// \brief Read the contents of the method pool for a given selector from +/// external storage. /// -/// This routine should only be called once, when neither the instance -/// nor the factory method pool has an entry for this selector. -Sema::MethodPool::iterator Sema::ReadMethodPool(Selector Sel, - bool isInstance) { +/// This routine should only be called once, when the method pool has no entry +/// for this selector. +Sema::GlobalMethodPool::iterator Sema::ReadMethodPool(Selector Sel) { assert(ExternalSource && "We need an external AST source"); - assert(InstanceMethodPool.find(Sel) == InstanceMethodPool.end() && - "Selector data already loaded into the instance method pool"); - assert(FactoryMethodPool.find(Sel) == FactoryMethodPool.end() && - "Selector data already loaded into the factory method pool"); + assert(MethodPool.find(Sel) == MethodPool.end() && + "Selector data already loaded into the method pool"); // Read the method list from the external source. - std::pair<ObjCMethodList, ObjCMethodList> Methods - = ExternalSource->ReadMethodPool(Sel); + GlobalMethods Methods = ExternalSource->ReadMethodPool(Sel); - if (isInstance) { - if (Methods.second.Method) - FactoryMethodPool[Sel] = Methods.second; - return InstanceMethodPool.insert(std::make_pair(Sel, Methods.first)).first; - } - - if (Methods.first.Method) - InstanceMethodPool[Sel] = Methods.first; - - return FactoryMethodPool.insert(std::make_pair(Sel, Methods.second)).first; + return MethodPool.insert(std::make_pair(Sel, Methods)).first; } -void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl) { - llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos - = InstanceMethodPool.find(Method->getSelector()); - if (Pos == InstanceMethodPool.end()) { - if (ExternalSource && !FactoryMethodPool.count(Method->getSelector())) - Pos = ReadMethodPool(Method->getSelector(), /*isInstance=*/true); +void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, + bool instance) { + GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector()); + if (Pos == MethodPool.end()) { + if (ExternalSource) + Pos = ReadMethodPool(Method->getSelector()); else - Pos = InstanceMethodPool.insert(std::make_pair(Method->getSelector(), - ObjCMethodList())).first; + Pos = MethodPool.insert(std::make_pair(Method->getSelector(), + GlobalMethods())).first; } Method->setDefined(impl); - ObjCMethodList &Entry = Pos->second; + ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second; if (Entry.Method == 0) { // Haven't seen a method with this selector name yet - add it. Entry.Method = Method; @@ -1163,111 +1150,48 @@ void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl) { } // FIXME: Finish implementing -Wno-strict-selector-match. -ObjCMethodDecl *Sema::LookupInstanceMethodInGlobalPool(Selector Sel, - SourceRange R, - bool warn) { - llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos - = InstanceMethodPool.find(Sel); - if (Pos == InstanceMethodPool.end()) { - if (ExternalSource && !FactoryMethodPool.count(Sel)) - Pos = ReadMethodPool(Sel, /*isInstance=*/true); +ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, + bool warn, bool instance) { + GlobalMethodPool::iterator Pos = MethodPool.find(Sel); + if (Pos == MethodPool.end()) { + if (ExternalSource) + Pos = ReadMethodPool(Sel); else return 0; } - ObjCMethodList &MethList = Pos->second; - bool issueWarning = false; + ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; - if (MethList.Method && MethList.Next) { - for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) + if (warn && MethList.Method && MethList.Next) { + bool issueWarning = false; + for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) { // This checks if the methods differ by size & alignment. if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true)) - issueWarning = warn; - } - if (issueWarning && (MethList.Method && MethList.Next)) { - Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; - Diag(MethList.Method->getLocStart(), diag::note_using) - << MethList.Method->getSourceRange(); - for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) - Diag(Next->Method->getLocStart(), diag::note_also_found) - << Next->Method->getSourceRange(); - } - return MethList.Method; -} - -void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl) { - llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos - = FactoryMethodPool.find(Method->getSelector()); - if (Pos == FactoryMethodPool.end()) { - if (ExternalSource && !InstanceMethodPool.count(Method->getSelector())) - Pos = ReadMethodPool(Method->getSelector(), /*isInstance=*/false); - else - Pos = FactoryMethodPool.insert(std::make_pair(Method->getSelector(), - ObjCMethodList())).first; - } - Method->setDefined(impl); - ObjCMethodList &Entry = Pos->second; - if (!Entry.Method) { - // Haven't seen a method with this selector name yet - add it. - Entry.Method = Method; - Entry.Next = 0; - return; - } - // We've seen a method with this name, see if we have already seen this type - // signature. - for (ObjCMethodList *List = &Entry; List; List = List->Next) - if (MatchTwoMethodDeclarations(Method, List->Method)) { - List->Method->setDefined(impl); - return; + issueWarning = true; + } + if (issueWarning) { + Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; + Diag(MethList.Method->getLocStart(), diag::note_using) + << MethList.Method->getSourceRange(); + for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) + Diag(Next->Method->getLocStart(), diag::note_also_found) + << Next->Method->getSourceRange(); } - - // 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>(); - Entry.Next = new (Mem) ObjCMethodList(Method, Entry.Next); -} - -ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel, - SourceRange R, - bool warn) { - llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos - = FactoryMethodPool.find(Sel); - if (Pos == FactoryMethodPool.end()) { - if (ExternalSource && !InstanceMethodPool.count(Sel)) - Pos = ReadMethodPool(Sel, /*isInstance=*/false); - else - return 0; - } - - ObjCMethodList &MethList = Pos->second; - bool issueWarning = false; - - if (MethList.Method && MethList.Next) { - for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) - // This checks if the methods differ by size & alignment. - if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true)) - issueWarning = warn; - } - if (issueWarning && (MethList.Method && MethList.Next)) { - Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; - Diag(MethList.Method->getLocStart(), diag::note_using) - << MethList.Method->getSourceRange(); - for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) - Diag(Next->Method->getLocStart(), diag::note_also_found) - << Next->Method->getSourceRange(); } return MethList.Method; } ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) { - SourceRange SR; - ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel, - SR, false); - if (Method && Method->isDefined()) - return Method; - Method = LookupFactoryMethodInGlobalPool(Sel, SR, false); - if (Method && Method->isDefined()) - return Method; + GlobalMethodPool::iterator Pos = MethodPool.find(Sel); + if (Pos == MethodPool.end()) + return 0; + + GlobalMethods &Methods = Pos->second; + + if (Methods.first.Method && Methods.first.Method->isDefined()) + return Methods.first.Method; + if (Methods.second.Method && Methods.second.Method->isDefined()) + return Methods.second.Method; return 0; } diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 4f2567eb55..bf933c3a43 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -930,7 +930,7 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE, ClassDecl = OCIType->getInterfaceDecl(); // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be // faster than the following method (which can do *many* linear searches). - // The idea is to add class info to InstanceMethodPool. + // The idea is to add class info to MethodPool. Method = ClassDecl->lookupInstanceMethod(Sel); if (!Method) { |