From efe7f36f4d87b6e64b87128a81018350b2f21987 Mon Sep 17 00:00:00 2001 From: Steve Naroff Date: Fri, 8 Feb 2008 22:06:17 +0000 Subject: [PATCH] A bunch-o changes to fix 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 --- Driver/TextDiagnosticPrinter.cpp | 5 +- Driver/TextDiagnosticPrinter.h | 1 + Sema/Sema.h | 3 +- Sema/SemaDeclObjC.cpp | 66 ++++++++++++++---------- include/clang/Basic/DiagnosticKinds.def | 6 +-- test/Sema/method-undef-category-warn-1.m | 16 +++--- test/Sema/method-undefined-warn-1.m | 16 +++--- test/Sema/undef-protocol-methods-1.m | 29 +++++++---- 8 files changed, 86 insertions(+), 56 deletions(-) diff --git a/Driver/TextDiagnosticPrinter.cpp b/Driver/TextDiagnosticPrinter.cpp index 2f867d0626..7c87f4b78c 100644 --- a/Driver/TextDiagnosticPrinter.cpp +++ b/Driver/TextDiagnosticPrinter.cpp @@ -159,7 +159,10 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic &Diags, llvm::cerr << FormatDiagnostic(Diags, Level, ID, Strs, NumStrs) << "\n"; - if (!NoCaretDiagnostics && Pos.isValid()) { + if (!NoCaretDiagnostics && Pos.isValid() && ((LastLoc != Pos) && !Ranges)) { + // Cache the LastLoc, it allows us to omit duplicate source/caret spewage. + LastLoc = Pos; + // Get the line of the source file. std::string SourceLine(LineStart, LineEnd); diff --git a/Driver/TextDiagnosticPrinter.h b/Driver/TextDiagnosticPrinter.h index 441f5ed80b..e9c2e3a2e5 100644 --- a/Driver/TextDiagnosticPrinter.h +++ b/Driver/TextDiagnosticPrinter.h @@ -23,6 +23,7 @@ class SourceManager; class TextDiagnosticPrinter : public TextDiagnostics { FullSourceLoc LastWarningLoc; + FullSourceLoc LastLoc; public: TextDiagnosticPrinter() {} diff --git a/Sema/Sema.h b/Sema/Sema.h index f3595e1076..e36049354c 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -270,7 +270,8 @@ private: /// 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 &InsMap, const llvm::DenseSet &ClsMap); diff --git a/Sema/SemaDeclObjC.cpp b/Sema/SemaDeclObjC.cpp index 60d8ce42e3..824557f4c5 100644 --- a/Sema/SemaDeclObjC.cpp +++ b/Sema/SemaDeclObjC.cpp @@ -457,21 +457,25 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, 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 &InsMap, - const llvm::DenseSet &ClsMap) { + const llvm::DenseSet &InsMap, + const llvm::DenseSet &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 @@ void Sema::CheckProtocolMethodDefs(ObjCProtocolDecl *PDecl, 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 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, 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 ClsMap; @@ -519,20 +529,20 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, 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 @@ void Sema::ImplCategoryMethodsVsIntfMethods(ObjCCategoryImplDecl *CatImplDecl, 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 ClsMap; // Check and see if class methods in category interface have been @@ -565,9 +578,12 @@ void Sema::ImplCategoryMethodsVsIntfMethods(ObjCCategoryImplDecl *CatImplDecl, 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 @@ void Sema::ImplCategoryMethodsVsIntfMethods(ObjCCategoryImplDecl *CatImplDecl, 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 - diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 3a8c04c9df..11d21775ed 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -446,10 +446,8 @@ DIAG(err_conflicting_ivar_type, ERROR, "conflicting instance variable type") DIAG(warn_undef_method_impl, WARNING, "method definition for '%0' not found") -DIAG(warn_incomplete_impl_class, WARNING, - "incomplete implementation of class '%0'") -DIAG(warn_incomplete_impl_category, WARNING, - "incomplete implementation of category '%0'") +DIAG(warn_incomplete_impl, WARNING, + "incomplete implementation") DIAG(error_duplicate_method_decl, ERROR, "duplicate declaration of method '%0'") DIAG(err_previous_declaration, ERROR, diff --git a/test/Sema/method-undef-category-warn-1.m b/test/Sema/method-undef-category-warn-1.m index af5a0e2bef..792c24d748 100644 --- a/test/Sema/method-undef-category-warn-1.m +++ b/test/Sema/method-undef-category-warn-1.m @@ -4,23 +4,27 @@ @end @protocol P -- (void) Pmeth; // expected-warning {{method definition for 'Pmeth' not found}} -- (void) Pmeth1; // expected-warning {{method definition for 'Pmeth1' not found}} +- (void) Pmeth; +- (void) Pmeth1; @end @interface MyClass1(CAT)

-- (void) meth2; // expected-warning {{method definition for 'meth2' not found}} +- (void) meth2; @end -@implementation MyClass1(CAT) // expected-warning {{incomplete implementation of category 'CAT'}} +@implementation MyClass1(CAT) // expected-warning {{incomplete implementation}} \ + expected-warning {{method definition for 'meth2' not found}} \ + expected-warning {{method definition for 'Pmeth' not found}} - (void) Pmeth1{} @end @interface MyClass1(DOG)

-- (void)ppp; // expected-warning {{method definition for 'ppp' not found}} +- (void)ppp; @end -@implementation MyClass1(DOG) // expected-warning {{incomplete implementation of category 'DOG'}} +@implementation MyClass1(DOG) // expected-warning {{incomplete implementation}} \ + expected-warning {{method definition for 'ppp' not found}} \ + expected-warning {{method definition for 'Pmeth1' not found}} - (void) Pmeth {} @end diff --git a/test/Sema/method-undefined-warn-1.m b/test/Sema/method-undefined-warn-1.m index 0e4e6a1172..9e646f82f7 100644 --- a/test/Sema/method-undefined-warn-1.m +++ b/test/Sema/method-undefined-warn-1.m @@ -3,12 +3,12 @@ @interface INTF - (void) meth; - (void) meth : (int) arg1; -- (int) int_meth; // expected-warning {{method definition for 'int_meth' not found}} -+ (int) cls_meth; // expected-warning {{method definition for 'cls_meth' not found}} -+ (void) cls_meth1 : (int) arg1; // expected-warning {{method definition for 'cls_meth1:' not found}} +- (int) int_meth; ++ (int) cls_meth; ++ (void) cls_meth1 : (int) arg1; @end -@implementation INTF // expected-warning {{incomplete implementation of class 'INTF'}} +@implementation INTF // expected-warning {{incomplete implementation}} expected-warning {{method definition for 'int_meth' not found}} expected-warning {{method definition for 'cls_meth' not found}} expected-warning {{method definition for 'cls_meth1:' not found}} - (void) meth {} - (void) meth : (int) arg2{} - (void) cls_meth1 : (int) arg2{} @@ -17,12 +17,12 @@ @interface INTF1 - (void) meth; - (void) meth : (int) arg1; -- (int) int_meth; // expected-warning {{method definition for 'int_meth' not found}} -+ (int) cls_meth; // expected-warning {{method definition for 'cls_meth' not found}} -+ (void) cls_meth1 : (int) arg1; // expected-warning {{method definition for 'cls_meth1:' not found}} +- (int) int_meth; ++ (int) cls_meth; ++ (void) cls_meth1 : (int) arg1; @end -@implementation INTF1 // expected-warning {{incomplete implementation of class 'INTF1'}} +@implementation INTF1 // expected-warning {{incomplete implementation}} expected-warning {{method definition for 'int_meth' not found}} expected-warning {{method definition for 'cls_meth' not found}} expected-warning {{method definition for 'cls_meth1:' not found}} - (void) meth {} - (void) meth : (int) arg2{} - (void) cls_meth1 : (int) arg2{} diff --git a/test/Sema/undef-protocol-methods-1.m b/test/Sema/undef-protocol-methods-1.m index 748b151fde..9ad3593c6c 100644 --- a/test/Sema/undef-protocol-methods-1.m +++ b/test/Sema/undef-protocol-methods-1.m @@ -1,31 +1,40 @@ // RUN: clang -fsyntax-only -verify %s @protocol P1 -- (void) P1proto; // expected-warning {{method definition for 'P1proto' not found}} -+ (void) ClsP1Proto; // expected-warning {{method definition for 'ClsP1Proto' not found}} +- (void) P1proto; ++ (void) ClsP1Proto; - (void) DefP1proto; @end @protocol P2 -- (void) P2proto; // expected-warning {{method definition for 'P2proto' not found}} -+ (void) ClsP2Proto; // expected-warning {{method definition for 'ClsP2Proto' not found}} +- (void) P2proto; ++ (void) ClsP2Proto; @end @protocol P3 -- (void) P3proto; // expected-warning {{method definition for 'P3proto' not found}} -+ (void) ClsP3Proto; // expected-warning {{method definition for 'ClsP3Proto' not found}} +- (void) P3proto; ++ (void) ClsP3Proto; + (void) DefClsP3Proto; @end @protocol PROTO -- (void) meth; // expected-warning {{method definition for 'meth' not found}} -- (void) meth : (int) arg1; // expected-warning {{method definition for 'meth:' not found}} -+ (void) cls_meth : (int) arg1; // expected-warning {{method definition for 'cls_meth:' not found}} +- (void) meth; +- (void) meth : (int) arg1; ++ (void) cls_meth : (int) arg1; @end @interface INTF @end -@implementation INTF // expected-warning {{incomplete implementation of class 'INTF'}} +@implementation INTF // expected-warning {{incomplete implementation}} \ + expected-warning {{method definition for 'meth' not found}} \ + expected-warning {{method definition for 'meth:' not found}} \ + expected-warning {{method definition for 'cls_meth:' not found}} \ + expected-warning {{method definition for 'P3proto' not found}} \ + expected-warning {{method definition for 'ClsP3Proto' not found}} \ + expected-warning {{method definition for 'P2proto' not found}} \ + expected-warning {{method definition for 'ClsP2Proto' not found}} \ + expected-warning {{method definition for 'ClsP1Proto' not found}} \ + expected-warning {{method definition for 'P1proto' not found}} - (void) DefP1proto{} + (void) DefClsP3Proto{} -- 2.40.0