Check for method type conflict between declaration in

class/protocol and implementation which could be
an imm. implementation or down in the inheritance
hierarchy.

llvm-svn: 70568
This commit is contained in:
Fariborz Jahanian 2009-05-01 20:07:12 +00:00
parent b781bcdc30
commit 07b7165b50
7 changed files with 126 additions and 42 deletions

View File

@ -1114,6 +1114,17 @@ public:
const ObjCMethodDecl *PrevMethod, const ObjCMethodDecl *PrevMethod,
bool matchBasedOnSizeAndAlignment = false); bool matchBasedOnSizeAndAlignment = false);
/// MatchAllMethodDeclarations - Check methods declaraed in interface or
/// or protocol against those declared in their implementations.
void MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
const llvm::DenseSet<Selector> &ClsMap,
llvm::DenseSet<Selector> &InsMapSeen,
llvm::DenseSet<Selector> &ClsMapSeen,
ObjCImplDecl* IMPDecl,
ObjCContainerDecl* IDecl,
bool &IncompleteImpl,
bool ImmediateClass);
/// AddInstanceMethodToGlobalPool - All instance methods in a translation /// AddInstanceMethodToGlobalPool - All instance methods in a translation
/// unit are added to a global pool. This allows us to efficiently associate /// unit are added to a global pool. This allows us to efficiently associate
/// a selector with a method declaraation for purposes of typechecking /// a selector with a method declaraation for purposes of typechecking

View File

@ -885,6 +885,79 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, IDecl); CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, IDecl);
} }
/// MatchAllMethodDeclarations - Check methods declaraed in interface or
/// or protocol against those declared in their implementations.
///
void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
const llvm::DenseSet<Selector> &ClsMap,
llvm::DenseSet<Selector> &InsMapSeen,
llvm::DenseSet<Selector> &ClsMapSeen,
ObjCImplDecl* IMPDecl,
ObjCContainerDecl* CDecl,
bool &IncompleteImpl,
bool ImmediateClass)
{
// Check and see if instance methods in class interface have been
// implemented in the implementation class. If so, their types match.
for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(Context),
E = CDecl->instmeth_end(Context); I != E; ++I) {
if (InsMapSeen.count((*I)->getSelector()))
continue;
InsMapSeen.insert((*I)->getSelector());
if (!(*I)->isSynthesized() &&
!InsMap.count((*I)->getSelector())) {
if (ImmediateClass)
WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
continue;
}
else {
ObjCMethodDecl *ImpMethodDecl =
IMPDecl->getInstanceMethod(Context, (*I)->getSelector());
ObjCMethodDecl *IntfMethodDecl =
CDecl->getInstanceMethod(Context, (*I)->getSelector());
assert(IntfMethodDecl &&
"IntfMethodDecl is null in ImplMethodsVsClassMethods");
// ImpMethodDecl may be null as in a @dynamic property.
if (ImpMethodDecl)
WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
}
}
// Check and see if class methods in class interface have been
// implemented in the implementation class. If so, their types match.
for (ObjCInterfaceDecl::classmeth_iterator
I = CDecl->classmeth_begin(Context),
E = CDecl->classmeth_end(Context);
I != E; ++I) {
if (ClsMapSeen.count((*I)->getSelector()))
continue;
ClsMapSeen.insert((*I)->getSelector());
if (!ClsMap.count((*I)->getSelector())) {
if (ImmediateClass)
WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
}
else {
ObjCMethodDecl *ImpMethodDecl =
IMPDecl->getClassMethod(Context, (*I)->getSelector());
ObjCMethodDecl *IntfMethodDecl =
CDecl->getClassMethod(Context, (*I)->getSelector());
WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
}
}
if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
// Check for any implementation of a methods declared in protocol.
for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(),
E = I->protocol_end(); PI != E; ++PI)
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
IMPDecl,
(*PI), IncompleteImpl, false);
if (I->getSuperClass())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
IMPDecl,
I->getSuperClass(), IncompleteImpl, false);
}
}
void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl, void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
ObjCContainerDecl* CDecl, ObjCContainerDecl* CDecl,
bool IncompleteImpl) { bool IncompleteImpl) {
@ -933,51 +1006,26 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl,
} }
} }
for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(Context),
E = CDecl->instmeth_end(Context); I != E; ++I) {
if (!(*I)->isSynthesized() && !InsMap.count((*I)->getSelector())) {
WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl);
continue;
}
ObjCMethodDecl *ImpMethodDecl =
IMPDecl->getInstanceMethod(Context, (*I)->getSelector());
ObjCMethodDecl *IntfMethodDecl =
CDecl->getInstanceMethod(Context, (*I)->getSelector());
assert(IntfMethodDecl &&
"IntfMethodDecl is null in ImplMethodsVsClassMethods");
// ImpMethodDecl may be null as in a @dynamic property.
if (ImpMethodDecl)
WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
}
llvm::DenseSet<Selector> ClsMap; llvm::DenseSet<Selector> ClsMap;
// Check and see if class methods in class interface have been
// implemented in the implementation class.
for (ObjCImplementationDecl::classmeth_iterator for (ObjCImplementationDecl::classmeth_iterator
I = IMPDecl->classmeth_begin(Context), I = IMPDecl->classmeth_begin(Context),
E = IMPDecl->classmeth_end(Context); I != E; ++I) E = IMPDecl->classmeth_end(Context); I != E; ++I)
ClsMap.insert((*I)->getSelector()); ClsMap.insert((*I)->getSelector());
for (ObjCInterfaceDecl::classmeth_iterator // Check for type conflict of methods declared in a class/protocol and
I = CDecl->classmeth_begin(Context), // its implementation; if any.
E = CDecl->classmeth_end(Context); llvm::DenseSet<Selector> InsMapSeen, ClsMapSeen;
I != E; ++I) MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
if (!ClsMap.count((*I)->getSelector())) IMPDecl, CDecl,
WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl); IncompleteImpl, true);
else {
ObjCMethodDecl *ImpMethodDecl =
IMPDecl->getClassMethod(Context, (*I)->getSelector());
ObjCMethodDecl *IntfMethodDecl =
CDecl->getClassMethod(Context, (*I)->getSelector());
WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl);
}
// Check the protocol list for unimplemented methods in the @implementation // Check the protocol list for unimplemented methods in the @implementation
// class. // class.
// Check and see if class methods in class interface have been
// implemented in the implementation class.
if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) { if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
for (ObjCCategoryDecl::protocol_iterator PI = I->protocol_begin(), for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(),
E = I->protocol_end(); PI != E; ++PI) E = I->protocol_end(); PI != E; ++PI)
CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
InsMap, ClsMap, I); InsMap, ClsMap, I);

View File

@ -44,7 +44,7 @@
-(id) O{ return 0; } -(id) O{ return 0; }
-(void) setO:(id)arg { } -(void) setO:(id)arg { }
- (void)dealloc - (id)dealloc
{ {
[_X release]; [_X release];
[_Z release]; [_Z release];

View File

@ -0,0 +1,25 @@
// RUN: clang-cc -fsyntax-only -verify %s
@protocol P
- (void) doSomethingInProtocol: (float) x; // expected-note {{previous definition is here}}
+ (void) doSomethingClassyInProtocol: (float) x; // expected-note {{previous definition is here}}
- (void) doNothingInProtocol : (float) x;
+ (void) doNothingClassyInProtocol : (float) x;
@end
@interface I <P>
- (void) doSomething: (float) x; // expected-note {{previous definition is here}}
+ (void) doSomethingClassy: (int) x; // expected-note {{previous definition is here}}
@end
@interface Bar : I
@end
@implementation Bar
- (void) doSomething: (int) x {} // expected-warning {{conflicting parameter types}}
+ (void) doSomethingClassy: (float) x{} // expected-warning {{conflicting parameter types}}
- (void) doSomethingInProtocol: (id) x {} // expected-warning {{conflicting parameter types}}
+ (void) doSomethingClassyInProtocol: (id) x {} // expected-warning {{conflicting parameter types}}
@end

View File

@ -21,7 +21,7 @@ typedef float CGFloat;
typedef struct _XCElementInset {} XCElementInset; typedef struct _XCElementInset {} XCElementInset;
@protocol XCElementP < NSObject > @protocol XCElementP < NSObject >
-(BOOL) vertical; -(id) vertical;
@end @end
@protocol XCElementDisplayDelegateP; @protocol XCElementDisplayDelegateP;
@ -60,6 +60,6 @@ typedef NSObject < XCElementJustifierP > XCElementJustifier;
if (_marker && _marker.variableSized) { if (_marker && _marker.variableSized) {
} }
} }
- vertical { return self; } - (id)vertical { return self; }
- (BOOL)isEqual:x { return 1; } - (BOOL)isEqual:x { return 1; }
@end @end

View File

@ -39,7 +39,7 @@
return self; return self;
} }
- (void)dealloc - dealloc
{ {
[_foo release]; [_foo release];
[_bar release]; [_bar release];

View File

@ -39,7 +39,7 @@
return self; return self;
} }
- (void)dealloc - dealloc
{ {
[_foo release]; [_foo release];
[_bar release]; [_bar release];