aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclObjC.cpp
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2011-07-24 20:53:26 +0000
committerFariborz Jahanian <fjahanian@apple.com>2011-07-24 20:53:26 +0000
commiteee3ef177a171c06f826c331e7a9e256d01eaeb0 (patch)
tree6d361dd21e7528f13178711bc5bcf999d345fd54 /lib/Sema/SemaDeclObjC.cpp
parent335608a778db3398aca12e3c855ecfa5ff11c5c9 (diff)
objc: clang should warn if redeclaration of methods
declared in protocol in the class qualified by the protocol have type conflicts. To reduce amount of noise, this is done when class is implemented. // rdar://9352731 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135890 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclObjC.cpp')
-rw-r--r--lib/Sema/SemaDeclObjC.cpp122
1 files changed, 113 insertions, 9 deletions
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index da3bedd12a..e9a39b614e 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1074,13 +1074,14 @@ static SourceRange getTypeRange(TypeSourceInfo *TSI) {
static void CheckMethodOverrideReturn(Sema &S,
ObjCMethodDecl *MethodImpl,
ObjCMethodDecl *MethodDecl,
- bool IsProtocolMethodDecl) {
+ bool IsProtocolMethodDecl,
+ bool IsDeclaration) {
if (IsProtocolMethodDecl &&
(MethodDecl->getObjCDeclQualifier() !=
MethodImpl->getObjCDeclQualifier())) {
S.Diag(MethodImpl->getLocation(),
diag::warn_conflicting_ret_type_modifiers)
- << MethodImpl->getDeclName()
+ << MethodImpl->getDeclName() << IsDeclaration
<< getTypeRange(MethodImpl->getResultTypeSourceInfo());
S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)
<< getTypeRange(MethodDecl->getResultTypeSourceInfo());
@@ -1113,6 +1114,7 @@ static void CheckMethodOverrideReturn(Sema &S,
<< MethodImpl->getDeclName()
<< MethodDecl->getResultType()
<< MethodImpl->getResultType()
+ << IsDeclaration
<< getTypeRange(MethodImpl->getResultTypeSourceInfo());
S.Diag(MethodDecl->getLocation(), diag::note_previous_definition)
<< getTypeRange(MethodDecl->getResultTypeSourceInfo());
@@ -1123,14 +1125,15 @@ static void CheckMethodOverrideParam(Sema &S,
ObjCMethodDecl *MethodDecl,
ParmVarDecl *ImplVar,
ParmVarDecl *IfaceVar,
- bool IsProtocolMethodDecl) {
+ bool IsProtocolMethodDecl,
+ bool IsDeclaration) {
if (IsProtocolMethodDecl &&
(ImplVar->getObjCDeclQualifier() !=
IfaceVar->getObjCDeclQualifier())) {
S.Diag(ImplVar->getLocation(),
diag::warn_conflicting_param_modifiers)
<< getTypeRange(ImplVar->getTypeSourceInfo())
- << MethodImpl->getDeclName();
+ << MethodImpl->getDeclName() << IsDeclaration;
S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration)
<< getTypeRange(IfaceVar->getTypeSourceInfo());
}
@@ -1162,7 +1165,8 @@ static void CheckMethodOverrideParam(Sema &S,
S.Diag(ImplVar->getLocation(), DiagID)
<< getTypeRange(ImplVar->getTypeSourceInfo())
- << MethodImpl->getDeclName() << IfaceTy << ImplTy;
+ << MethodImpl->getDeclName() << IfaceTy << ImplTy
+ << IsDeclaration;
S.Diag(IfaceVar->getLocation(), diag::note_previous_definition)
<< getTypeRange(IfaceVar->getTypeSourceInfo());
}
@@ -1239,22 +1243,24 @@ static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl,
void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
ObjCMethodDecl *MethodDecl,
- bool IsProtocolMethodDecl) {
+ bool IsProtocolMethodDecl,
+ bool IsDeclaration) {
if (getLangOptions().ObjCAutoRefCount &&
checkMethodFamilyMismatch(*this, ImpMethodDecl, MethodDecl))
return;
CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl,
- IsProtocolMethodDecl);
+ IsProtocolMethodDecl, IsDeclaration);
for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
IM != EM; ++IM, ++IF)
CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF,
- IsProtocolMethodDecl);
+ IsProtocolMethodDecl, IsDeclaration);
if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) {
- Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic);
+ Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic)
+ << IsDeclaration;
Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
}
}
@@ -1427,6 +1433,11 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
IMPDecl,
(*PI), IncompleteImpl, false);
+
+ // Check for any type mismtch of methods declared in class
+ // and methods declared in protocol.
+ MatchMethodsInClassAndItsProtocol(I);
+
if (I->getSuperClass())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
IMPDecl,
@@ -1434,6 +1445,99 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
}
}
+static void MatchMethodsInClassAndOneProtocol(Sema &S,
+ Sema::SelectorSet &InsMap,
+ Sema::SelectorSet &ClsMap,
+ const ObjCContainerDecl *IDecl,
+ const ObjCProtocolDecl *PDecl) {
+ if (!InsMap.empty())
+ for (ObjCInterfaceDecl::instmeth_iterator IM = PDecl->instmeth_begin(),
+ E = PDecl->instmeth_end(); IM != E; ++IM) {
+ Selector Sel = (*IM)->getSelector();
+ if (InsMap.count(Sel)) {
+ ObjCMethodDecl *ProtoMethodDecl = PDecl->getInstanceMethod(Sel);
+ ObjCMethodDecl *ClsMethodDecl = IDecl->getInstanceMethod(Sel);
+ if (ProtoMethodDecl && ClsMethodDecl)
+ S.WarnConflictingTypedMethods(
+ ClsMethodDecl,
+ ProtoMethodDecl, true, true);
+ InsMap.erase(Sel);
+ }
+ if (InsMap.empty())
+ break;
+ }
+ if (!ClsMap.empty())
+ for (ObjCInterfaceDecl::classmeth_iterator IM = PDecl->classmeth_begin(),
+ E = PDecl->classmeth_end(); IM != E; ++IM) {
+ Selector Sel = (*IM)->getSelector();
+ if (ClsMap.count(Sel)) {
+ ObjCMethodDecl *ProtoMethodDecl = PDecl->getClassMethod(Sel);
+ ObjCMethodDecl *ClsMethodDecl = IDecl->getClassMethod(Sel);
+ if (ProtoMethodDecl && ClsMethodDecl)
+ 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(),
+ PE = PDecl->protocol_end(); PI != PE; ++PI)
+ MatchMethodsInClassAndOneProtocol(S, InsMap, ClsMap, IDecl, (*PI));
+}
+
+void Sema::MatchMethodsInClassAndItsProtocol(const ObjCInterfaceDecl *CDecl) {
+ if (CDecl->all_referenced_protocol_begin() ==
+ CDecl->all_referenced_protocol_end())
+ return;
+
+ SelectorSet InsMap, ClsMap;
+ 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));
+ }
+}
+
+
void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
ObjCContainerDecl* CDecl,
bool IncompleteImpl) {