[cfe-commits] r137222 - in /cfe/trunk: include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/IdentifierTable.h include/clang/Sema/Sema.h lib/Sema/SemaDeclObjC.cpp test/SemaObjC/class-protocol-method-match.m test/SemaObjC/dist-object-modifiers.m test/SemaObjC/qualified-protocol-method-conflicts.m
Fariborz Jahanian
fjahanian at apple.com
Wed Aug 10 10:16:30 PDT 2011
Author: fjahanian
Date: Wed Aug 10 12:16:30 2011
New Revision: 137222
URL: http://llvm.org/viewvc/llvm-project?rev=137222&view=rev
Log:
objective-c: Using existing infrastructure for finding
overridden methods to diagnose their type mismatch.
This is a general solution for previous fixes
for // rdar://6191214 and // rdar://9352731
and removes lots of duplicate code.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticGroups.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Basic/IdentifierTable.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
cfe/trunk/test/SemaObjC/class-protocol-method-match.m
cfe/trunk/test/SemaObjC/dist-object-modifiers.m
cfe/trunk/test/SemaObjC/qualified-protocol-method-conflicts.m
Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Wed Aug 10 12:16:30 2011
@@ -187,6 +187,7 @@
def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">;
def Protocol : DiagGroup<"protocol">;
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
+def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">;
def : DiagGroup<"variadic-macros">;
def VariadicMacros : DiagGroup<"variadic-macros">;
def VectorConversions : DiagGroup<"vector-conversions">; // clang specific
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Aug 10 12:16:30 2011
@@ -383,32 +383,72 @@
def note_required_for_protocol_at :
Note<"required for direct or indirect protocol %0">;
+def warn_conflicting_overriding_ret_types : Warning<
+ "conflicting return type in "
+ "declaration of %0: %1 vs %2">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
def warn_conflicting_ret_types : Warning<
"conflicting return type in "
- "%select{implementation|declaration}3 of %0: %1 vs %2">;
+ "implementation of %0: %1 vs %2">;
+
+def warn_conflicting_overriding_ret_type_modifiers : Warning<
+ "conflicting distributed object modifiers on return type "
+ "in declaration of %0">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
def warn_conflicting_ret_type_modifiers : Warning<
"conflicting distributed object modifiers on return type "
- "in %select{implementation|declaration}1 of %0">,
+ "in implementation of %0">,
InGroup<DiagGroup<"distributed-object-modifiers">>;
+
+def warn_non_covariant_overriding_ret_types : Warning<
+ "conflicting return type in "
+ "declaration of %0: %1 vs %2">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
def warn_non_covariant_ret_types : Warning<
"conflicting return type in "
- "%select{implementation|declaration}3 of %0: %1 vs %2">,
+ "implementation of %0: %1 vs %2">,
InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
+def warn_conflicting_overriding_param_types : Warning<
+ "conflicting parameter types in "
+ "declaration of %0: %1 vs %2">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
def warn_conflicting_param_types : Warning<
"conflicting parameter types in "
- "%select{implementation|declaration}3 of %0: %1 vs %2">;
+ "implementation of %0: %1 vs %2">;
def warn_conflicting_param_modifiers : Warning<
"conflicting distributed object modifiers on parameter type "
- "in %select{implementation|declaration}1 of %0">,
+ "in implementation of %0">,
InGroup<DiagGroup<"distributed-object-modifiers">>;
+
+def warn_conflicting_overriding_param_modifiers : Warning<
+ "conflicting distributed object modifiers on parameter type "
+ "in declaration of %0">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
+def warn_non_contravariant_overriding_param_types : Warning<
+ "conflicting parameter types in "
+ "declaration of %0: %1 vs %2">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
def warn_non_contravariant_param_types : Warning<
"conflicting parameter types in "
- "%select{implementation|declaration}3 of %0: %1 vs %2">,
+ "implementation of %0: %1 vs %2">,
InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
+
+def warn_conflicting_overriding_variadic :Warning<
+ "conflicting variadic declaration of method and its "
+ "implementation">,
+ InGroup<OverridingMethodMismatch>, DefaultIgnore;
+
def warn_conflicting_variadic :Warning<
"conflicting variadic declaration of method and its "
- "%select{implementation|declaration}0">;
+ "implementation">;
+
def warn_category_method_impl_match:Warning<
"category is implementing a method which will also be implemented"
" by its primary class">, InGroup<ObjCProtocolMethodImpl>;
Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/IdentifierTable.h?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/IdentifierTable.h (original)
+++ cfe/trunk/include/clang/Basic/IdentifierTable.h Wed Aug 10 12:16:30 2011
@@ -557,11 +557,6 @@
bool operator!=(Selector RHS) const {
return InfoPtr != RHS.InfoPtr;
}
-
- bool operator < (Selector RHS) const {
- return InfoPtr < RHS.InfoPtr;
- }
-
void *getAsOpaquePtr() const {
return reinterpret_cast<void*>(InfoPtr);
}
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Aug 10 12:16:30 2011
@@ -493,39 +493,6 @@
/// a potentially evaluated expression.
typedef SmallVector<std::pair<SourceLocation, Decl *>, 10>
PotentiallyReferencedDecls;
-
- // FIXME. Improve on accessibility.
- class PROTOCOL_METHODS {
- public:
- Selector Sel;
- ObjCMethodDecl *Method;
- PROTOCOL_METHODS(Selector S, ObjCMethodDecl *M)
- : Sel(S), Method(M) {}
- // Allow sorting based on selector's opaque pointer.
- bool operator<(const PROTOCOL_METHODS &b) const {
- return Sel < b.Sel;
- }
- };
-
- /// \brief The set of protocols declared in protocols qualifying a
- /// class.
- typedef SmallVector<PROTOCOL_METHODS, 16> MethodsInProtocols;
-
- class IDENTICAL_SELECTOR_METHODS {
- public:
- SourceLocation Loc;
- ObjCMethodDecl *Method;
- IDENTICAL_SELECTOR_METHODS(SourceLocation L, ObjCMethodDecl *M)
- : Loc(L), Method(M) {}
- // Allow sorting based on selector's source location.
- bool operator<(const IDENTICAL_SELECTOR_METHODS &i) const {
- return !(Loc < i.Loc);
- }
- };
-
- /// \brief Methods with identical selectors to be type-matched against
- /// one another.
- typedef SmallVector<IDENTICAL_SELECTOR_METHODS, 8> IdenticalSelectorMethods;
/// \brief A set of diagnostics that may be emitted.
typedef SmallVector<std::pair<SourceLocation, PartialDiagnostic>, 10>
@@ -1813,12 +1780,7 @@
void WarnExactTypedMethods(ObjCMethodDecl *Method,
ObjCMethodDecl *MethodDecl,
bool IsProtocolMethodDecl);
-
- /// WarnOnMismatchedProtocolMethods - Issues warning on type mismatched
- /// protocols methods and then returns true(matched), or false(mismatched).
- bool WarnOnMismatchedProtocolMethods(ObjCMethodDecl *Method,
- ObjCMethodDecl *MethodDecl);
-
+
bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl,
ObjCInterfaceDecl *IDecl);
@@ -1942,17 +1904,6 @@
bool ImmediateClass,
bool WarnExactMatch=false);
- /// MatchIdenticalSelectorsInProtocols - Check that mathods with
- /// identical selectors in all protocols of this class type match.
- /// Issue warning if they don't.
- void MatchIdenticalSelectorsInProtocols(const ObjCInterfaceDecl *CDecl);
-
- /// MatchMethodsInClassAndItsProtocol - Check that any redeclaration of
- /// method in protocol in its qualified class match in their type and
- /// issue warnings otherwise.
- void MatchMethodsInClassAndItsProtocol(const ObjCInterfaceDecl *CDecl);
-
-
/// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
/// category matches with those implemented in its primary class and
/// warns each time an exact match is found.
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Wed Aug 10 12:16:30 2011
@@ -1075,15 +1075,17 @@
ObjCMethodDecl *MethodImpl,
ObjCMethodDecl *MethodDecl,
bool IsProtocolMethodDecl,
- bool IsDeclaration,
+ bool IsOverridingMode,
bool Warn) {
if (IsProtocolMethodDecl &&
(MethodDecl->getObjCDeclQualifier() !=
MethodImpl->getObjCDeclQualifier())) {
if (Warn) {
- S.Diag(MethodImpl->getLocation(),
- diag::warn_conflicting_ret_type_modifiers)
- << MethodImpl->getDeclName() << IsDeclaration
+ S.Diag(MethodImpl->getLocation(),
+ (IsOverridingMode ?
+ diag::warn_conflicting_overriding_ret_type_modifiers
+ : diag::warn_conflicting_ret_type_modifiers))
+ << MethodImpl->getDeclName()
<< getTypeRange(MethodImpl->getResultTypeSourceInfo());
S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)
<< getTypeRange(MethodDecl->getResultTypeSourceInfo());
@@ -1098,7 +1100,9 @@
if (!Warn)
return false;
- unsigned DiagID = diag::warn_conflicting_ret_types;
+ unsigned DiagID =
+ IsOverridingMode ? diag::warn_conflicting_overriding_ret_types
+ : diag::warn_conflicting_ret_types;
// Mismatches between ObjC pointers go into a different warning
// category, and sometimes they're even completely whitelisted.
@@ -1113,7 +1117,9 @@
if (isObjCTypeSubstitutable(S.Context, IfacePtrTy, ImplPtrTy, false))
return false;
- DiagID = diag::warn_non_covariant_ret_types;
+ DiagID =
+ IsOverridingMode ? diag::warn_non_covariant_overriding_ret_types
+ : diag::warn_non_covariant_ret_types;
}
}
@@ -1121,9 +1127,10 @@
<< MethodImpl->getDeclName()
<< MethodDecl->getResultType()
<< MethodImpl->getResultType()
- << IsDeclaration
<< getTypeRange(MethodImpl->getResultTypeSourceInfo());
- S.Diag(MethodDecl->getLocation(), diag::note_previous_definition)
+ S.Diag(MethodDecl->getLocation(),
+ IsOverridingMode ? diag::note_previous_declaration
+ : diag::note_previous_definition)
<< getTypeRange(MethodDecl->getResultTypeSourceInfo());
return false;
}
@@ -1134,16 +1141,21 @@
ParmVarDecl *ImplVar,
ParmVarDecl *IfaceVar,
bool IsProtocolMethodDecl,
- bool IsDeclaration,
+ bool IsOverridingMode,
bool Warn) {
if (IsProtocolMethodDecl &&
(ImplVar->getObjCDeclQualifier() !=
IfaceVar->getObjCDeclQualifier())) {
if (Warn) {
- S.Diag(ImplVar->getLocation(),
+ if (IsOverridingMode)
+ S.Diag(ImplVar->getLocation(),
+ diag::warn_conflicting_overriding_param_modifiers)
+ << getTypeRange(ImplVar->getTypeSourceInfo())
+ << MethodImpl->getDeclName();
+ else S.Diag(ImplVar->getLocation(),
diag::warn_conflicting_param_modifiers)
<< getTypeRange(ImplVar->getTypeSourceInfo())
- << MethodImpl->getDeclName() << IsDeclaration;
+ << MethodImpl->getDeclName();
S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration)
<< getTypeRange(IfaceVar->getTypeSourceInfo());
}
@@ -1159,7 +1171,9 @@
if (!Warn)
return false;
- unsigned DiagID = diag::warn_conflicting_param_types;
+ unsigned DiagID =
+ IsOverridingMode ? diag::warn_conflicting_overriding_param_types
+ : diag::warn_conflicting_param_types;
// Mismatches between ObjC pointers go into a different warning
// category, and sometimes they're even completely whitelisted.
@@ -1174,15 +1188,18 @@
if (isObjCTypeSubstitutable(S.Context, ImplPtrTy, IfacePtrTy, true))
return false;
- DiagID = diag::warn_non_contravariant_param_types;
+ DiagID =
+ IsOverridingMode ? diag::warn_non_contravariant_overriding_param_types
+ : diag::warn_non_contravariant_param_types;
}
}
S.Diag(ImplVar->getLocation(), DiagID)
<< getTypeRange(ImplVar->getTypeSourceInfo())
- << MethodImpl->getDeclName() << IfaceTy << ImplTy
- << IsDeclaration;
- S.Diag(IfaceVar->getLocation(), diag::note_previous_definition)
+ << MethodImpl->getDeclName() << IfaceTy << ImplTy;
+ S.Diag(IfaceVar->getLocation(),
+ (IsOverridingMode ? diag::note_previous_declaration
+ : diag::note_previous_definition))
<< getTypeRange(IfaceVar->getTypeSourceInfo());
return false;
}
@@ -1260,54 +1277,31 @@
void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
ObjCMethodDecl *MethodDecl,
bool IsProtocolMethodDecl,
- bool IsDeclaration) {
+ bool IsOverridingMode) {
if (getLangOptions().ObjCAutoRefCount &&
+ !IsOverridingMode &&
checkMethodFamilyMismatch(*this, ImpMethodDecl, MethodDecl))
return;
CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl,
- IsProtocolMethodDecl, IsDeclaration, true);
+ IsProtocolMethodDecl, IsOverridingMode,
+ true);
for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
- IM != EM; ++IM, ++IF)
+ IM != EM; ++IM, ++IF) {
CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF,
- IsProtocolMethodDecl, IsDeclaration, true);
-
- if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) {
- Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic)
- << IsDeclaration;
- Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
+ IsProtocolMethodDecl, IsOverridingMode, true);
}
-}
-/// WarnOnMismatchedProtocolMethods - Issues warning on type mismatched
-/// protocols methods and then returns true(matched), or false(mismatched).
-bool Sema::WarnOnMismatchedProtocolMethods(ObjCMethodDecl *ImpMethodDecl,
- ObjCMethodDecl *MethodDecl) {
-
- bool match = CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl,
- true,
- true, true);
- if (!match)
- return false;
-
- for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
- IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end();
- IM != EM; ++IM, ++IF) {
- match = CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF,
- true, true, true);
- if (!match)
- return false;
- }
-
if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) {
- Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic)
- << true;
+ if (IsOverridingMode)
+ Diag(ImpMethodDecl->getLocation(),
+ diag::warn_conflicting_overriding_variadic);
+ else
+ Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic);
Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
- return false;
}
- return true;
}
/// WarnExactTypedMethods - This routine issues a warning if method
@@ -1539,214 +1533,6 @@
}
}
-/// MatchMethodsInClassAndProtocols - 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 MatchMethodsInClassAndProtocols(Sema &S,
- const ObjCContainerDecl *IDecl,
- Sema::ProtocolsMethodsMap &InstMethodsInProtocols,
- Sema::ProtocolsMethodsMap &ClsMethodsInProtocols) {
- for (ObjCInterfaceDecl::instmeth_iterator IM = IDecl->instmeth_begin(),
- E = IDecl->instmeth_end(); IM != E; ++IM) {
- Selector Sel = (*IM)->getSelector();
- if (ObjCMethodDecl *ProtoMethodDecl = InstMethodsInProtocols[Sel]) {
- ObjCMethodDecl *ClsMethodDecl = (*IM);
- S.WarnConflictingTypedMethods(ClsMethodDecl,
- ProtoMethodDecl, true, true);
- }
- }
- for (ObjCInterfaceDecl::classmeth_iterator IM = IDecl->classmeth_begin(),
- E = IDecl->classmeth_end(); IM != E; ++IM) {
- Selector Sel = (*IM)->getSelector();
- if (ObjCMethodDecl *ProtoMethodDecl = ClsMethodsInProtocols[Sel]) {
- ObjCMethodDecl *ClsMethodDecl = (*IM);
- S.WarnConflictingTypedMethods(ClsMethodDecl,
- ProtoMethodDecl, true, true);
- }
- }
-
- if (const ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(IDecl)) {
- for (const ObjCCategoryDecl *ClsExtDecl = I->getFirstClassExtension();
- ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension())
- MatchMethodsInClassAndProtocols(S, ClsExtDecl, InstMethodsInProtocols,
- ClsMethodsInProtocols);
- }
-}
-
-/// CollectMethodsInOneProtocol - This routine collects all methods declared
-/// in a given protocol.
-static void CollectMethodsInOneProtocol(const ObjCProtocolDecl *PDecl,
- Sema::ProtocolsMethodsMap &InstMethodsInProtocols,
- Sema::ProtocolsMethodsMap &ClsMethodsInProtocols) {
- 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;
- }
-}
-
-/// CollectAllMethodsInProtocols - Helper routine to collect all methods
-/// declared in given class's immediate and nested protocols.
-static void CollectAllMethodsInProtocols(const ObjCContainerDecl *ContDecl,
- Sema::MethodsInProtocols &InstMethodsInProtocols,
- Sema::MethodsInProtocols & 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)
- CollectAllMethodsInProtocols(*PI, 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;
- InstMethodsInProtocols.push_back(Sema::PROTOCOL_METHODS(method->getSelector(),
- method));
- }
- for (ObjCProtocolDecl::classmeth_iterator I = PDecl->classmeth_begin(),
- E = PDecl->classmeth_end(); I != E; ++I) {
- ObjCMethodDecl *method = *I;
- ClsMethodsInProtocols.push_back(Sema::PROTOCOL_METHODS(method->getSelector(),
- method));
- }
-
- for (ObjCProtocolDecl::protocol_iterator
- PI = PDecl->protocol_begin(),
- E = PDecl->protocol_end(); PI != E; ++PI)
- CollectAllMethodsInProtocols(*PI, 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);
- CollectMethodsInOneProtocol(PDecl, InstMethodsInProtocols,
- ClsMethodsInProtocols);
-
- 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))
- CollectMethodsInOneProtocol(PDecl, InstMethodsInProtocols,
- ClsMethodsInProtocols);
-
-}
-
-/// MatchMethodsInClassAndItsProtocol - Check that any redeclaration of
-/// method in protocol in its qualified class match in their type and
-/// issue warnings otherwise.
-void Sema::MatchMethodsInClassAndItsProtocol(const ObjCInterfaceDecl *CDecl) {
- ProtocolsMethodsMap InstMethodsInProtocols, ClsMethodsInProtocols;
- CollectMethodsInProtocols(CDecl, InstMethodsInProtocols,
- ClsMethodsInProtocols);
-
- if (InstMethodsInProtocols.empty() && ClsMethodsInProtocols.empty())
- return;
- MatchMethodsInClassAndProtocols(*this, CDecl, InstMethodsInProtocols,
- ClsMethodsInProtocols);
-}
-
-/// MatchMethodsWithIdenticalSelectors - Helper routine to go through list
-/// of identical selector lists and issue warning for any type mismatche
-/// of these methods.
-static bool MatchMethodsWithIdenticalSelectors(Sema &S,
- const Sema::MethodsInProtocols Methods) {
- bool res = true;
- int size = Methods.size();
- int i = 0;
- while (i < size) {
- int upper = i;
- while (upper < size &&
- (Methods[i].Sel == Methods[upper].Sel))
- upper++;
- if (upper > i) {
- int lo = i;
- int hi = upper - 1;
-
- if (lo < hi) {
- Sema::IdenticalSelectorMethods SelectedMethods;
- for (int l = lo; l <= hi; l++) {
- ObjCMethodDecl *method = Methods[l].Method;
- Sema::IDENTICAL_SELECTOR_METHODS
- SelectedMethod(method->getLocation(), method);
- SelectedMethods.push_back(SelectedMethod);
- }
- llvm::array_pod_sort(SelectedMethods.begin(), SelectedMethods.end());
- lo = 0; hi = SelectedMethods.size()-1;
- while (lo < hi) {
- ObjCMethodDecl *targetMethod = SelectedMethods[lo].Method;
- for (int j = lo+1; j <= hi; j++) {
- // match two methods;
- ObjCMethodDecl *otherMethod = SelectedMethods[j].Method;
- if (!S.WarnOnMismatchedProtocolMethods(targetMethod, otherMethod))
- res = false;
- }
- ++lo;
- }
- }
- }
- i += upper;
- }
- return res;
-}
-
-/// MatchIdenticalSelectorsInProtocols - Main routine to go through list of
-/// class's protocols (and their protocols) and make sure that methods
-/// type match across all protocols and issue warnings if they don't.
-/// FIXME. This may move to static analyzer if performance is proven
-/// prohibitive.
-void Sema::MatchIdenticalSelectorsInProtocols(const ObjCInterfaceDecl *CDecl) {
- Sema::MethodsInProtocols InsMethods;
- Sema::MethodsInProtocols ClsMethods;
- CollectAllMethodsInProtocols(CDecl, InsMethods, ClsMethods);
-
- bool match = true;
- if (!InsMethods.empty()) {
- llvm::array_pod_sort(InsMethods.begin(), InsMethods.end());
- if (!MatchMethodsWithIdenticalSelectors(*this, InsMethods))
- match = false;
- }
-
- if (!ClsMethods.empty()) {
- llvm::array_pod_sort(ClsMethods.begin(), ClsMethods.end());
- if (!MatchMethodsWithIdenticalSelectors(*this, ClsMethods))
- match = false;
- }
- if (!match)
- Diag(CDecl->getLocation() ,diag::note_class_declared);
-}
-
-
/// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
/// category matches with those implemented in its primary class and
/// warns each time an exact match is found.
@@ -1809,14 +1595,6 @@
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
IMPDecl, CDecl,
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)) {
- MatchIdenticalSelectorsInProtocols(I);
- MatchMethodsInClassAndItsProtocol(I);
- }
// check all methods implemented in category against those declared
// in its primary class.
@@ -2828,6 +2606,13 @@
// Then merge the declarations.
mergeObjCMethodDecls(ObjCMethod, overridden);
+
+ // Check for overriding methods
+ if (isa<ObjCInterfaceDecl>(ObjCMethod->getDeclContext()) ||
+ isa<ObjCImplementationDecl>(ObjCMethod->getDeclContext())) {
+ WarnConflictingTypedMethods(ObjCMethod, overridden,
+ isa<ObjCProtocolDecl>(overridden->getDeclContext()), true);
+ }
}
bool ARCError = false;
Modified: cfe/trunk/test/SemaObjC/class-protocol-method-match.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/class-protocol-method-match.m?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/class-protocol-method-match.m (original)
+++ cfe/trunk/test/SemaObjC/class-protocol-method-match.m Wed Aug 10 12:16:30 2011
@@ -1,64 +1,48 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -Woverriding-method-mismatch -fsyntax-only -verify %s
// rdar://9352731
@protocol Bar
@required
-- (unsigned char) baz; // expected-note {{previous definition is here}}
-- (char) ok; // expected-note {{previous definition is here}}
+- (bycopy id)bud; // expected-note {{previous declaration is here}}
+- (unsigned char) baz; // expected-note {{previous declaration is here}}
+- (char) ok;
- (void) also_ok;
@end
@protocol Bar1
@required
-- (unsigned char) baz;
-- (unsigned char) also_ok;
+- (unsigned char) baz; // expected-note {{previous declaration is here}}
+- (unsigned char) also_ok; // expected-note {{previous declaration is here}}
- (void) ban : (int) arg, ...; // expected-note {{previous declaration is here}}
@end
@protocol Baz <Bar, Bar1>
-- (void) bar : (unsigned char)arg; // expected-note {{previous definition is here}}
-- (void) ok; // expected-warning {{conflicting return type in declaration of 'ok': 'char' vs 'void'}}
-- (char) bak; // expected-note {{previous definition is here}}
+- (void) bar : (unsigned char)arg; // expected-note {{previous declaration is here}}
+- (void) ok;
+- (char) bak; // expected-note {{previous declaration is here}}
@end
- at interface Foo <Baz> // expected-note {{class is declared here}}
-- (void) baz; // expected-warning {{conflicting return type in declaration of 'baz': 'unsigned char' vs 'void'}}
+ at interface Foo <Baz>
+- (id)bud; // expected-warning {{conflicting distributed object modifiers on return type in declaration of 'bud'}}
+- (void) baz; // expected-warning 2 {{conflicting return type in declaration of 'baz': 'unsigned char' vs 'void'}}
- (void) bar : (unsigned char*)arg; // expected-warning {{conflicting parameter types in declaration of 'bar:': 'unsigned char' vs 'unsigned char *'}}
- (void) ok;
-- (void) also_ok;
+- (void) also_ok; // expected-warning {{conflicting return type in declaration of 'also_ok': 'unsigned char' vs 'void'}}
- (void) still_ok;
-- (void) ban : (int) arg; // expected-warning {{conflicting variadic declaration of method and its declaration}}
+- (void) ban : (int) arg; // expected-warning {{conflicting variadic declaration of method and its implementation}}
@end
@interface Foo()
-- (void) bak; // expected-warning {{conflicting return type in declaration of 'bak': 'char' vs 'void'}}
+- (void) bak;
@end
@implementation Foo
+- (bycopy id)bud { return 0; }
- (void) baz {}
- (void) bar : (unsigned char*)arg {}
- (void) ok {}
- (void) also_ok {}
- (void) still_ok {}
- (void) ban : (int) arg {}
-- (void) bak {}
- at end
-
-// rdar://6911214
- at protocol Xint
--(void) setX: (int) arg0; // expected-note {{previous definition is here}}
-+(void) setX: (int) arg0; // expected-note {{previous definition is here}}
- at end
-
- at interface A <Xint>
- at end
-
- at 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 *'}}
- at end
-
- at implementation C
--(void) setX: (C*) arg0 {}
-+(void) setX: (C*) arg0 {}
+- (void) bak {} // expected-warning {{conflicting return type in declaration of 'bak': 'char' vs 'void'}}
@end
Modified: cfe/trunk/test/SemaObjC/dist-object-modifiers.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/dist-object-modifiers.m?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/dist-object-modifiers.m (original)
+++ cfe/trunk/test/SemaObjC/dist-object-modifiers.m Wed Aug 10 12:16:30 2011
@@ -4,12 +4,12 @@
@protocol P
- (bycopy id)serverPID; // expected-note {{previous declaration is here}}
- (void)doStuff:(bycopy id)clientId; // expected-note {{previous declaration is here}}
-- (bycopy id)Ok; // expected-note {{previous declaration is here}}
+- (bycopy id)Ok;
+ (oneway id) stillMore : (byref id)Arg : (bycopy oneway id)Arg1; // expected-note 3 {{previous declaration is here}}
@end
@interface I <P>
-- (id)Ok; // expected-warning {{conflicting distributed object modifiers on return type in declaration of 'Ok'}}
+- (id)Ok;
@end
@implementation I
Modified: cfe/trunk/test/SemaObjC/qualified-protocol-method-conflicts.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/qualified-protocol-method-conflicts.m?rev=137222&r1=137221&r2=137222&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/qualified-protocol-method-conflicts.m (original)
+++ cfe/trunk/test/SemaObjC/qualified-protocol-method-conflicts.m Wed Aug 10 12:16:30 2011
@@ -1,39 +1,39 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -Woverriding-method-mismatch -fsyntax-only -verify %s
// rdar://6191214
@protocol Xint
--(void) setX: (int) arg0; // expected-note 3 {{previous definition is here}}
-+(int) C; // expected-note 3 {{previous definition is here}}
+-(void) setX: (int) arg0; // expected-note {{previous declaration is here}}
++(int) C; // expected-note {{previous declaration is here}}
@end
@protocol Xfloat
--(void) setX: (float) arg0; // expected-warning 3 {{conflicting parameter types in declaration of 'setX:': 'int' vs 'float'}}
-+(float) C; // expected-warning 3 {{conflicting return type in declaration of 'C': 'int' vs 'float'}}
+-(void) setX: (float) arg0; // expected-note 2 {{previous declaration is here}}
++(float) C; // expected-note 2 {{previous declaration is here}}
@end
- at interface A <Xint, Xfloat> // expected-note {{class is declared here}}
+ at interface A <Xint, Xfloat>
@end
@implementation A
--(void) setX: (int) arg0 { }
-+(int) C {return 0; }
+-(void) setX: (int) arg0 { } // expected-warning {{conflicting parameter types in declaration of 'setX:': 'float' vs 'int'}}
++(int) C {return 0; } // expected-warning {{conflicting return type in declaration of 'C': 'float' vs 'int'}}
@end
- at interface B <Xfloat, Xint> // expected-note {{class is declared here}}
+ at interface B <Xfloat, Xint>
@end
@implementation B
--(void) setX: (float) arg0 { }
-+ (float) C {return 0.0; }
+-(void) setX: (float) arg0 { } // expected-warning {{conflicting parameter types in declaration of 'setX:': 'int' vs 'float'}}
++ (float) C {return 0.0; } // expected-warning {{conflicting return type in declaration of 'C': 'int' vs 'float'}}
@end
@protocol Xint_float<Xint, Xfloat>
@end
- at interface C<Xint_float> // expected-note {{class is declared here}}
+ at interface C<Xint_float>
@end
@implementation C
--(void) setX: (int) arg0 { }
-+ (int) C {return 0;}
+-(void) setX: (int) arg0 { } // expected-warning {{conflicting parameter types in declaration of 'setX:': 'float' vs 'int'}}
++ (int) C {return 0;} // expected-warning {{conflicting return type in declaration of 'C': 'float' vs 'int'}}
@end
More information about the cfe-commits
mailing list