]> granicus.if.org Git - clang/commitdiff
Finish up some fixes related to <rdar://problem/6497631> Message lookup is sometimes...
authorSteve Naroff <snaroff@apple.com>
Wed, 4 Mar 2009 15:11:40 +0000 (15:11 +0000)
committerSteve Naroff <snaroff@apple.com>
Wed, 4 Mar 2009 15:11:40 +0000 (15:11 +0000)
- Disallow casting 'super'. GCC allows this, however it doesn't make sense (super isn't an expression and the cast won't alter lookup/dispatch).
- Tighten up lookup when messaging 'self'.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66033 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.def
lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprObjC.cpp
test/SemaObjC/call-super-2.m [new file with mode: 0644]
test/SemaObjC/conditional-expr.m
test/SemaObjC/property-category-1.m
test/SemaObjC/property-noprotocol-warning.m

index 5fb7fe2b299be6e2977a87824ac2ea012be5ce7c..38977a3ed8267127a33253bf9fc22b91598ddb11 100644 (file)
@@ -966,6 +966,8 @@ DIAG(err_catch_param_not_objc_type, ERROR,
      "@catch parameter is not an Objective-C class type")
 DIAG(err_illegal_qualifiers_on_catch_parm, ERROR,
      "illegal qualifiers on @catch parameter")
+DIAG(err_illegal_super_cast, ERROR,
+     "cannot cast 'super' (it isn't an expression)")
 
 
 // C++ casts
index 14b72874f7fcea4839c99cf20772c84ec73c9617..9cb47cce4b2998f6d8098bc379a972e1ae5b99f5 100644 (file)
@@ -226,6 +226,9 @@ public:
   /// extremely uncommon (only 1% of selectors are "overloaded").
   llvm::DenseMap<Selector, ObjCMethodList> InstanceMethodPool;
   llvm::DenseMap<Selector, ObjCMethodList> FactoryMethodPool;
+  
+  /// Private Helper predicate to check for 'self'.
+  bool isSelfExpr(Expr *RExpr);
 public:
   Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer);
   ~Sema() {
index 6252bcaef5bfd3510bfe00d5aca7d38bef02cc29..43909b9afe38e42710feaeb38fa85df964accfae 100644 (file)
@@ -2302,6 +2302,8 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr) {
   } else if (castType->isVectorType()) {
     if (CheckVectorCast(TyR, castType, castExpr->getType()))
       return true;
+  } else if (getLangOptions().ObjC1 && isa<ObjCSuperExpr>(castExpr)) {
+    return Diag(castExpr->getLocStart(), diag::err_illegal_super_cast);
   }
   return false;
 }
index 39a89d6d9429f12e69bf1ab732bdf8d49fab5d0a..8705baffcb6eec3c9ccd99d509578eb72b3c9dc4 100644 (file)
@@ -202,6 +202,13 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
   return anyIncompatibleArgs;
 }
 
+bool Sema::isSelfExpr(Expr *RExpr) {
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RExpr))
+    if (DRE->getDecl()->getIdentifier() == &Context.Idents.get("self"))
+      return true;
+  return false;
+}
+
 // Helper method for ActOnClassMethod/ActOnInstanceMethod.
 // Will search "local" class/category implementations for a method decl.
 // Returns 0 if no method is found.
@@ -385,6 +392,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
   // Handle messages to Class.
   if (ReceiverCType == Context.getCanonicalType(Context.getObjCClassType())) {
     ObjCMethodDecl *Method = 0;
+    
     if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
       if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
         // First check the public methods in the class interface.
@@ -396,12 +404,15 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
       if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
         return true;
     }
-    // Look for any factory method named 'Sel'.
-    if (!Method)
-      Method = FactoryMethodPool[Sel].Method;
-    if (!Method)
-      Method = LookupInstanceMethodInGlobalPool(
-                               Sel, SourceRange(lbrac,rbrac));
+    if (!Method) {
+      // If not messaging 'self', look for any factory method named 'Sel'.
+      if (!isSelfExpr(RExpr)) {
+        Method = FactoryMethodPool[Sel].Method;
+        if (!Method)
+          Method = LookupInstanceMethodInGlobalPool(
+                                   Sel, SourceRange(lbrac,rbrac));
+      }
+    }
     if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
                                   lbrac, rbrac, returnType))
       return true;
@@ -462,15 +473,17 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector 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 && OCIType->qual_empty()) {
-        Method = LookupInstanceMethodInGlobalPool(
-                             Sel, SourceRange(lbrac,rbrac));
-        if (Method && !OCIType->getDecl()->isForwardDecl())
-          Diag(lbrac, diag::warn_maynot_respond) 
-            << OCIType->getDecl()->getIdentifier()->getName() << Sel;
+      if (!isSelfExpr(RExpr)) {
+        // 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 && OCIType->qual_empty()) {
+          Method = LookupInstanceMethodInGlobalPool(
+                               Sel, SourceRange(lbrac,rbrac));
+          if (Method && !OCIType->getDecl()->isForwardDecl())
+            Diag(lbrac, diag::warn_maynot_respond) 
+              << OCIType->getDecl()->getIdentifier()->getName() << Sel;
+        }
       }
     }
     if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
diff --git a/test/SemaObjC/call-super-2.m b/test/SemaObjC/call-super-2.m
new file mode 100644 (file)
index 0000000..98e4e08
--- /dev/null
@@ -0,0 +1,98 @@
+// RUN: clang -fsyntax-only -verify %s
+
+#include <stddef.h>
+
+typedef struct objc_object *id;
+id objc_getClass(const char *s);
+
+@interface Object 
+@end
+
+@protocol Func
++ (int) class_func0;
+- (int) instance_func0;
+@end
+
+@interface Derived: Object
++ (int) class_func1;
++ (int) class_func2;
++ (int) class_func3;
++ (int) class_func4;
++ (int) class_func5;
++ (int) class_func6;
++ (int) class_func7;
+- (int) instance_func1;
+- (int) instance_func2;
+- (int) instance_func3;
+- (int) instance_func4;
+- (int) instance_func5;
+- (int) instance_func6;
+- (int) instance_func7;
+@end
+
+@implementation Derived
++ (int) class_func1
+{
+   int i = (size_t)[self class_func0];       // expected-warning {{method '-class_func0' not found (return type defaults to 'id')}}
+   return i + (size_t)[super class_func0];   // expected-warning {{method '+class_func0' not found (return type defaults to 'id')}}
+}
++ (int) class_func2
+{
+   int i = [(id <Func>)self class_func0];  // expected-warning {{method '-class_func0' not found (return type defaults to 'id')}} // expected-warning {{incompatible pointer to integer conversion initializing 'id', expected 'int'}}
+   i += [(id <Func>)super class_func0];    // expected-error {{cannot cast 'super' (it isn't an expression)}}
+   i += [(Class <Func>)self class_func0];  // expected-error {{protocol qualified 'Class' is unsupported}}
+   return i + [(Class <Func>)super class_func0]; // expected-error {{protocol qualified 'Class' is unsupported}} // expected-error {{cannot cast 'super' (it isn't an expression)}}
+}
++ (int) class_func3
+{
+   return [(Object <Func> *)super class_func0];  // expected-error {{cannot cast 'super' (it isn't an expression)}}
+}
++ (int) class_func4
+{
+   return [(Derived <Func> *)super class_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}}
+}   
++ (int) class_func5
+{
+   int i = (size_t)[Derived class_func0];    // expected-warning {{method '+class_func0' not found (return type defaults to 'id')}}
+   return i + (size_t)[Object class_func0];  // expected-warning {{method '+class_func0' not found (return type defaults to 'id')}}
+}
++ (int) class_func6
+{
+   return (size_t)[objc_getClass("Object") class_func1]; // GCC warns about this
+}
++ (int) class_func7
+{
+   return [objc_getClass("Derived") class_func1];
+}
+- (int) instance_func1
+{
+   int i = (size_t)[self instance_func0];     // expected-warning {{method '-instance_func0' not found (return type defaults to 'id'))}}
+   return i + (size_t)[super instance_func0]; // expected-warning {{method '-instance_func0' not found (return type defaults to 'id')}}
+}
+- (int) instance_func2
+{
+   return [(id <Func>)super instance_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}}
+}
+- (int) instance_func3
+{
+   return [(Object <Func> *)super instance_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}}
+}
+- (int) instance_func4
+{
+   return [(Derived <Func> *)super instance_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}}
+}   
+- (int) instance_func5
+{
+   int i = (size_t)[Derived instance_func1]; // GCC currently warns.
+   return i + (size_t)[Object instance_func1]; // expected-warning {{method '+instance_func1' not found (return type defaults to 'id')}}
+}
+- (int) instance_func6
+{
+   return (size_t)[objc_getClass("Object") class_func1];
+}
+- (int) instance_func7
+{
+   return [objc_getClass("Derived") class_func1];
+}
+@end
+
index 76656717e14ba889c641bd37521cf6243c581c72..4792fa6644dd909771319f822f3b493674183f8c 100644 (file)
@@ -36,7 +36,7 @@
 // No @interface declaration for DTFilterOutputStream3
 @implementation DTFilterOutputStream3 // expected-warning {{cannot find interface declaration for 'DTFilterOutputStream3'}}
 - (id)initWithNextOutputStream:(id <DTOutputStreams>) outputStream {
-  id <DTOutputStreams> nextOutputStream = [self nextOutputStream]; // expected-warning {{DTFilterOutputStream3  may not respond to 'nextOutputStream'}}
+  id <DTOutputStreams> nextOutputStream = [self nextOutputStream]; // expected-warning {{method '-nextOutputStream' not found (return type defaults to 'id')}}
   // GCC warns about both of these as well (no errors).
   self = nextOutputStream; // expected-warning {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream3 *'}}
   return nextOutputStream ? nextOutputStream : self;
index 926f964202508ba05b7e39e533551ce04eb45b3e..243b774870d8f52ec059348b9d2d304d5c91c450 100644 (file)
@@ -1,7 +1,7 @@
 // RUN: clang -fsyntax-only -verify %s
 
 @interface Object
-- (id)new;
++ (id)new;
 @end
 
 @interface ReadOnly : Object
index 021c7874a9907037c858d41fb7d3b640dcd6870a..211185f2b62bcfe53662037698a07fb5b54fc561 100644 (file)
@@ -2,7 +2,7 @@
 
 
 @interface Object
-- (id) new;
++ (id) new;
 @end
 
 @protocol GCObject