[cfe-commits] r102081 - in /cfe/trunk/lib/Sema: Sema.h SemaExprObjC.cpp TreeTransform.h

Douglas Gregor dgregor at apple.com
Thu Apr 22 10:01:48 PDT 2010


Author: dgregor
Date: Thu Apr 22 12:01:48 2010
New Revision: 102081

URL: http://llvm.org/viewvc/llvm-project?rev=102081&view=rev
Log:
When a dependent Objective-C++ message send was able to resolve the
method being called at template definition time, retain that method
and pass it through to type-checking. We will not perform any lookup
for the method during template instantiation.

Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/lib/Sema/TreeTransform.h

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=102081&r1=102080&r2=102081&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Apr 22 12:01:48 2010
@@ -3886,6 +3886,7 @@
                                      QualType ReceiverType,
                                      SourceLocation SuperLoc,
                                      Selector Sel,
+                                     ObjCMethodDecl *Method,
                                      SourceLocation LBracLoc, 
                                      SourceLocation RBracLoc,
                                      MultiExprArg Args);
@@ -3902,6 +3903,7 @@
                                         QualType ReceiverType,
                                         SourceLocation SuperLoc,
                                         Selector Sel,
+                                        ObjCMethodDecl *Method,
                                         SourceLocation LBracLoc, 
                                         SourceLocation RBracLoc,
                                         MultiExprArg Args);

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=102081&r1=102080&r2=102081&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Thu Apr 22 12:01:48 2010
@@ -643,14 +643,16 @@
     QualType SuperTy = Context.getObjCInterfaceType(Super);
     SuperTy = Context.getObjCObjectPointerType(SuperTy);
     return BuildInstanceMessage(ExprArg(*this), SuperTy, SuperLoc,
-                                Sel, LBracLoc, RBracLoc, move(Args));
+                                Sel, /*Method=*/0, LBracLoc, RBracLoc, 
+                                move(Args));
   }
   
   // Since we are in a class method, this is a class message to
   // the superclass.
   return BuildClassMessage(/*ReceiverTypeInfo=*/0,
                            Context.getObjCInterfaceType(Super),
-                           SuperLoc, Sel, LBracLoc, RBracLoc, move(Args));
+                           SuperLoc, Sel, /*Method=*/0, LBracLoc, RBracLoc, 
+                           move(Args));
 }
 
 /// \brief Build an Objective-C class message expression.
@@ -673,6 +675,9 @@
 ///
 /// \param Sel The selector to which the message is being sent.
 ///
+/// \param Method The method that this class message is invoking, if
+/// already known.
+///
 /// \param LBracLoc The location of the opening square bracket ']'.
 ///
 /// \param RBrac The location of the closing square bracket ']'.
@@ -682,6 +687,7 @@
                                                QualType ReceiverType,
                                                SourceLocation SuperLoc,
                                                Selector Sel,
+                                               ObjCMethodDecl *Method,
                                                SourceLocation LBracLoc, 
                                                SourceLocation RBracLoc,
                                                MultiExprArg ArgsIn) {
@@ -712,25 +718,26 @@
   assert(Class && "We don't know which class we're messaging?");
 
   // Find the method we are messaging.
-  ObjCMethodDecl *Method = 0;
-  if (Class->isForwardDecl()) {
-    // A forward class used in messaging is treated as a 'Class'
-    Diag(Loc, diag::warn_receiver_forward_class) << Class->getDeclName();
-    Method = LookupFactoryMethodInGlobalPool(Sel, 
-                                             SourceRange(LBracLoc, RBracLoc));
-    if (Method)
-      Diag(Method->getLocation(), diag::note_method_sent_forward_class)
-        << Method->getDeclName();
-  }
-  if (!Method)
-    Method = Class->lookupClassMethod(Sel);
+  if (!Method) {
+    if (Class->isForwardDecl()) {
+      // A forward class used in messaging is treated as a 'Class'
+      Diag(Loc, diag::warn_receiver_forward_class) << Class->getDeclName();
+      Method = LookupFactoryMethodInGlobalPool(Sel, 
+                                               SourceRange(LBracLoc, RBracLoc));
+      if (Method)
+        Diag(Method->getLocation(), diag::note_method_sent_forward_class)
+          << Method->getDeclName();
+    }
+    if (!Method)
+      Method = Class->lookupClassMethod(Sel);
 
-  // If we have an implementation in scope, check "private" methods.
-  if (!Method)
-    Method = LookupPrivateClassMethod(Sel, Class);
+    // If we have an implementation in scope, check "private" methods.
+    if (!Method)
+      Method = LookupPrivateClassMethod(Sel, Class);
 
-  if (Method && DiagnoseUseOfDecl(Method, Loc))
-    return ExprError();
+    if (Method && DiagnoseUseOfDecl(Method, Loc))
+      return ExprError();
+  }
 
   // Check the argument types and determine the result type.
   QualType ReturnType;
@@ -775,7 +782,7 @@
     ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc);
 
   return BuildClassMessage(ReceiverTypeInfo, ReceiverType, 
-                           /*SuperLoc=*/SourceLocation(), Sel, 
+                           /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
                            LBracLoc, RBracLoc, move(Args));
 }
 
@@ -799,6 +806,9 @@
 ///
 /// \param Sel The selector to which the message is being sent.
 ///
+/// \param Method The method that this instance message is invoking, if
+/// already known.
+///
 /// \param LBracLoc The location of the opening square bracket ']'.
 ///
 /// \param RBrac The location of the closing square bracket ']'.
@@ -808,6 +818,7 @@
                                                   QualType ReceiverType,
                                                   SourceLocation SuperLoc,
                                                   Selector Sel,
+                                                  ObjCMethodDecl *Method,
                                                   SourceLocation LBracLoc, 
                                                   SourceLocation RBracLoc,
                                                   MultiExprArg ArgsIn) {
@@ -836,125 +847,126 @@
   // The location of the receiver.
   SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
 
-  ObjCMethodDecl *Method = 0;
-  // Handle messages to id.
-  if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType() ||
-      (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
-    Method = LookupInstanceMethodInGlobalPool(Sel, 
+  if (!Method) {
+    // Handle messages to id.
+    if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType() ||
+        (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
+      Method = LookupInstanceMethodInGlobalPool(Sel, 
                                               SourceRange(LBracLoc, RBracLoc));
-    if (!Method)
-      Method = LookupFactoryMethodInGlobalPool(Sel, 
+      if (!Method)
+        Method = LookupFactoryMethodInGlobalPool(Sel, 
                                                SourceRange(LBracLoc, RBracLoc));
-  } else if (ReceiverType->isObjCClassType() ||
-             ReceiverType->isObjCQualifiedClassType()) {
-    // Handle messages to Class.
-    if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
-      if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
-        // First check the public methods in the class interface.
-        Method = ClassDecl->lookupClassMethod(Sel);
+    } else if (ReceiverType->isObjCClassType() ||
+               ReceiverType->isObjCQualifiedClassType()) {
+      // Handle messages to Class.
+      if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
+        if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
+          // First check the public methods in the class interface.
+          Method = ClassDecl->lookupClassMethod(Sel);
 
-        if (!Method)
-          Method = LookupPrivateClassMethod(Sel, ClassDecl);
+          if (!Method)
+            Method = LookupPrivateClassMethod(Sel, ClassDecl);
 
-        // FIXME: if we still haven't found a method, we need to look in
-        // protocols (if we have qualifiers).
-      }
-      if (Method && DiagnoseUseOfDecl(Method, Loc))
-        return ExprError();
-    }
-    if (!Method) {
-      // If not messaging 'self', look for any factory method named 'Sel'.
-      if (!Receiver || !isSelfExpr(Receiver)) {
-        Method = LookupFactoryMethodInGlobalPool(Sel, 
-                                             SourceRange(LBracLoc, RBracLoc));
-        if (!Method) {
-          // If no class (factory) method was found, check if an _instance_
-          // method of the same name exists in the root class only.
-          Method = LookupInstanceMethodInGlobalPool(Sel,
-                                             SourceRange(LBracLoc, RBracLoc));
-          if (Method)
-              if (const ObjCInterfaceDecl *ID =
-                dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
-              if (ID->getSuperClass())
-                Diag(Loc, diag::warn_root_inst_method_not_found)
-                  << Sel << SourceRange(LBracLoc, RBracLoc);
-            }
+          // FIXME: if we still haven't found a method, we need to look in
+          // protocols (if we have qualifiers).
         }
+        if (Method && DiagnoseUseOfDecl(Method, Loc))
+          return ExprError();
       }
-    }
-  } else {
-    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 (const ObjCObjectPointerType *QIdTy 
-                                 = ReceiverType->getAsObjCQualifiedIdType()) {
-      // Search protocols for instance methods.
-      for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
-             E = QIdTy->qual_end(); I != E; ++I) {
-        ObjCProtocolDecl *PDecl = *I;
-        if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
-          break;
-        // Since we aren't supporting "Class<foo>", look for a class method.
-        if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
-          break;
+      if (!Method) {
+        // If not messaging 'self', look for any factory method named 'Sel'.
+        if (!Receiver || !isSelfExpr(Receiver)) {
+          Method = LookupFactoryMethodInGlobalPool(Sel, 
+                                               SourceRange(LBracLoc, RBracLoc));
+          if (!Method) {
+            // If no class (factory) method was found, check if an _instance_
+            // method of the same name exists in the root class only.
+            Method = LookupInstanceMethodInGlobalPool(Sel,
+                                               SourceRange(LBracLoc, RBracLoc));
+            if (Method)
+                if (const ObjCInterfaceDecl *ID =
+                  dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
+                if (ID->getSuperClass())
+                  Diag(Loc, diag::warn_root_inst_method_not_found)
+                    << Sel << SourceRange(LBracLoc, RBracLoc);
+              }
+          }
+        }
       }
-    } else if (const ObjCObjectPointerType *OCIType
-                 = ReceiverType->getAsObjCInterfacePointerType()) {
-      // We allow sending a message to a pointer to an interface (an object).
-      ClassDecl = OCIType->getInterfaceDecl();
-      // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
-      // faster than the following method (which can do *many* linear searches).
-      // The idea is to add class info to InstanceMethodPool.
-      Method = ClassDecl->lookupInstanceMethod(Sel);
+    } else {
+      ObjCInterfaceDecl* ClassDecl = 0;
 
-      if (!Method) {
-        // Search protocol qualifiers.
-        for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(),
-               E = OCIType->qual_end(); QI != E; ++QI) {
-          if ((Method = (*QI)->lookupInstanceMethod(Sel)))
+      // 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 (const ObjCObjectPointerType *QIdTy 
+                                   = ReceiverType->getAsObjCQualifiedIdType()) {
+        // Search protocols for instance methods.
+        for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
+               E = QIdTy->qual_end(); I != E; ++I) {
+          ObjCProtocolDecl *PDecl = *I;
+          if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
+            break;
+          // Since we aren't supporting "Class<foo>", look for a class method.
+          if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
             break;
         }
-      }
-      if (!Method) {
-        // If we have implementations in scope, check "private" methods.
-        Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
+      } else if (const ObjCObjectPointerType *OCIType
+                   = ReceiverType->getAsObjCInterfacePointerType()) {
+        // We allow sending a message to a pointer to an interface (an object).
+        ClassDecl = OCIType->getInterfaceDecl();
+        // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
+        // faster than the following method (which can do *many* linear searches).
+        // The idea is to add class info to InstanceMethodPool.
+        Method = ClassDecl->lookupInstanceMethod(Sel);
 
-        if (!Method && (!Receiver || !isSelfExpr(Receiver))) {
-          // 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 (OCIType->qual_empty()) {
-            Method = LookupInstanceMethodInGlobalPool(Sel,
-                                               SourceRange(LBracLoc, RBracLoc));
-            if (Method && !OCIType->getInterfaceDecl()->isForwardDecl())
-              Diag(Loc, diag::warn_maynot_respond)
-                << OCIType->getInterfaceDecl()->getIdentifier() << Sel;
+        if (!Method) {
+          // Search protocol qualifiers.
+          for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(),
+                 E = OCIType->qual_end(); QI != E; ++QI) {
+            if ((Method = (*QI)->lookupInstanceMethod(Sel)))
+              break;
           }
         }
-      }
-      if (Method && DiagnoseUseOfDecl(Method, Loc))
+        if (!Method) {
+          // If we have implementations in scope, check "private" methods.
+          Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
+
+          if (!Method && (!Receiver || !isSelfExpr(Receiver))) {
+            // 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 (OCIType->qual_empty()) {
+              Method = LookupInstanceMethodInGlobalPool(Sel,
+                                                 SourceRange(LBracLoc, RBracLoc));
+              if (Method && !OCIType->getInterfaceDecl()->isForwardDecl())
+                Diag(Loc, diag::warn_maynot_respond)
+                  << OCIType->getInterfaceDecl()->getIdentifier() << Sel;
+            }
+          }
+        }
+        if (Method && DiagnoseUseOfDecl(Method, Loc))
+          return ExprError();
+      } else if (!Context.getObjCIdType().isNull() &&
+                 (ReceiverType->isPointerType() ||
+                  (ReceiverType->isIntegerType() &&
+                   ReceiverType->isScalarType()))) {
+        // Implicitly convert integers and pointers to 'id' but emit a warning.
+        Diag(Loc, diag::warn_bad_receiver_type)
+          << ReceiverType 
+          << Receiver->getSourceRange();
+        if (ReceiverType->isPointerType())
+          ImpCastExprToType(Receiver, Context.getObjCIdType(), 
+                            CastExpr::CK_BitCast);
+        else
+          ImpCastExprToType(Receiver, Context.getObjCIdType(),
+                            CastExpr::CK_IntegralToPointer);
+        ReceiverType = Receiver->getType();
+      } else {
+        // Reject other random receiver types (e.g. structs).
+        Diag(Loc, diag::err_bad_receiver_type)
+          << ReceiverType << Receiver->getSourceRange();
         return ExprError();
-    } else if (!Context.getObjCIdType().isNull() &&
-               (ReceiverType->isPointerType() ||
-                (ReceiverType->isIntegerType() &&
-                 ReceiverType->isScalarType()))) {
-      // Implicitly convert integers and pointers to 'id' but emit a warning.
-      Diag(Loc, diag::warn_bad_receiver_type)
-        << ReceiverType 
-        << Receiver->getSourceRange();
-      if (ReceiverType->isPointerType())
-        ImpCastExprToType(Receiver, Context.getObjCIdType(), 
-                          CastExpr::CK_BitCast);
-      else
-        ImpCastExprToType(Receiver, Context.getObjCIdType(),
-                          CastExpr::CK_IntegralToPointer);
-      ReceiverType = Receiver->getType();
-    } else {
-      // Reject other random receiver types (e.g. structs).
-      Diag(Loc, diag::err_bad_receiver_type)
-        << ReceiverType << Receiver->getSourceRange();
-      return ExprError();
+      }
     }
   }
 
@@ -992,7 +1004,7 @@
     return ExprError();
 
   return BuildInstanceMessage(move(ReceiverE), Receiver->getType(),
-                              /*SuperLoc=*/SourceLocation(),
-                              Sel, LBracLoc, RBracLoc, move(Args));
+                              /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, 
+                              LBracLoc, RBracLoc, move(Args));
 }
 

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=102081&r1=102080&r2=102081&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Apr 22 12:01:48 2010
@@ -1698,13 +1698,10 @@
                                           SourceLocation LBracLoc, 
                                           MultiExprArg Args,
                                           SourceLocation RBracLoc) {
-    // FIXME: Drops Method
     return SemaRef.BuildClassMessage(ReceiverTypeInfo,
                                      ReceiverTypeInfo->getType(),
                                      /*SuperLoc=*/SourceLocation(),
-                                     Sel,
-                                     LBracLoc,
-                                     RBracLoc,
+                                     Sel, Method, LBracLoc, RBracLoc,
                                      move(Args));
   }
 
@@ -1715,14 +1712,11 @@
                                           SourceLocation LBracLoc, 
                                           MultiExprArg Args,
                                           SourceLocation RBracLoc) {
-    // FIXME: Drops Method
     QualType ReceiverType = static_cast<Expr *>(Receiver.get())->getType();
     return SemaRef.BuildInstanceMessage(move(Receiver),
                                         ReceiverType,
                                         /*SuperLoc=*/SourceLocation(),
-                                        Sel,
-                                        LBracLoc,
-                                        RBracLoc,
+                                        Sel, Method, LBracLoc, RBracLoc,
                                         move(Args));
   }
 





More information about the cfe-commits mailing list