]> granicus.if.org Git - clang/commitdiff
continue cleaning up code, and disable sending a message directly to an
authorChris Lattner <sabre@nondot.org>
Mon, 21 Jul 2008 06:12:56 +0000 (06:12 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 21 Jul 2008 06:12:56 +0000 (06:12 +0000)
interface.  This fixes a bug where we used to accept:

void test2(NSNumber x) {
[x METH];
}

which doesn't make sense and GCC rejects.

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

include/clang/AST/Type.h
lib/Sema/SemaExprObjC.cpp
test/Parser/objc-init.m

index e35f0aae1117c32a745d1e99562432e6b4a47b49..22f7abaf49be6cc1f86ab12876934189be2c7548 100644 (file)
@@ -362,6 +362,10 @@ public:
   const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const;
   const ObjCQualifiedIdType *getAsObjCQualifiedIdType() const;
 
+  /// getAsPointerToObjCInterfaceType - If this is a pointer to an ObjC
+  /// interface, return the interface type, otherwise return null.
+  const ObjCInterfaceType *getAsPointerToObjCInterfaceType() const;
+
   
   /// getDesugaredType - Return the specified type with any "sugar" removed from
   /// the type.  This takes off typedefs, typeof's etc.  If the outer level of
@@ -1289,6 +1293,12 @@ inline unsigned QualType::getAddressSpace() const {
 inline const TypedefType* Type::getAsTypedefType() const {
   return dyn_cast<TypedefType>(this);
 }
+inline const ObjCInterfaceType *Type::getAsPointerToObjCInterfaceType() const {
+  if (const PointerType *PT = getAsPointerType())
+    return PT->getPointeeType()->getAsObjCInterfaceType();
+  return 0;
+}
+  
   
 inline bool Type::isFunctionType() const {
   return isa<FunctionType>(CanonicalType.getUnqualifiedType());
index bcd3975b205261d0958aa059185c7fc7fee5800a..0e5de3ab1470abd503e26f6521876f1f67dc0fdc 100644 (file)
@@ -226,14 +226,13 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
   Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
   Expr *RExpr = static_cast<Expr *>(receiver);
   QualType returnType;
-  ObjCMethodDecl *Method = 0;
 
   QualType receiverType = 
     RExpr->getType().getCanonicalType().getUnqualifiedType();
   
   // Handle messages to id.
   if (receiverType == Context.getObjCIdType().getCanonicalType()) {
-    Method = InstanceMethodPool[Sel].Method;
+    ObjCMethodDecl *Method = InstanceMethodPool[Sel].Method;
     if (!Method)
       Method = FactoryMethodPool[Sel].Method;
     if (!Method) {
@@ -252,6 +251,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
   
   // Handle messages to Class.
   if (receiverType == Context.getObjCClassType().getCanonicalType()) {
+    ObjCMethodDecl *Method = 0;
     if (getCurMethodDecl()) {
       ObjCInterfaceDecl* ClassDecl = getCurMethodDecl()->getClassInterface();
       // If we have an implementation in scope, check "private" methods.
@@ -279,18 +279,14 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
                                ArgExprs, NumArgs);
   }
   
-  // We allow sending a message to a qualified ID ("id<foo>") to an interface
-  // directly ("[NSNumber foo]") and to a pointer to an interface (an object).
-  if (!isa<ObjCQualifiedIdType>(receiverType) &&
-      !isa<ObjCInterfaceType>(receiverType))
-    if (const PointerType *PTy = receiverType->getAsPointerType())
-      receiverType = PTy->getPointeeType();
-    // else error, invalid receiver.
-  
+  ObjCMethodDecl *Method = 0;
   ObjCInterfaceDecl* ClassDecl = 0;
+  
+  // We allow sending a message to a qualified ID ("id<foo>"), which is ok as 
+  // long as one of the protocols implements the selector (if not, warn).
   if (ObjCQualifiedIdType *QIT = 
            dyn_cast<ObjCQualifiedIdType>(receiverType)) {
-    // search protocols
+    // Search protocols
     for (unsigned i = 0; i < QIT->getNumProtocols(); i++) {
       ObjCProtocolDecl *PDecl = QIT->getProtocols(i);
       if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
@@ -300,13 +296,9 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
       Diag(lbrac, diag::warn_method_not_found_in_protocol, 
            std::string("-"), Sel.getName(),
            SourceRange(lbrac, rbrac));
-  } else {
-    ObjCInterfaceType *OCIReceiver =dyn_cast<ObjCInterfaceType>(receiverType);
-    if (OCIReceiver == 0) {
-      Diag(lbrac, diag::error_bad_receiver_type,
-           RExpr->getType().getAsString());
-      return true;
-    }
+  } else if (const ObjCInterfaceType *OCIReceiver = 
+                receiverType->getAsPointerToObjCInterfaceType()) {
+    // We allow sending a message to a pointer to an interface (an object).
     
     ClassDecl = OCIReceiver->getDecl();
     // FIXME: consider using InstanceMethodPool, since it will be faster
@@ -327,6 +319,10 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
       Diag(lbrac, diag::warn_method_not_found_in_protocol, 
            std::string("-"), Sel.getName(),
            SourceRange(lbrac, rbrac));
+  } else {
+    Diag(lbrac, diag::error_bad_receiver_type,
+         RExpr->getType().getAsString());
+    return true;
   }
   
   if (!Method) {
index 303d80cf7ce8399893eff0eff612fcc7d9424e84..4478665f7accd65f3a2593174212d66e72072085 100644 (file)
@@ -11,13 +11,16 @@ void test1() {
 }
 
 void test2(NSNumber x) {
+       id objects[] = {[x METH]}; // expected-error {{bad receiver type}}
+}
+
+void test3(NSNumber *x) {
        id objects[] = {[x METH]};
-       return 0;
 }
 
 
 // rdar://5977581
-void test3() {
+void test4() {
   unsigned x[] = {[NSNumber METH2]+2};
 }