diff options
author | Chris Lattner <sabre@nondot.org> | 2009-03-01 00:56:52 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-03-01 00:56:52 +0000 |
commit | 9ef10f4638bce8c83cf08454bcbea036094ac465 (patch) | |
tree | cfc071852d17ca88a023c7f9ef82960436d397eb /clang/lib | |
parent | 89d856e9e00101e552c89bcb30549099db6a0009 (diff) | |
download | bcm5719-llvm-9ef10f4638bce8c83cf08454bcbea036094ac465.tar.gz bcm5719-llvm-9ef10f4638bce8c83cf08454bcbea036094ac465.zip |
"This patch uses the new ObjCImplDecl class to merge Sema::ImplMethodsVsClassMethods and Sema::ImplCategoryMethodsVsIntfMethods methods.
And now, when clang check a class implementation to find unimplemented methods, it also checks all methods from the class extensions (unnamed categories).
There is also a test case to check this warning.
This patch contains also a minor update for ObjCImplDecl . getNameAsCString and getNameAsString now returns an empty string instead of crashing for unnamed categories."
Patch by Jean-Daniel Dupas!
llvm-svn: 65744
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/Sema.h | 14 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 99 |
2 files changed, 35 insertions, 78 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 3e9d07aefb6..6e0b935b88a 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -68,6 +68,7 @@ namespace clang { class ObjCInterfaceDecl; class ObjCCompatibleAliasDecl; class ObjCProtocolDecl; + class ObjCImplDecl; class ObjCImplementationDecl; class ObjCCategoryImplDecl; class ObjCCategoryDecl; @@ -930,14 +931,11 @@ public: SourceLocation Loc); /// ImplMethodsVsClassMethods - This is main routine to warn if any method - /// remains unimplemented in the @implementation class. - void ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, - ObjCInterfaceDecl* IDecl); - - /// ImplCategoryMethodsVsIntfMethods - Checks that methods declared in the - /// category interface is implemented in the category @implementation. - void ImplCategoryMethodsVsIntfMethods(ObjCCategoryImplDecl *CatImplDecl, - ObjCCategoryDecl *CatClassDecl); + /// remains unimplemented in the class or category @implementation. + void ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl, + ObjCContainerDecl* IDecl, + bool IncompleteImpl = false); + /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns /// true, or false, accordingly. bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 654891d5ab5..f1f03844a24 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -814,8 +814,9 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, IDecl); } -void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, - ObjCInterfaceDecl* IDecl) { +void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl, + ObjCContainerDecl* CDecl, + bool IncompleteImpl) { llvm::DenseSet<Selector> InsMap; // Check and see if instance methods in class interface have been // implemented in the implementation class. @@ -823,9 +824,8 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, E = IMPDecl->instmeth_end(); I != E; ++I) InsMap.insert((*I)->getSelector()); - bool IncompleteImpl = false; - for (ObjCInterfaceDecl::instmeth_iterator I = IDecl->instmeth_begin(), - E = IDecl->instmeth_end(); I != E; ++I) { + for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(), + E = CDecl->instmeth_end(); I != E; ++I) { if (!(*I)->isSynthesized() && !InsMap.count((*I)->getSelector())) { WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl); continue; @@ -834,7 +834,7 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, ObjCMethodDecl *ImpMethodDecl = IMPDecl->getInstanceMethod((*I)->getSelector()); ObjCMethodDecl *IntfMethodDecl = - IDecl->getInstanceMethod((*I)->getSelector()); + CDecl->getInstanceMethod((*I)->getSelector()); assert(IntfMethodDecl && "IntfMethodDecl is null in ImplMethodsVsClassMethods"); // ImpMethodDecl may be null as in a @dynamic property. @@ -849,82 +849,41 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, E = IMPDecl->classmeth_end(); I != E; ++I) ClsMap.insert((*I)->getSelector()); - for (ObjCInterfaceDecl::classmeth_iterator I = IDecl->classmeth_begin(), - E = IDecl->classmeth_end(); I != E; ++I) + for (ObjCInterfaceDecl::classmeth_iterator I = CDecl->classmeth_begin(), + E = CDecl->classmeth_end(); I != E; ++I) if (!ClsMap.count((*I)->getSelector())) WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl); else { ObjCMethodDecl *ImpMethodDecl = IMPDecl->getClassMethod((*I)->getSelector()); ObjCMethodDecl *IntfMethodDecl = - IDecl->getClassMethod((*I)->getSelector()); + CDecl->getClassMethod((*I)->getSelector()); WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); } // Check the protocol list for unimplemented methods in the @implementation // class. - const ObjCList<ObjCProtocolDecl> &Protocols = - IDecl->getReferencedProtocols(); - for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), - E = Protocols.end(); I != E; ++I) - CheckProtocolMethodDefs(IMPDecl->getLocation(), *I, - IncompleteImpl, InsMap, ClsMap, IDecl); -} - -/// ImplCategoryMethodsVsIntfMethods - Checks that methods declared in the -/// category interface are implemented in the category @implementation. -void Sema::ImplCategoryMethodsVsIntfMethods(ObjCCategoryImplDecl *CatImplDecl, - ObjCCategoryDecl *CatClassDecl) { - llvm::DenseSet<Selector> InsMap; - // Check and see if instance methods in category interface have been - // implemented in its implementation class. - for (ObjCCategoryImplDecl::instmeth_iterator I =CatImplDecl->instmeth_begin(), - E = CatImplDecl->instmeth_end(); I != E; ++I) - InsMap.insert((*I)->getSelector()); - - bool IncompleteImpl = false; - for (ObjCCategoryDecl::instmeth_iterator I = CatClassDecl->instmeth_begin(), - E = CatClassDecl->instmeth_end(); I != E; ++I) - if (!(*I)->isSynthesized() && !InsMap.count((*I)->getSelector())) - WarnUndefinedMethod(CatImplDecl->getLocation(), *I, IncompleteImpl); - else { - ObjCMethodDecl *ImpMethodDecl = - CatImplDecl->getInstanceMethod((*I)->getSelector()); - ObjCMethodDecl *IntfMethodDecl = - CatClassDecl->getInstanceMethod((*I)->getSelector()); - assert(IntfMethodDecl && - "IntfMethodDecl is null in ImplCategoryMethodsVsIntfMethods"); - // ImpMethodDecl may be null as in a @dynamic property. - if (ImpMethodDecl) - WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); - } - - llvm::DenseSet<Selector> ClsMap; - // Check and see if class methods in category interface have been - // implemented in its implementation class. - for (ObjCCategoryImplDecl::classmeth_iterator - I = CatImplDecl->classmeth_begin(), E = CatImplDecl->classmeth_end(); - I != E; ++I) - ClsMap.insert((*I)->getSelector()); - - for (ObjCCategoryDecl::classmeth_iterator I = CatClassDecl->classmeth_begin(), - E = CatClassDecl->classmeth_end(); I != E; ++I) - if (!ClsMap.count((*I)->getSelector())) - WarnUndefinedMethod(CatImplDecl->getLocation(), *I, IncompleteImpl); - else { - ObjCMethodDecl *ImpMethodDecl = - CatImplDecl->getClassMethod((*I)->getSelector()); - ObjCMethodDecl *IntfMethodDecl = - CatClassDecl->getClassMethod((*I)->getSelector()); - WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); + if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) { + for (ObjCCategoryDecl::protocol_iterator PI = I->protocol_begin(), + E = I->protocol_end(); PI != E; ++PI) + CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, + InsMap, ClsMap, I); + // Check class extensions (unnamed categories) + for (ObjCCategoryDecl *Categories = I->getCategoryList(); + Categories; Categories = Categories->getNextClassCategory()) { + if (!Categories->getIdentifier()) { + ImplMethodsVsClassMethods(IMPDecl, Categories, IncompleteImpl); + break; + } } - // Check the protocol list for unimplemented methods in the @implementation - // class. - for (ObjCCategoryDecl::protocol_iterator PI = CatClassDecl->protocol_begin(), - E = CatClassDecl->protocol_end(); PI != E; ++PI) - CheckProtocolMethodDefs(CatImplDecl->getLocation(), *PI, IncompleteImpl, - InsMap, ClsMap, CatClassDecl->getClassInterface()); + } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { + for (ObjCCategoryDecl::protocol_iterator PI = C->protocol_begin(), + E = C->protocol_end(); PI != E; ++PI) + CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, + InsMap, ClsMap, C->getClassInterface()); + } else + assert(false && "invalid ObjCContainerDecl type."); } /// ActOnForwardClassDeclaration - @@ -1302,7 +1261,7 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclTy *classDecl, for (ObjCCategoryDecl *Categories = IDecl->getCategoryList(); Categories; Categories = Categories->getNextClassCategory()) { if (Categories->getIdentifier() == CatImplClass->getIdentifier()) { - ImplCategoryMethodsVsIntfMethods(CatImplClass, Categories); + ImplMethodsVsClassMethods(CatImplClass, Categories); break; } } |