[cfe-commits] r65292 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.def lib/AST/Decl.cpp lib/AST/DeclObjC.cpp lib/Sema/SemaExprObjC.cpp test/SemaObjC/property-11.m test/SemaObjC/protocol-id-test-1.m test/SemaObjC/protocol-id-test-2.m

Steve Naroff snaroff at apple.com
Sun Feb 22 11:35:57 PST 2009


Author: snaroff
Date: Sun Feb 22 13:35:57 2009
New Revision: 65292

URL: http://llvm.org/viewvc/llvm-project?rev=65292&view=rev
Log:
Contains the following (related to problems found while investigting <rdar://problem/6497631> Message lookup is sometimes different than gcc's).

- Implement instance/class overloading in ObjCContainerDecl (removing a FIXME). This involved hacking NamedDecl::declarationReplaces(), which took awhile to figure out (didn't realize replace was the default).
- Changed Sema::ActOnInstanceMessage() to remove redundant warnings when dealing with protocols. For now, I've omitted the "protocol" term in the diagnostic. It simplifies the code flow and wan't always 100% accurate (e.g. "Foo<Prot>" looks in the class interface, not just the protocol).
- Changed several test cases to jive with the above changes.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclObjC.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/test/SemaObjC/property-11.m
    cfe/trunk/test/SemaObjC/protocol-id-test-1.m
    cfe/trunk/test/SemaObjC/protocol-id-test-2.m

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=65292&r1=65291&r2=65292&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Sun Feb 22 13:35:57 2009
@@ -916,8 +916,6 @@
      "no super class declared in @interface for %0")
 DIAG(err_invalid_receiver_to_message, ERROR,
      "invalid receiver to message expression")
-DIAG(warn_method_not_found_in_protocol, WARNING,
-     "method %objcinstance0 not found in protocol (return type defaults to 'id')")
 DIAG(error_bad_receiver_type, ERROR,
      "bad receiver type %0")
 DIAG(error_objc_throw_expects_object, ERROR,

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=65292&r1=65291&r2=65292&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Sun Feb 22 13:35:57 2009
@@ -13,6 +13,7 @@
 
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/Expr.h"
@@ -194,6 +195,10 @@
     // For function declarations, we keep track of redeclarations.
     return FD->getPreviousDeclaration() == OldD;
 
+  // For method declarations, we keep track of redeclarations.
+  if (isa<ObjCMethodDecl>(this))
+    return false;
+    
   // For non-function declarations, if the declarations are of the
   // same kind then this must be a redeclaration, or semantic analysis
   // would not have given us the new declaration.

Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=65292&r1=65291&r2=65292&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Sun Feb 22 13:35:57 2009
@@ -14,6 +14,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Stmt.h"
+#include "llvm/ADT/STLExtras.h"
 using namespace clang;
 
 //===----------------------------------------------------------------------===//
@@ -42,21 +43,42 @@
 //===----------------------------------------------------------------------===//
 
 // Get the local instance method declared in this interface.
-// FIXME: handle overloading, instance & class methods can have the same name.
 ObjCMethodDecl *ObjCContainerDecl::getInstanceMethod(Selector Sel) const {
-  lookup_const_result MethodResult = lookup(Sel);
-  if (MethodResult.first)
-    return const_cast<ObjCMethodDecl*>(
-                        dyn_cast<ObjCMethodDecl>(*MethodResult.first));
+  // Since instance & class methods can have the same name, the loop below
+  // ensures we get the correct method.
+  //
+  // @interface Whatever
+  // - (int) class_method;
+  // + (float) class_method;
+  // @end
+  //
+  lookup_const_iterator Meth, MethEnd;
+  for (llvm::tie(Meth, MethEnd) = lookup(Sel);
+       Meth != MethEnd; ++Meth) {
+    ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
+    if (MD && MD->isInstanceMethod())
+      return MD;
+  }
   return 0;
 }
 
 // Get the local class method declared in this interface.
 ObjCMethodDecl *ObjCContainerDecl::getClassMethod(Selector Sel) const {
-  lookup_const_result MethodResult = lookup(Sel);
-  if (MethodResult.first)
-    return const_cast<ObjCMethodDecl*>(
-                           dyn_cast<ObjCMethodDecl>(*MethodResult.first));
+  // Since instance & class methods can have the same name, the loop below
+  // ensures we get the correct method.
+  //
+  // @interface Whatever
+  // - (int) class_method;
+  // + (float) class_method;
+  // @end
+  //
+  lookup_const_iterator Meth, MethEnd;
+  for (llvm::tie(Meth, MethEnd) = lookup(Sel);
+       Meth != MethEnd; ++Meth) {
+    ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
+    if (MD && MD->isClassMethod())
+      return MD;
+  }
   return 0;
 }
 

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=65292&r1=65291&r2=65292&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Sun Feb 22 13:35:57 2009
@@ -397,9 +397,6 @@
       if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
         break;
     }
-    if (!Method)
-      Diag(lbrac, diag::warn_method_not_found_in_protocol)
-        << Sel << RExpr->getSourceRange();
   // Check for GCC extension "Class<foo>".
   } else if (ObjCQualifiedClassType *QIT = 
                dyn_cast<ObjCQualifiedClassType>(ReceiverCType)) {
@@ -409,9 +406,6 @@
       if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
         break;
     }
-    if (!Method)
-      Diag(lbrac, diag::warn_method_not_found_in_protocol)
-        << Sel << RExpr->getSourceRange();
   } else if (const ObjCInterfaceType *OCIReceiver = 
                 ReceiverCType->getAsPointerToObjCInterfaceType()) {
     // We allow sending a message to a pointer to an interface (an object).
@@ -422,19 +416,29 @@
     // The idea is to add class info to InstanceMethodPool.
     Method = ClassDecl->lookupInstanceMethod(Sel);
     
+    bool haveQualifiers = false;
     if (!Method) {
       // Search protocol qualifiers.
       for (ObjCQualifiedIdType::qual_iterator QI = OCIReceiver->qual_begin(),
            E = OCIReceiver->qual_end(); QI != E; ++QI) {
+        haveQualifiers = true;
         if ((Method = (*QI)->lookupInstanceMethod(Sel)))
           break;
       }
     }
-    
-    if (!Method && !OCIReceiver->qual_empty())
-      Diag(lbrac, diag::warn_method_not_found_in_protocol)
-        << Sel << SourceRange(lbrac, rbrac);
-    
+    if (!Method) {
+      // If we have an implementation in scope, check "private" methods.
+      if (ClassDecl)
+        if (ObjCImplementationDecl *ImpDecl = 
+              ObjCImplementations[ClassDecl->getIdentifier()])
+          Method = ImpDecl->getInstanceMethod(Sel);
+          // If we still haven't found a method, look in the global pool. This
+          // behavior isn't very desirable, however we need it for GCC
+          // compatibility. FIXME: should we deviate??
+          if (!Method && !haveQualifiers)
+            Method = LookupInstanceMethodInGlobalPool(
+                                 Sel, SourceRange(lbrac,rbrac));
+    }
     if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
       return true;
   } else {
@@ -443,19 +447,6 @@
     return true;
   }
   
-  if (!Method) {
-    // If we have an implementation in scope, check "private" methods.
-    if (ClassDecl)
-      if (ObjCImplementationDecl *ImpDecl = 
-            ObjCImplementations[ClassDecl->getIdentifier()])
-        Method = ImpDecl->getInstanceMethod(Sel);
-        // If we still haven't found a method, look in the global pool. This
-        // behavior isn't very desirable, however we need it for GCC
-        // compatibility.
-        if (!Method)
-          Method = LookupInstanceMethodInGlobalPool(
-                               Sel, SourceRange(lbrac,rbrac));
-  }
   if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
                                 lbrac, rbrac, returnType))
     return true;

Modified: cfe/trunk/test/SemaObjC/property-11.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-11.m?rev=65292&r1=65291&r2=65292&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/property-11.m (original)
+++ cfe/trunk/test/SemaObjC/property-11.m Sun Feb 22 13:35:57 2009
@@ -22,7 +22,10 @@
   NSSound *x;
   id o;
 
-  o = [x foo]; 
+  // GCC does *not* warn about the following. Since foo/setFoo: are not in the
+  // class or category interface for NSSound, the compiler shouldn't find them.
+  // For now, we will support GCC's behavior (sigh).
+  o = [x foo];
   o = x.foo;
   [x setFoo:o];
   x.foo = o;

Modified: cfe/trunk/test/SemaObjC/protocol-id-test-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/protocol-id-test-1.m?rev=65292&r1=65291&r2=65292&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/protocol-id-test-1.m (original)
+++ cfe/trunk/test/SemaObjC/protocol-id-test-1.m Sun Feb 22 13:35:57 2009
@@ -12,5 +12,5 @@
 @end
 
 @implementation INTF
-- (void)IMeth {INTF<P> *pi;  [pi Meth]; } // expected-warning {{method '-Meth' not found in protocol (return type defaults to 'id')}}
+- (void)IMeth {INTF<P> *pi;  [pi Meth]; } // expected-warning {{method '-Meth' not found (return type defaults to 'id')}}
 @end

Modified: cfe/trunk/test/SemaObjC/protocol-id-test-2.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/protocol-id-test-2.m?rev=65292&r1=65291&r2=65292&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/protocol-id-test-2.m (original)
+++ cfe/trunk/test/SemaObjC/protocol-id-test-2.m Sun Feb 22 13:35:57 2009
@@ -5,10 +5,8 @@
 
 @interface INTF<P>
 - (void)IMeth;
- - (void) Meth;
 @end
 
 @implementation INTF
-- (void)IMeth { [(id<P>)self Meth]; }  // expected-warning {{method '-Meth' not found in protocol (return type defaults to 'id')}}
-- (void) Meth {}
+- (void)IMeth { [(id<P>)self Meth]; }  // expected-warning {{method '-Meth' not found (return type defaults to 'id')}}
 @end





More information about the cfe-commits mailing list