]> granicus.if.org Git - clang/commitdiff
A bunch-o changes to fix <rdar://problem/5716046> incomplete implementation of ObjC...
authorSteve Naroff <snaroff@apple.com>
Fri, 8 Feb 2008 22:06:17 +0000 (22:06 +0000)
committerSteve Naroff <snaroff@apple.com>
Fri, 8 Feb 2008 22:06:17 +0000 (22:06 +0000)
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
Driver/TextDiagnosticPrinter.h
Sema/Sema.h
Sema/SemaDeclObjC.cpp
include/clang/Basic/DiagnosticKinds.def
test/Sema/method-undef-category-warn-1.m
test/Sema/method-undefined-warn-1.m
test/Sema/undef-protocol-methods-1.m

index 2f867d0626553ff319ad70de0e3a3167e4f4f816..7c87f4b78c15843c5c969a3ad0f0bdc5b27979f5 100644 (file)
@@ -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);
     
index 441f5ed80b74f6ddbac4d2e884e47a36fee91efb..e9c2e3a2e5ef3ccdd97b1bc8e3c25a12ba7b6f5a 100644 (file)
@@ -23,6 +23,7 @@ class SourceManager;
 
 class TextDiagnosticPrinter : public TextDiagnostics {
   FullSourceLoc LastWarningLoc;
+  FullSourceLoc LastLoc;
 public:
   TextDiagnosticPrinter() {}
 
index f3595e10767e5086969be7f89e63af841bbeff2e..e36049354c0360749fcd68964ccf57401b2f80ca 100644 (file)
@@ -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<Selector> &InsMap,
                                const llvm::DenseSet<Selector> &ClsMap);
index 60d8ce42e3000d20f8131c263085a932b6ff65b5..824557f4c585c9ff2376e4e52a6867674817b47a 100644 (file)
@@ -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<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 @@ 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<Selector> 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<Selector> 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 - 
index 3a8c04c9df858047ec35a8678e383f06da8c4ca9..11d21775ed3685e4ec64730bc9809d63c1e8d158 100644 (file)
@@ -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,
index af5a0e2befaad61de8975f059c00e68f8c6fad99..792c24d748f5fd711997c27fea22649620e83567 100644 (file)
@@ -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) <P>
-- (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) <P>
-- (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
 
index 0e4e6a1172860f65297e51ccf3ddb381a4ced149..9e646f82f73a73974efe3598e55fa10fb7553338 100644 (file)
@@ -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{}
 @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{}
index 748b151fde41e558c33a8322773d171e1aa6aecf..9ad3593c6c4d03cdb8797108d3eba4b95862e32f 100644 (file)
@@ -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<P2>
-- (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<P1, P3>
-- (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 <PROTO>
 @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{}