Patch to warn on umimplemented methods coming from class's

protocols.

llvm-svn: 42436
This commit is contained in:
Fariborz Jahanian 2007-09-28 17:40:07 +00:00
parent 25d506c41b
commit b75db4cc8c
5 changed files with 95 additions and 26 deletions

View File

@ -390,8 +390,6 @@ public:
virtual void ActOnImpleIvarVsClassIvars(DeclTy *ClassDecl, virtual void ActOnImpleIvarVsClassIvars(DeclTy *ClassDecl,
DeclTy **Fields, unsigned NumFields); DeclTy **Fields, unsigned NumFields);
virtual void ActOnImplMethodsVsClassMethods(DeclTy *ImplClass, DeclTy *Class);
virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc, virtual DeclTy *ObjcBuildMethodDeclaration(SourceLocation MethodLoc,
tok::TokenKind MethodType, TypeTy *ReturnType, SelectorInfo *Sel, tok::TokenKind MethodType, TypeTy *ReturnType, SelectorInfo *Sel,
// optional arguments. The number of types/arguments is obtained // optional arguments. The number of types/arguments is obtained

View File

@ -1174,46 +1174,76 @@ void Sema::ActOnImpleIvarVsClassIvars(DeclTy *ClassDecl,
} }
void Sema::ActOnImplMethodsVsClassMethods(DeclTy* ImplClassDecl, /// CheckProtocolMethodDefs - This routine checks unimpletented methods
DeclTy* ClassDecl) { /// Declared in protocol, and those referenced by it.
ObjcImplementationDecl* IMPDecl = ///
cast<ObjcImplementationDecl>(static_cast<Decl*>(ImplClassDecl)); static void CheckProtocolMethodDefs(Sema* objSema, ObjcProtocolDecl *PDecl,
assert(IMPDecl && "missing implmentation class decl"); const llvm::DenseMap<const SelectorInfo*, char>& InsMap,
const llvm::DenseMap<const SelectorInfo*, char>& ClsMap) {
// check unimplemented instance methods.
ObjcMethodDecl** methods = PDecl->getInsMethods();
for (int j = 0; j < PDecl->getNumInsMethods(); j++)
if (!InsMap.count(methods[j]->getSelector())) {
llvm::SmallString<128> buf;
objSema->Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
methods[j]->getSelector()->getName(buf));
}
// check unimplemented class methods
methods = PDecl->getClsMethods();
for (int j = 0; j < PDecl->getNumClsMethods(); j++)
if (!ClsMap.count(methods[j]->getSelector())) {
llvm::SmallString<128> buf;
objSema->Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
methods[j]->getSelector()->getName(buf));
}
ObjcInterfaceDecl* IDecl = // Check on this protocols's referenced protocols, recursively
cast<ObjcInterfaceDecl>(static_cast<Decl*>(ClassDecl)); ObjcProtocolDecl** RefPDecl = PDecl->getReferencedProtocols();
assert(IDecl && "missing interface class decl"); for (int i = 0; i < PDecl->getNumReferencedProtocols(); i++)
CheckProtocolMethodDefs(objSema, RefPDecl[i], InsMap, ClsMap);
}
llvm::DenseMap<const SelectorInfo*, char> Map; static void ImplMethodsVsClassMethods(Sema* objSema,
ObjcImplementationDecl* IMPDecl,
ObjcInterfaceDecl* IDecl) {
llvm::DenseMap<const SelectorInfo*, char> InsMap;
// Check and see if instance methods in class interface have been // Check and see if instance methods in class interface have been
// implemented in the implementation class. // implemented in the implementation class.
ObjcMethodDecl **methods = IMPDecl->getInsMethods(); ObjcMethodDecl **methods = IMPDecl->getInsMethods();
for (int i=0; i < IMPDecl->getNumInsMethods(); i++) { for (int i=0; i < IMPDecl->getNumInsMethods(); i++) {
Map[methods[i]->getSelector()] = 'a'; InsMap[methods[i]->getSelector()] = 'a';
} }
methods = IDecl->getInsMethods(); methods = IDecl->getInsMethods();
for (int j = 0; j < IDecl->getNumInsMethods(); j++) for (int j = 0; j < IDecl->getNumInsMethods(); j++)
if (!Map.count(methods[j]->getSelector())) { if (!InsMap.count(methods[j]->getSelector())) {
llvm::SmallString<128> buf; llvm::SmallString<128> buf;
Diag(methods[j]->getLocation(), diag::warn_undef_method_impl, objSema->Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
methods[j]->getSelector()->getName(buf)); methods[j]->getSelector()->getName(buf));
} }
Map.clear(); llvm::DenseMap<const SelectorInfo*, char> ClsMap;
// Check and see if class methods in class interface have been // Check and see if class methods in class interface have been
// implemented in the implementation class. // implemented in the implementation class.
methods = IMPDecl->getClsMethods(); methods = IMPDecl->getClsMethods();
for (int i=0; i < IMPDecl->getNumClsMethods(); i++) { for (int i=0; i < IMPDecl->getNumClsMethods(); i++) {
Map[methods[i]->getSelector()] = 'a'; ClsMap[methods[i]->getSelector()] = 'a';
} }
methods = IDecl->getClsMethods(); methods = IDecl->getClsMethods();
for (int j = 0; j < IDecl->getNumClsMethods(); j++) for (int j = 0; j < IDecl->getNumClsMethods(); j++)
if (!Map.count(methods[j]->getSelector())) { if (!ClsMap.count(methods[j]->getSelector())) {
llvm::SmallString<128> buf; llvm::SmallString<128> buf;
Diag(methods[j]->getLocation(), diag::warn_undef_method_impl, objSema->Diag(methods[j]->getLocation(), diag::warn_undef_method_impl,
methods[j]->getSelector()->getName(buf)); methods[j]->getSelector()->getName(buf));
} }
// Check the protocol list for unimplemented methods in the @implementation
// class.
ObjcProtocolDecl** protocols = IDecl->getIntfRefProtocols();
for (int i = 0; i < IDecl->getNumIntfRefProtocols(); i++) {
ObjcProtocolDecl* PDecl = protocols[i];
CheckProtocolMethodDefs(objSema, PDecl, InsMap, ClsMap);
}
return; return;
} }
@ -1612,7 +1642,7 @@ void Sema::ObjcAddMethodsToClass(DeclTy *ClassDecl,
ObjcInterfaceDecl* IDecl = ObjcInterfaceDecl* IDecl =
Context.getObjCInterfaceDecl(ImplClass->getIdentifier()); Context.getObjCInterfaceDecl(ImplClass->getIdentifier());
if (IDecl) if (IDecl)
ActOnImplMethodsVsClassMethods(ImplClass, IDecl); ImplMethodsVsClassMethods(this, ImplClass, IDecl);
} }
else else
assert(0 && "Sema::ObjcAddMethodsToClass(): Unknown DeclTy"); assert(0 && "Sema::ObjcAddMethodsToClass(): Unknown DeclTy");

View File

@ -588,6 +588,10 @@ public:
NumIntfRefProtocols = numRefProtos; NumIntfRefProtocols = numRefProtos;
} }
} }
ObjcProtocolDecl **getIntfRefProtocols() const { return IntfRefProtocols; }
int getNumIntfRefProtocols() const { return NumIntfRefProtocols; }
ObjcIvarDecl **getIntfDeclIvars() const { return Ivars; } ObjcIvarDecl **getIntfDeclIvars() const { return Ivars; }
int getIntfDeclNumIvars() const { return NumIvars; } int getIntfDeclNumIvars() const { return NumIvars; }
@ -776,6 +780,16 @@ public:
ReferencedProtocols[idx] = OID; ReferencedProtocols[idx] = OID;
} }
ObjcProtocolDecl** getReferencedProtocols() const {
return ReferencedProtocols;
}
int getNumReferencedProtocols() const { return NumReferencedProtocols; }
ObjcMethodDecl** getInsMethods() const { return ProtoInsMethods; }
int getNumInsMethods() const { return NumProtoInsMethods; }
ObjcMethodDecl** getClsMethods() const { return ProtoClsMethods; }
int getNumClsMethods() const { return NumProtoClsMethods; }
bool getIsForwardProtoDecl() const { return isForwardProtoDecl; } bool getIsForwardProtoDecl() const { return isForwardProtoDecl; }
void setIsForwardProtoDecl(bool val) { isForwardProtoDecl = val; } void setIsForwardProtoDecl(bool val) { isForwardProtoDecl = val; }

View File

@ -451,10 +451,6 @@ public:
DeclTy **Fields, unsigned NumFields) { DeclTy **Fields, unsigned NumFields) {
return; return;
} }
virtual void ActOnImplMethodsVsClassMethods(DeclTy *ImplClassDecl,
DeclTy *ClassDecl) {
return;
}
virtual DeclTy *ObjcStartProtoInterface(Scope* S, virtual DeclTy *ObjcStartProtoInterface(Scope* S,
SourceLocation AtProtoInterfaceLoc, SourceLocation AtProtoInterfaceLoc,
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,

View File

@ -0,0 +1,31 @@
@protocol P1
- (void) P1proto; // expected-warning {{method definition for 'P1proto' not found}}
+ (void) ClsP1Proto; // expected-warning {{method definition for 'ClsP1Proto' not found}}
- (void) DefP1proto;
@end
@protocol P2
- (void) P2proto; // expected-warning {{method definition for 'P2proto' not found}}
+ (void) ClsP2Proto; // expected-warning {{method definition for 'ClsP2Proto' not found}}
@end
@protocol P3<P2>
- (void) P3proto; // expected-warning {{method definition for 'P3proto' not found}}
+ (void) ClsP3Proto; // expected-warning {{method definition for 'ClsP3Proto' not found}}
+ (void) DefClsP3Proto;
@end
@protocol PROTO<P1, P3>
- (void) meth; // expected-warning {{method definition for 'meth' not found
- (void) meth : (int) arg1; // expected-warning {{method definition for 'meth:' not found
+ (void) cls_meth : (int) arg1; // expected-warning {{method definition for 'cls_meth:' not found
@end
@interface INTF <PROTO>
@end
@implementation INTF
- (void) DefP1proto{}
+ (void) DefClsP3Proto{}
@end