Fix <rdar://problem/6252129> implementation of method in category doesn't effectively declare it for methods below.

llvm-svn: 56771
This commit is contained in:
Steve Naroff 2008-09-28 14:55:53 +00:00
parent 4831c74d40
commit 8edb573a79
4 changed files with 46 additions and 2 deletions

View File

@ -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.

View File

@ -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;
}

View File

@ -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)

View File

@ -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;}