diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/ParseAST.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 18 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 85 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaObjCProperty.cpp | 4 |
5 files changed, 79 insertions, 35 deletions
diff --git a/lib/Sema/ParseAST.cpp b/lib/Sema/ParseAST.cpp index bb0bd9e1cb..73f1167d0e 100644 --- a/lib/Sema/ParseAST.cpp +++ b/lib/Sema/ParseAST.cpp @@ -92,7 +92,7 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>()); }; // Check for any pending objective-c implementation decl. - while ((ADecl = P.RetrievePendingObjCImpDecl())) + while ((ADecl = P.FinishPendingObjCActions())) Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>()); // Process any TopLevelDecls generated by #pragma weak. diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 490ff65cd9..0540dd9e0c 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -606,6 +606,11 @@ public: MethodPool InstanceMethodPool; MethodPool FactoryMethodPool; + /// Method selectors used in a @selector expression. Used for implementation + /// of -Wselector. + llvm::DenseMap<Selector, SourceLocation> ReferencedSelectors; + + MethodPool::iterator ReadMethodPool(Selector Sel, bool isInstance); /// Private Helper predicate to check for 'self'. @@ -798,6 +803,8 @@ public: DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr); + void DiagnoseUseOfUnimplementedSelectors(); + virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS, bool isClassName = false, @@ -1656,7 +1663,7 @@ public: /// 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); + void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false); /// LookupInstanceMethodInGlobalPool - Returns the method and warns if /// there are multiple signatures. @@ -1665,10 +1672,15 @@ public: /// LookupFactoryMethodInGlobalPool - Returns the method and warns if /// there are multiple signatures. - ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R); + ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R, + bool warn=true); + + /// LookupImplementedMethodInGlobalPool - Returns the method which has an + /// implementation. + ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel); /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods. - void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method); + void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false); /// CollectIvarsToConstructOrDestruct - Collect those ivars which require /// initialization. diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 21aeb59a08..5f2f37eb0b 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -32,10 +32,10 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) { // Allow the rest of sema to find private method decl implementations. if (MDecl->isInstanceMethod()) - AddInstanceMethodToGlobalPool(MDecl); + AddInstanceMethodToGlobalPool(MDecl, true); else - AddFactoryMethodToGlobalPool(MDecl); - + AddFactoryMethodToGlobalPool(MDecl, true); + // Allow all of Sema to see that we are entering a method definition. PushDeclContext(FnBodyScope, MDecl); PushFunctionScope(); @@ -1130,7 +1130,7 @@ Sema::MethodPool::iterator Sema::ReadMethodPool(Selector Sel, return FactoryMethodPool.insert(std::make_pair(Sel, Methods.second)).first; } -void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) { +void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl) { llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos = InstanceMethodPool.find(Method->getSelector()); if (Pos == InstanceMethodPool.end()) { @@ -1140,7 +1140,7 @@ void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) { Pos = InstanceMethodPool.insert(std::make_pair(Method->getSelector(), ObjCMethodList())).first; } - + Method->setDefined(impl); ObjCMethodList &Entry = Pos->second; if (Entry.Method == 0) { // Haven't seen a method with this selector name yet - add it. @@ -1152,8 +1152,10 @@ void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) { // 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)) + if (MatchTwoMethodDeclarations(Method, List->Method)) { + List->Method->setDefined(impl); return; + } // We have a new signature for an existing method - add it. // This is extremely rare. Only 1% of Cocoa selectors are "overloaded". @@ -1194,7 +1196,7 @@ ObjCMethodDecl *Sema::LookupInstanceMethodInGlobalPool(Selector Sel, return MethList.Method; } -void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) { +void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl) { llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos = FactoryMethodPool.find(Method->getSelector()); if (Pos == FactoryMethodPool.end()) { @@ -1204,32 +1206,31 @@ void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) { Pos = FactoryMethodPool.insert(std::make_pair(Method->getSelector(), ObjCMethodList())).first; } - - ObjCMethodList &FirstMethod = Pos->second; - if (!FirstMethod.Method) { + Method->setDefined(impl); + ObjCMethodList &Entry = Pos->second; + if (!Entry.Method) { // Haven't seen a method with this selector name yet - add it. - FirstMethod.Method = Method; - FirstMethod.Next = 0; - } else { - // We've seen a method with this name, now check the type signature(s). - bool match = MatchTwoMethodDeclarations(Method, FirstMethod.Method); - - for (ObjCMethodList *Next = FirstMethod.Next; !match && Next; - Next = Next->Next) - match = MatchTwoMethodDeclarations(Method, Next->Method); - - if (!match) { - // 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>(); - ObjCMethodList *OMI = new (Mem) ObjCMethodList(Method, FirstMethod.Next); - FirstMethod.Next = OMI; + 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; } - } + + // 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) { + SourceRange R, + bool warn) { llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos = FactoryMethodPool.find(Sel); if (Pos == FactoryMethodPool.end()) { @@ -1246,7 +1247,7 @@ ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel, 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; + issueWarning = warn; } if (issueWarning && (MethList.Method && MethList.Next)) { Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; @@ -1259,6 +1260,18 @@ ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel, 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; + return 0; +} + /// CompareMethodParamsInBaseAndSuper - This routine compares methods with /// identical selector names in current and its super classes and issues /// a warning if any of their argument types are incompatible. @@ -1540,7 +1553,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( ResultTInfo, cast<DeclContext>(ClassDecl), MethodType == tok::minus, isVariadic, - false, + false, false, MethodDeclKind == tok::objc_optional ? ObjCMethodDecl::Optional : ObjCMethodDecl::Required); @@ -1849,3 +1862,15 @@ void ObjCImplementationDecl::setIvarInitializers(ASTContext &C, } } +void Sema::DiagnoseUseOfUnimplementedSelectors() { + if (ReferencedSelectors.empty()) + return; + for (llvm::DenseMap<Selector, SourceLocation>::iterator S = + ReferencedSelectors.begin(), + E = ReferencedSelectors.end(); S != E; ++S) { + Selector Sel = (*S).first; + if (!LookupImplementedMethodInGlobalPool(Sel)) + Diag((*S).second, diag::warn_unimplemented_selector) << Sel; + } + return; +} diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 9f43471e0a..5132464d24 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -163,6 +163,11 @@ Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, if (!Method) Diag(SelLoc, diag::warn_undeclared_selector) << Sel; + llvm::DenseMap<Selector, SourceLocation>::iterator Pos + = ReferencedSelectors.find(Sel); + if (Pos == ReferencedSelectors.end()) + ReferencedSelectors.insert(std::make_pair(Sel, SelLoc)); + QualType Ty = Context.getObjCSelType(); return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc); } diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index e7358edec3..6a7d8dbee1 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -1084,7 +1084,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, // for this class. GetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(), property->getLocation(), property->getGetterName(), - property->getType(), 0, CD, true, false, true, + property->getType(), 0, CD, true, false, true, + false, (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) ? ObjCMethodDecl::Optional : @@ -1112,6 +1113,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, property->getLocation(), property->getSetterName(), Context.VoidTy, 0, CD, true, false, true, + false, (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) ? ObjCMethodDecl::Optional : |