From: Steve Naroff Date: Sun, 28 Sep 2008 14:55:53 +0000 (+0000) Subject: Fix implementation of method in category doesn't effectively... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e84a864a7871243d7c60441f399a309dea076f5c;p=clang Fix implementation of method in category doesn't effectively declare it for methods below. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56771 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index f553629a6c..dcd197dad6 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -92,10 +92,14 @@ public: /// This is only necessary for issuing pretty diagnostics. llvm::SmallVector ExtVectorDecls; - /// ObjCImplementations - Keep track of all of the classes with - /// @implementation's, so that we can emit errors on duplicates. + /// ObjCImplementations - Keep track of all class @implementations + /// so we can emit errors on duplicates. llvm::DenseMap ObjCImplementations; + /// ObjCCategoryImpls - Maintain a list of category implementations so + /// we can check for duplicates and find local method declarations. + llvm::SmallVector ObjCCategoryImpls; + /// ObjCProtocols - Keep track of all protocol declarations declared /// with @protocol keyword, so that we can emit errors on duplicates and /// find the declarations when needed. diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index a09daa0814..0241655026 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -429,6 +429,7 @@ Sema::DeclTy *Sema::ActOnStartCategoryImplementation( /// TODO: Check that CatName, category name, is not used in another // implementation. + ObjCCategoryImpls.push_back(CDecl); return CDecl; } diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 390baed9a3..a2a3992bab 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -233,6 +233,14 @@ Sema::ExprResult Sema::ActOnClassMessage( if (ObjCImplementationDecl *ImpDecl = ObjCImplementations[ClassDecl->getIdentifier()]) Method = ImpDecl->getClassMethod(Sel); + + // Look through local category implementations associated with the class. + if (!Method) { + for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) { + if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl) + Method = ObjCCategoryImpls[i]->getClassMethod(Sel); + } + } } // Before we give up, check if the selector is an instance method. if (!Method) diff --git a/test/SemaObjC/category-method-lookup.m b/test/SemaObjC/category-method-lookup.m new file mode 100644 index 0000000000..a709008460 --- /dev/null +++ b/test/SemaObjC/category-method-lookup.m @@ -0,0 +1,31 @@ +// RUN: clang -fsyntax-only -verify %s + +@interface Foo +@end +@implementation Foo +@end + +@implementation Foo(Whatever) ++(float)returnsFloat { return 7.0; } +@end + +@interface Foo (MoreStuff) ++(int)returnsInt; +@end + +@implementation Foo (MoreStuff) ++(int)returnsInt { + return 0; +} + ++(void)returnsNothing { +} +-(int)callsReturnsInt { + float f = [Foo returnsFloat]; // GCC doesn't find this method (which is a bug IMHO). + [Foo returnsNothing]; + return [Foo returnsInt]; +} +@end + +int main() {return 0;} +