[cfe-commits] r150206 - in /cfe/trunk: include/clang/AST/DeclObjC.h include/clang/Sema/Sema.h lib/AST/DeclObjC.cpp lib/Sema/SemaDeclObjC.cpp test/SemaObjC/method-undef-category-warn-1.m
Fariborz Jahanian
fjahanian at apple.com
Thu Feb 9 13:30:24 PST 2012
Author: fjahanian
Date: Thu Feb 9 15:30:24 2012
New Revision: 150206
URL: http://llvm.org/viewvc/llvm-project?rev=150206&view=rev
Log:
objc: If a method is not implemented in the category implementation but
has been declared in its primary class, superclass,
or in one of their protocols, no need to issue unimplemented method.
// rdar://10823023
Modified:
cfe/trunk/include/clang/AST/DeclObjC.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/AST/DeclObjC.cpp
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
cfe/trunk/test/SemaObjC/method-undef-category-warn-1.m
Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=150206&r1=150205&r2=150206&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Thu Feb 9 15:30:24 2012
@@ -898,12 +898,15 @@
// Lookup a method. First, we search locally. If a method isn't
// found, we search referenced protocols and class categories.
- ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance) const;
- ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const {
- return lookupMethod(Sel, true/*isInstance*/);
- }
- ObjCMethodDecl *lookupClassMethod(Selector Sel) const {
- return lookupMethod(Sel, false/*isInstance*/);
+ ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance,
+ bool noCategoryLookup= false) const;
+ ObjCMethodDecl *lookupInstanceMethod(Selector Sel,
+ bool noCategoryLookup = false) const {
+ return lookupMethod(Sel, true/*isInstance*/, noCategoryLookup);
+ }
+ ObjCMethodDecl *lookupClassMethod(Selector Sel,
+ bool noCategoryLookup = false) const {
+ return lookupMethod(Sel, false/*isInstance*/, noCategoryLookup);
}
ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=150206&r1=150205&r2=150206&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Feb 9 15:30:24 2012
@@ -1964,7 +1964,7 @@
ObjCContainerDecl* IDecl,
bool &IncompleteImpl,
bool ImmediateClass,
- bool WarnExactMatch=false);
+ bool WarnCategoryMethodImpl=false);
/// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
/// category matches with those implemented in its primary class and
Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=150206&r1=150205&r2=150206&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Thu Feb 9 15:30:24 2012
@@ -317,7 +317,8 @@
/// lookupMethod - This method returns an instance/class method by looking in
/// the class, its categories, and its super classes (using a linear search).
ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
- bool isInstance) const {
+ bool isInstance,
+ bool noCategoryLookup) const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
return 0;
@@ -339,21 +340,22 @@
E = Protocols.end(); I != E; ++I)
if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
return MethodDecl;
-
- // Didn't find one yet - now look through categories.
- ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList();
- while (CatDecl) {
- if ((MethodDecl = CatDecl->getMethod(Sel, isInstance)))
- return MethodDecl;
-
- // Didn't find one yet - look through protocols.
- const ObjCList<ObjCProtocolDecl> &Protocols =
- CatDecl->getReferencedProtocols();
- for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
- E = Protocols.end(); I != E; ++I)
- if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
+ if (!noCategoryLookup) {
+ // Didn't find one yet - now look through categories.
+ ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList();
+ while (CatDecl) {
+ if ((MethodDecl = CatDecl->getMethod(Sel, isInstance)))
return MethodDecl;
- CatDecl = CatDecl->getNextClassCategory();
+
+ // Didn't find one yet - look through protocols.
+ const ObjCList<ObjCProtocolDecl> &Protocols =
+ CatDecl->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end(); I != E; ++I)
+ if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
+ return MethodDecl;
+ CatDecl = CatDecl->getNextClassCategory();
+ }
}
ClassDecl = ClassDecl->getSuperClass();
}
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=150206&r1=150205&r2=150206&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Thu Feb 9 15:30:24 2012
@@ -1465,11 +1465,9 @@
const llvm::DenseSet<Selector> &InsMap,
const llvm::DenseSet<Selector> &ClsMap,
ObjCContainerDecl *CDecl) {
- ObjCInterfaceDecl *IDecl;
- if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl))
- IDecl = C->getClassInterface();
- else
- IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
+ ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
+ ObjCInterfaceDecl *IDecl = C ? C->getClassInterface()
+ : dyn_cast<ObjCInterfaceDecl>(CDecl);
assert (IDecl && "CheckProtocolMethodDefs - IDecl is null");
ObjCInterfaceDecl *Super = IDecl->getSuperClass();
@@ -1504,20 +1502,27 @@
!method->isSynthesized() && !InsMap.count(method->getSelector()) &&
(!Super ||
!Super->lookupInstanceMethod(method->getSelector()))) {
+ // If a method is not implemented in the category implementation but
+ // has been declared in its primary class, superclass,
+ // or in one of their protocols, no need to issue the warning.
+ // This is because method will be implemented in the primary class
+ // or one of its super class implementation.
+
// Ugly, but necessary. Method declared in protcol might have
// have been synthesized due to a property declared in the class which
// uses the protocol.
- ObjCMethodDecl *MethodInClass =
- IDecl->lookupInstanceMethod(method->getSelector());
- if (!MethodInClass || !MethodInClass->isSynthesized()) {
- unsigned DIAG = diag::warn_unimplemented_protocol_method;
- if (Diags.getDiagnosticLevel(DIAG, ImpLoc)
- != DiagnosticsEngine::Ignored) {
- WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG);
- Diag(method->getLocation(), diag::note_method_declared_at);
- Diag(CDecl->getLocation(), diag::note_required_for_protocol_at)
- << PDecl->getDeclName();
- }
+ if (ObjCMethodDecl *MethodInClass =
+ IDecl->lookupInstanceMethod(method->getSelector(),
+ true /*noCategoryLookup*/))
+ if (C || MethodInClass->isSynthesized())
+ continue;
+ unsigned DIAG = diag::warn_unimplemented_protocol_method;
+ if (Diags.getDiagnosticLevel(DIAG, ImpLoc)
+ != DiagnosticsEngine::Ignored) {
+ WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG);
+ Diag(method->getLocation(), diag::note_method_declared_at);
+ Diag(CDecl->getLocation(), diag::note_required_for_protocol_at)
+ << PDecl->getDeclName();
}
}
}
@@ -1529,6 +1534,10 @@
if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
!ClsMap.count(method->getSelector()) &&
(!Super || !Super->lookupClassMethod(method->getSelector()))) {
+ // See above comment for instance method lookups.
+ if (C && IDecl->lookupClassMethod(method->getSelector(),
+ true /*noCategoryLookup*/))
+ continue;
unsigned DIAG = diag::warn_unimplemented_protocol_method;
if (Diags.getDiagnosticLevel(DIAG, ImpLoc) !=
DiagnosticsEngine::Ignored) {
@@ -1542,7 +1551,7 @@
// Check on this protocols's referenced protocols, recursively.
for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
E = PDecl->protocol_end(); PI != E; ++PI)
- CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, IDecl);
+ CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, CDecl);
}
/// MatchAllMethodDeclarations - Check methods declared in interface
@@ -1556,7 +1565,7 @@
ObjCContainerDecl* CDecl,
bool &IncompleteImpl,
bool ImmediateClass,
- bool WarnExactMatch) {
+ bool WarnCategoryMethodImpl) {
// 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(),
@@ -1578,12 +1587,12 @@
ObjCMethodDecl *MethodDecl = *I;
// ImpMethodDecl may be null as in a @dynamic property.
if (ImpMethodDecl) {
- if (!WarnExactMatch)
+ if (!WarnCategoryMethodImpl)
WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl,
isa<ObjCProtocolDecl>(CDecl));
else if (!MethodDecl->isSynthesized())
WarnExactTypedMethods(ImpMethodDecl, MethodDecl,
- isa<ObjCProtocolDecl>(CDecl));
+ isa<ObjCProtocolDecl>(CDecl));
}
}
}
@@ -1605,12 +1614,12 @@
assert(CDecl->getClassMethod((*I)->getSelector()) &&
"Expected to find the method through lookup as well");
ObjCMethodDecl *MethodDecl = *I;
- if (!WarnExactMatch)
+ if (!WarnCategoryMethodImpl)
WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl,
isa<ObjCProtocolDecl>(CDecl));
else
WarnExactTypedMethods(ImpMethodDecl, MethodDecl,
- isa<ObjCProtocolDecl>(CDecl));
+ isa<ObjCProtocolDecl>(CDecl));
}
}
@@ -1621,7 +1630,8 @@
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
IMPDecl,
const_cast<ObjCCategoryDecl *>(ClsExtDecl),
- IncompleteImpl, false, WarnExactMatch);
+ IncompleteImpl, false,
+ WarnCategoryMethodImpl);
// Check for any implementation of a methods declared in protocol.
for (ObjCInterfaceDecl::all_protocol_iterator
@@ -1629,11 +1639,12 @@
E = I->all_referenced_protocol_end(); PI != E; ++PI)
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
IMPDecl,
- (*PI), IncompleteImpl, false, WarnExactMatch);
+ (*PI), IncompleteImpl, false,
+ WarnCategoryMethodImpl);
// FIXME. For now, we are not checking for extact match of methods
// in category implementation and its primary class's super class.
- if (!WarnExactMatch && I->getSuperClass())
+ if (!WarnCategoryMethodImpl && I->getSuperClass())
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
IMPDecl,
I->getSuperClass(), IncompleteImpl, false);
@@ -1670,7 +1681,8 @@
bool IncompleteImpl = false;
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
CatIMPDecl, IDecl,
- IncompleteImpl, false, true /*WarnExactMatch*/);
+ IncompleteImpl, false,
+ true /*WarnCategoryMethodImpl*/);
}
void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
Modified: cfe/trunk/test/SemaObjC/method-undef-category-warn-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/method-undef-category-warn-1.m?rev=150206&r1=150205&r2=150206&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/method-undef-category-warn-1.m (original)
+++ cfe/trunk/test/SemaObjC/method-undef-category-warn-1.m Thu Feb 9 15:30:24 2012
@@ -28,3 +28,26 @@
@implementation MyClass1(CAT1)
@end
+
+// rdar://10823023
+ at class NSString;
+
+ at protocol NSObject
+- (NSString *)meth_inprotocol;
+ at end
+
+ at interface NSObject <NSObject>
+- (NSString *)description;
++ (NSString *) cls_description;
+ at end
+
+ at protocol Foo
+- (NSString *)description;
++ (NSString *) cls_description;
+ at end
+
+ at interface NSObject (FooConformance) <Foo>
+ at end
+
+ at implementation NSObject (FooConformance)
+ at end
More information about the cfe-commits
mailing list