r176339 - Perform the receiver-expression transformations regardless of

John McCall rjmccall at apple.com
Fri Mar 1 01:20:14 PST 2013


Author: rjmccall
Date: Fri Mar  1 03:20:14 2013
New Revision: 176339

URL: http://llvm.org/viewvc/llvm-project?rev=176339&view=rev
Log:
Perform the receiver-expression transformations regardless of
whether we already have a method.  Fixes a bug where we were
failing to properly contextually convert a message receiver
during template instantiation.

As a side-effect, we now actually perform correct method lookup
after adjusting a message-send to integral or non-ObjC pointer
types (legal outside of ARC).

rdar://13305374

Added:
    cfe/trunk/test/CodeGenObjCXX/message.mm
Modified:
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/test/SemaObjC/bad-receiver-1.m
    cfe/trunk/test/SemaObjC/message.m
    cfe/trunk/test/SemaObjC/super.m
    cfe/trunk/test/SemaObjC/warn-isa-ref.m

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=176339&r1=176338&r2=176339&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Fri Mar  1 03:20:14 2013
@@ -2119,8 +2119,46 @@ ExprResult Sema::BuildInstanceMessage(Ex
       return ExprError();
     Receiver = Result.take();
     ReceiverType = Receiver->getType();
+
+    // If the receiver is an ObjC pointer, a block pointer, or an
+    // __attribute__((NSObject)) pointer, we don't need to do any
+    // special conversion in order to look up a receiver.
+    if (ReceiverType->isObjCRetainableType()) {
+      // do nothing
+    } else if (!getLangOpts().ObjCAutoRefCount &&
+               !Context.getObjCIdType().isNull() &&
+               (ReceiverType->isPointerType() || 
+                ReceiverType->isIntegerType())) {
+      // Implicitly convert integers and pointers to 'id' but emit a warning.
+      // But not in ARC.
+      Diag(Loc, diag::warn_bad_receiver_type)
+        << ReceiverType 
+        << Receiver->getSourceRange();
+      if (ReceiverType->isPointerType()) {
+        Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), 
+                                     CK_CPointerToObjCPointerCast).take();
+      } else {
+        // TODO: specialized warning on null receivers?
+        bool IsNull = Receiver->isNullPointerConstant(Context,
+                                              Expr::NPC_ValueDependentIsNull);
+        CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer;
+        Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
+                                     Kind).take();
+      }
+      ReceiverType = Receiver->getType();
+    } else if (getLangOpts().CPlusPlus) {
+      ExprResult result = PerformContextuallyConvertToObjCPointer(Receiver);
+      if (result.isUsable()) {
+        Receiver = result.take();
+        ReceiverType = Receiver->getType();
+      }
+    }
   }
 
+  // There's a somewhat weird interaction here where we assume that we
+  // won't actually have a method unless we also don't need to do some
+  // of the more detailed type-checking on the receiver.
+
   if (!Method) {
     // Handle messages to id.
     bool receiverIsId = ReceiverType->isObjCIdType();
@@ -2256,48 +2294,11 @@ ExprResult Sema::BuildInstanceMessage(Ex
         }
         if (Method && DiagnoseUseOfDecl(Method, Loc, forwardClass))
           return ExprError();
-      } else if (!getLangOpts().ObjCAutoRefCount &&
-                 !Context.getObjCIdType().isNull() &&
-                 (ReceiverType->isPointerType() || 
-                  ReceiverType->isIntegerType())) {
-        // Implicitly convert integers and pointers to 'id' but emit a warning.
-        // But not in ARC.
-        Diag(Loc, diag::warn_bad_receiver_type)
-          << ReceiverType 
-          << Receiver->getSourceRange();
-        if (ReceiverType->isPointerType())
-          Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), 
-                            CK_CPointerToObjCPointerCast).take();
-        else {
-          // TODO: specialized warning on null receivers?
-          bool IsNull = Receiver->isNullPointerConstant(Context,
-                                              Expr::NPC_ValueDependentIsNull);
-          CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer;
-          Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(),
-                                       Kind).take();
-        }
-        ReceiverType = Receiver->getType();
       } else {
-        ExprResult ReceiverRes;
-        if (getLangOpts().CPlusPlus)
-          ReceiverRes = PerformContextuallyConvertToObjCPointer(Receiver);
-        if (ReceiverRes.isUsable()) {
-          Receiver = ReceiverRes.take();
-          return BuildInstanceMessage(Receiver,
-                                      ReceiverType,
-                                      SuperLoc,
-                                      Sel,
-                                      Method,
-                                      LBracLoc,
-                                      SelectorLocs,
-                                      RBracLoc,
-                                      ArgsIn);
-        } else {
-          // Reject other random receiver types (e.g. structs).
-          Diag(Loc, diag::err_bad_receiver_type)
-            << ReceiverType << Receiver->getSourceRange();
-          return ExprError();
-        }
+        // Reject other random receiver types (e.g. structs).
+        Diag(Loc, diag::err_bad_receiver_type)
+          << ReceiverType << Receiver->getSourceRange();
+        return ExprError();
       }
     }
   }

Added: cfe/trunk/test/CodeGenObjCXX/message.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/message.mm?rev=176339&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/message.mm (added)
+++ cfe/trunk/test/CodeGenObjCXX/message.mm Fri Mar  1 03:20:14 2013
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.7 -emit-llvm -o - %s | FileCheck %s
+
+// Properly instantiate a non-dependent message expression which
+// requires a contextual conversion to ObjC pointer type.
+// <rdar://13305374>
+ at interface Test0
+- (void) foo;
+ at end
+namespace test0 {
+  struct A {
+    operator Test0*();
+  };
+  template <class T> void foo() {
+    A a;
+    [a foo];
+  }
+  template void foo<int>();
+  // CHECK:    define weak_odr void @_ZN5test03fooIiEEvv()
+  // CHECK:      [[T0:%.*]] = call [[TEST0:%.*]]* @_ZN5test01AcvP5Test0Ev(
+  // CHECK-NEXT: [[T1:%.*]] = load i8**
+  // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST0]]* [[T0]] to i8*
+  // CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* [[T2]], i8* [[T1]])
+  // CHECK-NEXT: ret void
+}

Modified: cfe/trunk/test/SemaObjC/bad-receiver-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/bad-receiver-1.m?rev=176339&r1=176338&r2=176339&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/bad-receiver-1.m (original)
+++ cfe/trunk/test/SemaObjC/bad-receiver-1.m Fri Mar  1 03:20:14 2013
@@ -7,8 +7,7 @@
 int objc_lookUpClass(const char*);
 
 void __raiseExc1() {
- [objc_lookUpClass("NSString") retain]; // expected-warning {{receiver type 'int' is not 'id'}} \
-    expected-warning {{method '-retain' not found}}
+ [objc_lookUpClass("NSString") retain]; // expected-warning {{receiver type 'int' is not 'id'}}
 }
 
 typedef const struct __CFString * CFStringRef;

Modified: cfe/trunk/test/SemaObjC/message.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/message.m?rev=176339&r1=176338&r2=176339&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/message.m (original)
+++ cfe/trunk/test/SemaObjC/message.m Fri Mar  1 03:20:14 2013
@@ -95,7 +95,7 @@ int test5(int X) {
 void foo4() {
   struct objc_object X[10];
   
-  [X rect]; // expected-warning {{receiver type 'struct objc_object *' is not 'id' or interface pointer, consider casting it to 'id'}} expected-warning {{method '-rect' not found (return type defaults to 'id')}}
+  [X rect]; // expected-warning {{receiver type 'struct objc_object *' is not 'id' or interface pointer, consider casting it to 'id'}}
 }
 
 // rdar://13207886

Modified: cfe/trunk/test/SemaObjC/super.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/super.m?rev=176339&r1=176338&r2=176339&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/super.m (original)
+++ cfe/trunk/test/SemaObjC/super.m Fri Mar  1 03:20:14 2013
@@ -51,8 +51,7 @@ void f(id super) {
   [super m];
 }
 void f0(int super) {
-  [super m]; // expected-warning{{receiver type 'int' is not 'id'}} \
-                expected-warning {{method '-m' not found (return type defaults to 'id')}}
+  [super m]; // expected-warning{{receiver type 'int' is not 'id'}}
 }
 void f1(id puper) {  // expected-note {{'puper' declared here}}
   [super m]; // expected-error{{use of undeclared identifier 'super'}}

Modified: cfe/trunk/test/SemaObjC/warn-isa-ref.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/warn-isa-ref.m?rev=176339&r1=176338&r2=176339&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/warn-isa-ref.m (original)
+++ cfe/trunk/test/SemaObjC/warn-isa-ref.m Fri Mar  1 03:20:14 2013
@@ -26,13 +26,11 @@ static void func() {
   // GCC allows this, with the following warning: 
   //   instance variable 'isa' is @protected; this will be a hard error in the future
   //
-  // FIXME: see if we can avoid the 2 warnings that follow the error.
+  // FIXME: see if we can avoid the warning that follows the error.
   [(*y).isa self]; // expected-error {{instance variable 'isa' is protected}} \
-                      expected-warning{{receiver type 'struct objc_class *' is not 'id' or interface pointer, consider casting it to 'id'}} \
-                      expected-warning{{method '-self' not found (return type defaults to 'id')}}
+                      expected-warning{{receiver type 'struct objc_class *' is not 'id' or interface pointer, consider casting it to 'id'}}
   [y->isa self]; // expected-error {{instance variable 'isa' is protected}} \
-                    expected-warning{{receiver type 'struct objc_class *' is not 'id' or interface pointer, consider casting it to 'id'}} \
-                    expected-warning{{method '-self' not found (return type defaults to 'id')}}
+                    expected-warning{{receiver type 'struct objc_class *' is not 'id' or interface pointer, consider casting it to 'id'}}
 }
 
 // rdar://11702488





More information about the cfe-commits mailing list