зеркало из https://github.com/microsoft/clang.git
Check for method type conflict between declaration in
class/protocol and implementation which could be an imm. implementation or down in the inheritance hierarchy. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70568 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
e9146f2e9f
Коммит
b33f3ad379
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc
|
- dealloc
|
||||||
{
|
{
|
||||||
[_foo release];
|
[_foo release];
|
||||||
[_bar release];
|
[_bar release];
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc
|
- dealloc
|
||||||
{
|
{
|
||||||
[_foo release];
|
[_foo release];
|
||||||
[_bar release];
|
[_bar release];
|
||||||
|
|
Загрузка…
Ссылка в новой задаче