diff options
-rw-r--r-- | lib/Sema/Sema.h | 8 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 8 | ||||
-rw-r--r-- | test/SemaObjC/category-method-lookup.m | 31 |
4 files changed, 46 insertions, 2 deletions
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<TypedefDecl*, 24> 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<IdentifierInfo*, ObjCImplementationDecl*> ObjCImplementations; + /// ObjCCategoryImpls - Maintain a list of category implementations so + /// we can check for duplicates and find local method declarations. + llvm::SmallVector<ObjCCategoryImplDecl*, 8> 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;} + |