forked from OSchip/llvm-project
objective-c: Methods declared in methods must type match
those declated in its protocols. First half or // rdar://6191214 llvm-svn: 136794
This commit is contained in:
parent
f169c394ca
commit
2bda1b65b1
|
@ -1785,7 +1785,8 @@ public:
|
||||||
ObjCInterfaceDecl *IDecl);
|
ObjCInterfaceDecl *IDecl);
|
||||||
|
|
||||||
typedef llvm::DenseSet<Selector, llvm::DenseMapInfo<Selector> > SelectorSet;
|
typedef llvm::DenseSet<Selector, llvm::DenseMapInfo<Selector> > SelectorSet;
|
||||||
|
typedef llvm::DenseMap<Selector, ObjCMethodDecl*> ProtocolsMethodsMap;
|
||||||
|
|
||||||
/// CheckProtocolMethodDefs - This routine checks unimplemented
|
/// CheckProtocolMethodDefs - This routine checks unimplemented
|
||||||
/// methods declared in protocol, and those referenced by it.
|
/// methods declared in protocol, and those referenced by it.
|
||||||
/// \param IDecl - Used for checking for methods which may have been
|
/// \param IDecl - Used for checking for methods which may have been
|
||||||
|
|
|
@ -1498,12 +1498,6 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
|
||||||
IMPDecl,
|
IMPDecl,
|
||||||
(*PI), IncompleteImpl, false, WarnExactMatch);
|
(*PI), IncompleteImpl, false, WarnExactMatch);
|
||||||
|
|
||||||
// Check for any type mismtch of methods declared in class
|
|
||||||
// and methods declared in protocol. Do this only when the class
|
|
||||||
// is being implementaed.
|
|
||||||
if (isa<ObjCImplementationDecl>(IMPDecl))
|
|
||||||
MatchMethodsInClassAndItsProtocol(I);
|
|
||||||
|
|
||||||
// FIXME. For now, we are not checking for extact match of methods
|
// FIXME. For now, we are not checking for extact match of methods
|
||||||
// in category implementation and its primary class's super class.
|
// in category implementation and its primary class's super class.
|
||||||
if (!WarnExactMatch && I->getSuperClass())
|
if (!WarnExactMatch && I->getSuperClass())
|
||||||
|
@ -1513,99 +1507,113 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// MatchMethodsInClassAndOneProtocol - This routine goes thru list of methods
|
||||||
|
/// declared in the class, and its class extensions. For each method which is
|
||||||
|
/// also declared in one of its qualifying protocols, they must type match or
|
||||||
|
/// it issues a warning.
|
||||||
static void MatchMethodsInClassAndOneProtocol(Sema &S,
|
static void MatchMethodsInClassAndOneProtocol(Sema &S,
|
||||||
Sema::SelectorSet &InsMap,
|
|
||||||
Sema::SelectorSet &ClsMap,
|
|
||||||
const ObjCContainerDecl *IDecl,
|
const ObjCContainerDecl *IDecl,
|
||||||
const ObjCProtocolDecl *PDecl) {
|
Sema::ProtocolsMethodsMap &InstMethodsInProtocols,
|
||||||
if (!InsMap.empty())
|
Sema::ProtocolsMethodsMap &ClsMethodsInProtocols) {
|
||||||
for (ObjCInterfaceDecl::instmeth_iterator IM = PDecl->instmeth_begin(),
|
for (ObjCInterfaceDecl::instmeth_iterator IM = IDecl->instmeth_begin(),
|
||||||
E = PDecl->instmeth_end(); IM != E; ++IM) {
|
E = IDecl->instmeth_end(); IM != E; ++IM) {
|
||||||
Selector Sel = (*IM)->getSelector();
|
Selector Sel = (*IM)->getSelector();
|
||||||
if (InsMap.count(Sel)) {
|
if (ObjCMethodDecl *ProtoMethodDecl = InstMethodsInProtocols[Sel]) {
|
||||||
ObjCMethodDecl *ProtoMethodDecl = PDecl->getInstanceMethod(Sel);
|
ObjCMethodDecl *ClsMethodDecl = (*IM);
|
||||||
ObjCMethodDecl *ClsMethodDecl = IDecl->getInstanceMethod(Sel);
|
S.WarnConflictingTypedMethods(ClsMethodDecl,
|
||||||
if (ProtoMethodDecl && ClsMethodDecl)
|
ProtoMethodDecl, true, true);
|
||||||
S.WarnConflictingTypedMethods(
|
|
||||||
ClsMethodDecl,
|
|
||||||
ProtoMethodDecl, true, true);
|
|
||||||
InsMap.erase(Sel);
|
|
||||||
}
|
|
||||||
if (InsMap.empty())
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (!ClsMap.empty())
|
}
|
||||||
for (ObjCInterfaceDecl::classmeth_iterator IM = PDecl->classmeth_begin(),
|
for (ObjCInterfaceDecl::classmeth_iterator IM = IDecl->classmeth_begin(),
|
||||||
E = PDecl->classmeth_end(); IM != E; ++IM) {
|
E = IDecl->classmeth_end(); IM != E; ++IM) {
|
||||||
Selector Sel = (*IM)->getSelector();
|
Selector Sel = (*IM)->getSelector();
|
||||||
if (ClsMap.count(Sel)) {
|
if (ObjCMethodDecl *ProtoMethodDecl = ClsMethodsInProtocols[Sel]) {
|
||||||
ObjCMethodDecl *ProtoMethodDecl = PDecl->getClassMethod(Sel);
|
ObjCMethodDecl *ClsMethodDecl = (*IM);
|
||||||
ObjCMethodDecl *ClsMethodDecl = IDecl->getClassMethod(Sel);
|
S.WarnConflictingTypedMethods(ClsMethodDecl,
|
||||||
if (ProtoMethodDecl && ClsMethodDecl)
|
ProtoMethodDecl, true, true);
|
||||||
S.WarnConflictingTypedMethods(
|
|
||||||
ClsMethodDecl,
|
|
||||||
ProtoMethodDecl, true, true);
|
|
||||||
ClsMap.erase(Sel);
|
|
||||||
}
|
|
||||||
if (ClsMap.empty())
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (InsMap.empty() && ClsMap.empty())
|
}
|
||||||
return;
|
|
||||||
|
|
||||||
for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
|
if (const ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(IDecl)) {
|
||||||
PE = PDecl->protocol_end(); PI != PE; ++PI)
|
for (const ObjCCategoryDecl *ClsExtDecl = I->getFirstClassExtension();
|
||||||
MatchMethodsInClassAndOneProtocol(S, InsMap, ClsMap, IDecl, (*PI));
|
ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension())
|
||||||
|
MatchMethodsInClassAndOneProtocol(S, ClsExtDecl, InstMethodsInProtocols,
|
||||||
|
ClsMethodsInProtocols);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// CollectMethodsInProtocols - This routine collects all methods declared
|
||||||
|
/// in class's list and nested qualified protocols. Instance methods and
|
||||||
|
/// class methods have separate containers as they have identical selectors.
|
||||||
|
static void CollectMethodsInProtocols(const ObjCContainerDecl *ContDecl,
|
||||||
|
Sema::ProtocolsMethodsMap &InstMethodsInProtocols,
|
||||||
|
Sema::ProtocolsMethodsMap &ClsMethodsInProtocols) {
|
||||||
|
if (const ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(ContDecl)) {
|
||||||
|
for (ObjCInterfaceDecl::all_protocol_iterator
|
||||||
|
PI = CDecl->all_referenced_protocol_begin(),
|
||||||
|
E = CDecl->all_referenced_protocol_end(); PI != E; ++PI) {
|
||||||
|
ObjCProtocolDecl *PDecl = (*PI);
|
||||||
|
|
||||||
|
for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
|
||||||
|
E = PDecl->instmeth_end(); I != E; ++I) {
|
||||||
|
ObjCMethodDecl *method = *I;
|
||||||
|
ObjCMethodDecl *&ProtocolEntry =
|
||||||
|
InstMethodsInProtocols[method->getSelector()];
|
||||||
|
if (!ProtocolEntry)
|
||||||
|
ProtocolEntry = method;
|
||||||
|
}
|
||||||
|
for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
|
||||||
|
E = PDecl->classmeth_end(); I != E; ++I) {
|
||||||
|
ObjCMethodDecl *method = *I;
|
||||||
|
ObjCMethodDecl *&ProtocolEntry =
|
||||||
|
ClsMethodsInProtocols[method->getSelector()];
|
||||||
|
if (!ProtocolEntry)
|
||||||
|
ProtocolEntry = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ObjCProtocolDecl::protocol_iterator P = PDecl->protocol_begin(),
|
||||||
|
PE = PDecl->protocol_end(); P != PE; ++P)
|
||||||
|
CollectMethodsInProtocols(*P, InstMethodsInProtocols,
|
||||||
|
ClsMethodsInProtocols);
|
||||||
|
}
|
||||||
|
if (CDecl->getSuperClass())
|
||||||
|
CollectMethodsInProtocols(CDecl->getSuperClass(), InstMethodsInProtocols,
|
||||||
|
ClsMethodsInProtocols);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(ContDecl)) {
|
||||||
|
for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
|
||||||
|
E = PDecl->instmeth_end(); I != E; ++I) {
|
||||||
|
ObjCMethodDecl *method = *I;
|
||||||
|
ObjCMethodDecl *&ProtocolEntry =
|
||||||
|
InstMethodsInProtocols[method->getSelector()];
|
||||||
|
if (!ProtocolEntry)
|
||||||
|
ProtocolEntry = method;
|
||||||
|
}
|
||||||
|
for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
|
||||||
|
E = PDecl->classmeth_end(); I != E; ++I) {
|
||||||
|
ObjCMethodDecl *method = *I;
|
||||||
|
ObjCMethodDecl *&ProtocolEntry =
|
||||||
|
ClsMethodsInProtocols[method->getSelector()];
|
||||||
|
if (!ProtocolEntry)
|
||||||
|
ProtocolEntry = method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MatchMethodsInClassAndItsProtocol - Check that any redeclaration of
|
/// MatchMethodsInClassAndItsProtocol - Check that any redeclaration of
|
||||||
/// method in protocol in its qualified class match in their type and
|
/// method in protocol in its qualified class match in their type and
|
||||||
/// issue warnings otherwise.
|
/// issue warnings otherwise.
|
||||||
void Sema::MatchMethodsInClassAndItsProtocol(const ObjCInterfaceDecl *CDecl) {
|
void Sema::MatchMethodsInClassAndItsProtocol(const ObjCInterfaceDecl *CDecl) {
|
||||||
if (CDecl->all_referenced_protocol_begin() ==
|
ProtocolsMethodsMap InstMethodsInProtocols, ClsMethodsInProtocols;
|
||||||
CDecl->all_referenced_protocol_end())
|
CollectMethodsInProtocols(CDecl, InstMethodsInProtocols,
|
||||||
|
ClsMethodsInProtocols);
|
||||||
|
|
||||||
|
if (InstMethodsInProtocols.empty() && ClsMethodsInProtocols.empty())
|
||||||
return;
|
return;
|
||||||
|
MatchMethodsInClassAndOneProtocol(*this, CDecl, InstMethodsInProtocols,
|
||||||
SelectorSet InsMap, ClsMap;
|
ClsMethodsInProtocols);
|
||||||
for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(),
|
|
||||||
E = CDecl->instmeth_end(); I != E; ++I)
|
|
||||||
if (!InsMap.count((*I)->getSelector()))
|
|
||||||
InsMap.insert((*I)->getSelector());
|
|
||||||
|
|
||||||
for (ObjCInterfaceDecl::classmeth_iterator
|
|
||||||
I = CDecl->classmeth_begin(), E = CDecl->classmeth_end(); I != E; ++I)
|
|
||||||
if (!ClsMap.count((*I)->getSelector()))
|
|
||||||
ClsMap.insert((*I)->getSelector());
|
|
||||||
|
|
||||||
if (!InsMap.empty() || !ClsMap.empty())
|
|
||||||
for (ObjCInterfaceDecl::all_protocol_iterator
|
|
||||||
PI = CDecl->all_referenced_protocol_begin(),
|
|
||||||
E = CDecl->all_referenced_protocol_end(); PI != E; ++PI)
|
|
||||||
MatchMethodsInClassAndOneProtocol(*this, InsMap, ClsMap, CDecl, (*PI));
|
|
||||||
|
|
||||||
// Also for class extensions
|
|
||||||
if (!CDecl->getFirstClassExtension())
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (const ObjCCategoryDecl *ClsExtDecl = CDecl->getFirstClassExtension();
|
|
||||||
ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
|
|
||||||
InsMap.clear();
|
|
||||||
ClsMap.clear();
|
|
||||||
for (ObjCCategoryDecl::instmeth_iterator I = ClsExtDecl->instmeth_begin(),
|
|
||||||
E = ClsExtDecl->instmeth_end(); I != E; ++I)
|
|
||||||
if (!InsMap.count((*I)->getSelector()))
|
|
||||||
InsMap.insert((*I)->getSelector());
|
|
||||||
for (ObjCCategoryDecl::classmeth_iterator I = ClsExtDecl->classmeth_begin(),
|
|
||||||
E = ClsExtDecl->classmeth_end(); I != E; ++I)
|
|
||||||
if (!ClsMap.count((*I)->getSelector()))
|
|
||||||
ClsMap.insert((*I)->getSelector());
|
|
||||||
if (InsMap.empty() && ClsMap.empty())
|
|
||||||
continue;
|
|
||||||
for (ObjCInterfaceDecl::all_protocol_iterator
|
|
||||||
PI = CDecl->all_referenced_protocol_begin(),
|
|
||||||
E = CDecl->all_referenced_protocol_end(); PI != E; ++PI)
|
|
||||||
MatchMethodsInClassAndOneProtocol(*this, InsMap, ClsMap, ClsExtDecl, (*PI));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
|
/// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
|
||||||
|
@ -1670,6 +1678,13 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
|
||||||
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
|
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
|
||||||
IMPDecl, CDecl,
|
IMPDecl, CDecl,
|
||||||
IncompleteImpl, true);
|
IncompleteImpl, true);
|
||||||
|
// Check for any type mismtch of methods declared in class
|
||||||
|
// and methods declared in protocol. Do this only when the class
|
||||||
|
// is being implementaed.
|
||||||
|
if (isa<ObjCImplementationDecl>(IMPDecl))
|
||||||
|
if (const ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(CDecl))
|
||||||
|
MatchMethodsInClassAndItsProtocol(I);
|
||||||
|
|
||||||
// check all methods implemented in category against those declared
|
// check all methods implemented in category against those declared
|
||||||
// in its primary class.
|
// in its primary class.
|
||||||
if (ObjCCategoryImplDecl *CatDecl =
|
if (ObjCCategoryImplDecl *CatDecl =
|
||||||
|
|
|
@ -44,3 +44,21 @@
|
||||||
- (void) bak {}
|
- (void) bak {}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
// rdar://6911214
|
||||||
|
@protocol Xint
|
||||||
|
-(void) setX: (int) arg0; // expected-note {{previous definition is here}}
|
||||||
|
+(void) setX: (int) arg0; // expected-note {{previous definition is here}}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface A <Xint>
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface C : A
|
||||||
|
-(void) setX: (C*) arg0; // expected-warning {{conflicting parameter types in declaration of 'setX:': 'int' vs 'C *'}}
|
||||||
|
+(void) setX: (C*) arg0; // expected-warning {{conflicting parameter types in declaration of 'setX:': 'int' vs 'C *'}}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation C
|
||||||
|
-(void) setX: (C*) arg0 {}
|
||||||
|
+(void) setX: (C*) arg0 {}
|
||||||
|
@end
|
||||||
|
|
Loading…
Reference in New Issue