A bunch-o changes to fix <rdar://problem/5716046> incomplete implementation of ObjC class warning is incomplete
As part of this fix, I made a low-level change to the text diagnostics machinery (to basically avoid printing duplicate source lines/carets when you have multiple diagnostics that refer to the same exact place). For now, this only happens with we don't have a source range (could be extended to support source ranges as well).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46897 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Sema/Sema.h b/Sema/Sema.h
index f3595e1..e360493 100644
--- a/Sema/Sema.h
+++ b/Sema/Sema.h
@@ -270,7 +270,8 @@
/// CheckProtocolMethodDefs - This routine checks unimpletented methods
/// Declared in protocol, and those referenced by it.
- void CheckProtocolMethodDefs(ObjCProtocolDecl *PDecl,
+ void CheckProtocolMethodDefs(SourceLocation ImpLoc,
+ ObjCProtocolDecl *PDecl,
bool& IncompleteImpl,
const llvm::DenseSet<Selector> &InsMap,
const llvm::DenseSet<Selector> &ClsMap);
diff --git a/Sema/SemaDeclObjC.cpp b/Sema/SemaDeclObjC.cpp
index 60d8ce4..824557f 100644
--- a/Sema/SemaDeclObjC.cpp
+++ b/Sema/SemaDeclObjC.cpp
@@ -457,21 +457,25 @@
Diag((*IVI)->getLocation(), diag::err_inconsistant_ivar_count);
}
-/// CheckProtocolMethodDefs - This routine checks unimpletented methods
+/// CheckProtocolMethodDefs - This routine checks unimplemented methods
/// Declared in protocol, and those referenced by it.
-void Sema::CheckProtocolMethodDefs(ObjCProtocolDecl *PDecl,
+void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
+ ObjCProtocolDecl *PDecl,
bool& IncompleteImpl,
- const llvm::DenseSet<Selector> &InsMap,
- const llvm::DenseSet<Selector> &ClsMap) {
+ const llvm::DenseSet<Selector> &InsMap,
+ const llvm::DenseSet<Selector> &ClsMap) {
// check unimplemented instance methods.
for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(),
E = PDecl->instmeth_end(); I != E; ++I) {
ObjCMethodDecl *method = *I;
if (!InsMap.count(method->getSelector()) &&
method->getImplementationControl() != ObjCMethodDecl::Optional) {
- Diag(method->getLocation(), diag::warn_undef_method_impl,
+ if (!IncompleteImpl) {
+ Diag(ImpLoc, diag::warn_incomplete_impl);
+ IncompleteImpl = true;
+ }
+ Diag(ImpLoc, diag::warn_undef_method_impl,
method->getSelector().getName());
- IncompleteImpl = true;
}
}
// check unimplemented class methods
@@ -480,15 +484,18 @@
ObjCMethodDecl *method = *I;
if (!ClsMap.count(method->getSelector()) &&
method->getImplementationControl() != ObjCMethodDecl::Optional) {
- Diag(method->getLocation(), diag::warn_undef_method_impl,
+ if (!IncompleteImpl) {
+ Diag(ImpLoc, diag::warn_incomplete_impl);
+ IncompleteImpl = true;
+ }
+ Diag(ImpLoc, diag::warn_undef_method_impl,
method->getSelector().getName());
- IncompleteImpl = true;
}
}
// Check on this protocols's referenced protocols, recursively
ObjCProtocolDecl** RefPDecl = PDecl->getReferencedProtocols();
for (unsigned i = 0; i < PDecl->getNumReferencedProtocols(); i++)
- CheckProtocolMethodDefs(RefPDecl[i], IncompleteImpl, InsMap, ClsMap);
+ CheckProtocolMethodDefs(ImpLoc, RefPDecl[i], IncompleteImpl, InsMap, ClsMap);
}
void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl,
@@ -504,9 +511,12 @@
for (ObjCInterfaceDecl::instmeth_iterator I = IDecl->instmeth_begin(),
E = IDecl->instmeth_end(); I != E; ++I)
if (!InsMap.count((*I)->getSelector())) {
- Diag((*I)->getLocation(), diag::warn_undef_method_impl,
+ if (!IncompleteImpl) {
+ Diag(IMPDecl->getLocation(), diag::warn_incomplete_impl);
+ IncompleteImpl = true;
+ }
+ Diag(IMPDecl->getLocation(), diag::warn_undef_method_impl,
(*I)->getSelector().getName());
- IncompleteImpl = true;
}
llvm::DenseSet<Selector> ClsMap;
@@ -519,20 +529,20 @@
for (ObjCInterfaceDecl::classmeth_iterator I = IDecl->classmeth_begin(),
E = IDecl->classmeth_end(); I != E; ++I)
if (!ClsMap.count((*I)->getSelector())) {
- Diag((*I)->getLocation(), diag::warn_undef_method_impl,
+ if (!IncompleteImpl) {
+ Diag(IMPDecl->getLocation(), diag::warn_incomplete_impl);
+ IncompleteImpl = true;
+ }
+ Diag(IMPDecl->getLocation(), diag::warn_undef_method_impl,
(*I)->getSelector().getName());
- IncompleteImpl = true;
}
// Check the protocol list for unimplemented methods in the @implementation
// class.
ObjCProtocolDecl** protocols = IDecl->getReferencedProtocols();
for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++)
- CheckProtocolMethodDefs(protocols[i], IncompleteImpl, InsMap, ClsMap);
-
- if (IncompleteImpl)
- Diag(IMPDecl->getLocation(), diag::warn_incomplete_impl_class,
- IMPDecl->getName());
+ CheckProtocolMethodDefs(IMPDecl->getLocation(), protocols[i],
+ IncompleteImpl, InsMap, ClsMap);
}
/// ImplCategoryMethodsVsIntfMethods - Checks that methods declared in the
@@ -550,9 +560,12 @@
for (ObjCCategoryDecl::instmeth_iterator I = CatClassDecl->instmeth_begin(),
E = CatClassDecl->instmeth_end(); I != E; ++I)
if (!InsMap.count((*I)->getSelector())) {
- Diag((*I)->getLocation(), diag::warn_undef_method_impl,
+ if (!IncompleteImpl) {
+ Diag(CatImplDecl->getLocation(), diag::warn_incomplete_impl);
+ IncompleteImpl = true;
+ }
+ Diag(CatImplDecl->getLocation(), diag::warn_undef_method_impl,
(*I)->getSelector().getName());
- IncompleteImpl = true;
}
llvm::DenseSet<Selector> ClsMap;
// Check and see if class methods in category interface have been
@@ -565,9 +578,12 @@
for (ObjCCategoryDecl::classmeth_iterator I = CatClassDecl->classmeth_begin(),
E = CatClassDecl->classmeth_end(); I != E; ++I)
if (!ClsMap.count((*I)->getSelector())) {
- Diag((*I)->getLocation(), diag::warn_undef_method_impl,
+ if (!IncompleteImpl) {
+ Diag(CatImplDecl->getLocation(), diag::warn_incomplete_impl);
+ IncompleteImpl = true;
+ }
+ Diag(CatImplDecl->getLocation(), diag::warn_undef_method_impl,
(*I)->getSelector().getName());
- IncompleteImpl = true;
}
// Check the protocol list for unimplemented methods in the @implementation
@@ -575,11 +591,9 @@
ObjCProtocolDecl** protocols = CatClassDecl->getReferencedProtocols();
for (unsigned i = 0; i < CatClassDecl->getNumReferencedProtocols(); i++) {
ObjCProtocolDecl* PDecl = protocols[i];
- CheckProtocolMethodDefs(PDecl, IncompleteImpl, InsMap, ClsMap);
+ CheckProtocolMethodDefs(CatImplDecl->getLocation(), PDecl, IncompleteImpl,
+ InsMap, ClsMap);
}
- if (IncompleteImpl)
- Diag(CatImplDecl->getLocation(), diag::warn_incomplete_impl_category,
- CatClassDecl->getName());
}
/// ActOnForwardClassDeclaration -