diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-04-24 21:10:55 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-04-24 21:10:55 +0000 |
commit | c78d34699fc47e947939d640b5ba215f9018b4fc (patch) | |
tree | 13b9bb1e1ba83be3469884750063ce1fd910b94a /clang/lib/Sema | |
parent | 969bc68195957fffe2f33594d8d9c660795fc56a (diff) | |
download | bcm5719-llvm-c78d34699fc47e947939d640b5ba215f9018b4fc.tar.gz bcm5719-llvm-c78d34699fc47e947939d640b5ba215f9018b4fc.zip |
PCH support for the global method pool (= instance and factory method
pools, combined). The methods in the global method pool are lazily
loaded from an on-disk hash table when Sema looks into its version of
the hash tables.
llvm-svn: 69989
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 32 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 96 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 4 |
4 files changed, 112 insertions, 24 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 3702c89cf60..367c9f5756b 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -163,8 +163,8 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, bool CompleteTranslationUnit) : LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), - Diags(PP.getDiagnostics()), - SourceMgr(PP.getSourceManager()), CurContext(0), PreDeclaratorDC(0), + Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), + ExternalSource(0), CurContext(0), PreDeclaratorDC(0), CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()), GlobalNewDeleteDeclared(false), CompleteTranslationUnit(CompleteTranslationUnit) { diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index b3cb5e25fb3..7426965a442 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -19,13 +19,13 @@ #include "CXXFieldCollector.h" #include "SemaOverload.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/DeclObjC.h" #include "clang/Parse/Action.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" -#include "clang/AST/DeclObjC.h" #include <string> #include <vector> @@ -40,6 +40,7 @@ namespace clang { class Decl; class DeclContext; class DeclSpec; + class ExternalSemaSource; class NamedDecl; class Stmt; class Expr; @@ -128,6 +129,9 @@ public: Diagnostic &Diags; SourceManager &SourceMgr; + /// \brief Source of additional semantic information. + ExternalSemaSource *ExternalSource; + /// CurContext - This is the current declaration context of parsing. DeclContext *CurContext; @@ -243,27 +247,17 @@ public: /// unit. bool CompleteTranslationUnit; - /// ObjCMethodList - a linked list of methods with different signatures. - struct ObjCMethodList { - ObjCMethodDecl *Method; - ObjCMethodList *Next; - - ObjCMethodList() { - Method = 0; - Next = 0; - } - ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) { - Method = M; - Next = C; - } - }; + typedef llvm::DenseMap<Selector, ObjCMethodList> MethodPool; + /// 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"). - llvm::DenseMap<Selector, ObjCMethodList> InstanceMethodPool; - llvm::DenseMap<Selector, ObjCMethodList> FactoryMethodPool; + MethodPool InstanceMethodPool; + MethodPool FactoryMethodPool; + MethodPool::iterator ReadMethodPool(Selector Sel, bool isInstance); + /// Private Helper predicate to check for 'self'. bool isSelfExpr(Expr *RExpr); public: @@ -1126,6 +1120,10 @@ public: /// LookupInstanceMethodInGlobalPool - Returns the method and warns if /// there are multiple signatures. ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R); + + /// LookupFactoryMethodInGlobalPool - Returns the method and warns if + /// there are multiple signatures. + ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R); /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods. void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index f4014d1f25d..05e471b10df 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "clang/Sema/ExternalSemaSource.h" #include "clang/AST/Expr.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -1090,8 +1091,47 @@ 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. +/// +/// 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) { + 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"); + + // Read the method list from the external source. + std::pair<ObjCMethodList, ObjCMethodList> 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; +} + void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) { - ObjCMethodList &Entry = InstanceMethodPool[Method->getSelector()]; + 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); + else + Pos = InstanceMethodPool.insert(std::make_pair(Method->getSelector(), + ObjCMethodList())).first; + } + + ObjCMethodList &Entry = Pos->second; if (Entry.Method == 0) { // Haven't seen a method with this selector name yet - add it. Entry.Method = Method; @@ -1113,7 +1153,16 @@ void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) { // FIXME: Finish implementing -Wno-strict-selector-match. ObjCMethodDecl *Sema::LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R) { - ObjCMethodList &MethList = InstanceMethodPool[Sel]; + llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos + = InstanceMethodPool.find(Sel); + if (Pos == InstanceMethodPool.end() && !FactoryMethodPool.count(Sel)) { + if (ExternalSource) + Pos = ReadMethodPool(Sel, /*isInstance=*/true); + else + return 0; + } + + ObjCMethodList &MethList = Pos->second; bool issueWarning = false; if (MethList.Method && MethList.Next) { @@ -1134,7 +1183,17 @@ ObjCMethodDecl *Sema::LookupInstanceMethodInGlobalPool(Selector Sel, } void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) { - ObjCMethodList &FirstMethod = FactoryMethodPool[Method->getSelector()]; + 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; + } + + ObjCMethodList &FirstMethod = Pos->second; if (!FirstMethod.Method) { // Haven't seen a method with this selector name yet - add it. FirstMethod.Method = Method; @@ -1156,6 +1215,37 @@ void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) { } } +ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel, + SourceRange R) { + 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 = true; + } + if (issueWarning && (MethList.Method && MethList.Next)) { + Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; + Diag(MethList.Method->getLocStart(), diag::note_using_decl) + << MethList.Method->getSourceRange(); + for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) + Diag(Next->Method->getLocStart(), diag::note_also_found_decl) + << Next->Method->getSourceRange(); + } + return MethList.Method; +} + /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods /// have the property type and issue diagnostics if they don't. /// Also synthesize a getter/setter method if none exist (and update the diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index d48ba4470c4..f2cd00195fa 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -497,7 +497,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool( Sel, SourceRange(lbrac,rbrac)); if (!Method) - Method = FactoryMethodPool[Sel].Method; + Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac, rbrac)); if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, lbrac, rbrac, returnType)) return true; @@ -523,7 +523,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, if (!Method) { // If not messaging 'self', look for any factory method named 'Sel'. if (!isSelfExpr(RExpr)) { - Method = FactoryMethodPool[Sel].Method; + Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac)); if (!Method) { Method = LookupInstanceMethodInGlobalPool( Sel, SourceRange(lbrac,rbrac)); |