[cfe-commits] r66033 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.def lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaExprObjC.cpp test/SemaObjC/call-super-2.m test/SemaObjC/conditional-expr.m test/SemaObjC/property-category-1.m test/SemaObjC/property-noprotocol-warning.m

Steve Naroff snaroff at apple.com
Wed Mar 4 07:11:51 PST 2009


Author: snaroff
Date: Wed Mar  4 09:11:40 2009
New Revision: 66033

URL: http://llvm.org/viewvc/llvm-project?rev=66033&view=rev
Log:
Finish up some fixes related to <rdar://problem/6497631> Message lookup is sometimes different than gcc's.

- 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'.


Added:
    cfe/trunk/test/SemaObjC/call-super-2.m
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/test/SemaObjC/conditional-expr.m
    cfe/trunk/test/SemaObjC/property-category-1.m
    cfe/trunk/test/SemaObjC/property-noprotocol-warning.m

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Wed Mar  4 09:11:40 2009
@@ -966,6 +966,8 @@
      "@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

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=66033&r1=66032&r2=66033&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Mar  4 09:11:40 2009
@@ -226,6 +226,9 @@
   /// 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() {

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Mar  4 09:11:40 2009
@@ -2302,6 +2302,8 @@
   } 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;
 }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Wed Mar  4 09:11:40 2009
@@ -202,6 +202,13 @@
   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 @@
   // 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 @@
       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 @@
           }
         }
       }
-      // 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))

Added: cfe/trunk/test/SemaObjC/call-super-2.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/call-super-2.m?rev=66033&view=auto

==============================================================================
--- cfe/trunk/test/SemaObjC/call-super-2.m (added)
+++ cfe/trunk/test/SemaObjC/call-super-2.m Wed Mar  4 09:11:40 2009
@@ -0,0 +1,98 @@
+// RUN: clang -fsyntax-only -verify %s
+
+#include <stddef.h>
+
+typedef struct objc_object *id;
+id objc_getClass(const char *s);
+
+ at interface Object 
+ at end
+
+ at protocol Func
++ (int) class_func0;
+- (int) instance_func0;
+ at end
+
+ at 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;
+ at end
+
+ at 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];
+}
+ at end
+

Modified: cfe/trunk/test/SemaObjC/conditional-expr.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/conditional-expr.m?rev=66033&r1=66032&r2=66033&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/conditional-expr.m (original)
+++ cfe/trunk/test/SemaObjC/conditional-expr.m Wed Mar  4 09:11:40 2009
@@ -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;

Modified: cfe/trunk/test/SemaObjC/property-category-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-category-1.m?rev=66033&r1=66032&r2=66033&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/property-category-1.m (original)
+++ cfe/trunk/test/SemaObjC/property-category-1.m Wed Mar  4 09:11:40 2009
@@ -1,7 +1,7 @@
 // RUN: clang -fsyntax-only -verify %s
 
 @interface Object
-- (id)new;
++ (id)new;
 @end
 
 @interface ReadOnly : Object

Modified: cfe/trunk/test/SemaObjC/property-noprotocol-warning.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-noprotocol-warning.m?rev=66033&r1=66032&r2=66033&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/property-noprotocol-warning.m (original)
+++ cfe/trunk/test/SemaObjC/property-noprotocol-warning.m Wed Mar  4 09:11:40 2009
@@ -2,7 +2,7 @@
 
 
 @interface Object
-- (id) new;
++ (id) new;
 @end
 
 @protocol GCObject





More information about the cfe-commits mailing list