r215577 - Objective-C. This patch is to resolve the method used in method

Fariborz Jahanian fjahanian at apple.com
Wed Aug 13 14:07:35 PDT 2014


Author: fjahanian
Date: Wed Aug 13 16:07:35 2014
New Revision: 215577

URL: http://llvm.org/viewvc/llvm-project?rev=215577&view=rev
Log:
Objective-C. This patch is to resolve the method used in method
expression to the best method found in global method pools. 
This is wip.  // rdar://16808765

Added:
    cfe/trunk/test/SemaObjC/resolve-method-in-global-pool.m
Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaObjC/warn-strict-selector-match.m

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=215577&r1=215576&r2=215577&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Aug 13 16:07:35 2014
@@ -2883,6 +2883,19 @@ private:
   ObjCMethodDecl *LookupMethodInGlobalPool(Selector Sel, SourceRange R,
                                            bool receiverIdOrClass,
                                            bool warn, bool instance);
+  
+  /// \brief - Returns instance or factory methods in global method pool for
+  /// given selector. If no such method or only one method found, function returns
+  /// false; otherwise, it returns true
+  bool CollectMultipleMethodsInGlobalPool(Selector Sel,
+                                          SmallVectorImpl<ObjCMethodDecl*>& Methods,
+                                          bool instance);
+    
+  /// \brief - Returns a selector which best matches given argument list or
+  /// nullptr if none could be found
+  ObjCMethodDecl *SelectBestMethod(Selector Sel, MultiExprArg Args,
+                                   SmallVectorImpl<ObjCMethodDecl*>& Methods);
+    
 
   /// \brief Record the typo correction failure and return an empty correction.
   TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc,

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=215577&r1=215576&r2=215577&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Wed Aug 13 16:07:35 2014
@@ -2315,6 +2315,23 @@ static bool isAcceptableMethodMismatch(O
   return (chosen->getReturnType()->isIntegerType());
 }
 
+bool Sema::CollectMultipleMethodsInGlobalPool(Selector Sel,
+                                              SmallVectorImpl<ObjCMethodDecl*>& Methods,
+                                              bool instance) {
+  if (ExternalSource)
+    ReadMethodPool(Sel);
+
+  GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
+  if (Pos == MethodPool.end())
+    return false;
+  // Gather the non-hidden methods.
+  ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
+  for (ObjCMethodList *M = &MethList; M; M = M->getNext())
+    if (M->Method && !M->Method->isHidden())
+      Methods.push_back(M->Method);
+  return (Methods.size() > 1);
+}
+
 ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
                                                bool receiverIdOrClass,
                                                bool warn, bool instance) {

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=215577&r1=215576&r2=215577&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Wed Aug 13 16:07:35 2014
@@ -2418,6 +2418,13 @@ ExprResult Sema::BuildInstanceMessage(Ex
         Method = LookupFactoryMethodInGlobalPool(Sel, 
                                                  SourceRange(LBracLoc,RBracLoc),
                                                  receiverIsId);
+      if (Method) {
+        SmallVector<ObjCMethodDecl*, 4> Methods;
+        if (CollectMultipleMethodsInGlobalPool(Sel, Methods,
+                                               Method->isInstanceMethod()))
+          if (ObjCMethodDecl *BestMethod = SelectBestMethod(Sel, ArgsIn, Methods))
+            Method = BestMethod;
+      }
     } else if (ReceiverType->isObjCClassType() ||
                ReceiverType->isObjCQualifiedClassType()) {
       // Handle messages to Class.

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=215577&r1=215576&r2=215577&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Aug 13 16:07:35 2014
@@ -5677,6 +5677,79 @@ Sema::AddOverloadCandidate(FunctionDecl
   }
 }
 
+ObjCMethodDecl *Sema::SelectBestMethod(Selector Sel, MultiExprArg Args,
+                                       SmallVectorImpl<ObjCMethodDecl*>& Methods) {
+  for (unsigned b = 0, e = Methods.size(); b < e; b++) {
+    bool Match = true;
+    ObjCMethodDecl *Method = Methods[b];
+    unsigned NumNamedArgs = Sel.getNumArgs();
+    // Method might have more arguments than selector indicates. This is due
+    // to addition of c-style arguments in method.
+    if (Method->param_size() > NumNamedArgs)
+      NumNamedArgs = Method->param_size();
+    if (Args.size() < NumNamedArgs)
+      continue;
+            
+    for (unsigned i = 0; i < NumNamedArgs; i++) {
+      // We can't do any type-checking on a type-dependent argument.
+      if (Args[i]->isTypeDependent()) {
+        Match = false;
+        break;
+      }
+        
+      ParmVarDecl *param = Method->parameters()[i];
+      Expr *argExpr = Args[i];
+      assert(argExpr && "SelectBestMethod(): missing expression");
+                
+      // Strip the unbridged-cast placeholder expression off unless it's
+      // a consumed argument.
+      if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) &&
+          !param->hasAttr<CFConsumedAttr>())
+        argExpr = stripARCUnbridgedCast(argExpr);
+                
+      // If the parameter is __unknown_anytype, move on to the next method.
+      if (param->getType() == Context.UnknownAnyTy) {
+        Match = false;
+        break;
+      }
+                
+      ImplicitConversionSequence ConversionState
+        = TryCopyInitialization(*this, argExpr, param->getType(),
+                                /*SuppressUserConversions*/false,
+                                /*InOverloadResolution=*/true,
+                                /*AllowObjCWritebackConversion=*/
+                                getLangOpts().ObjCAutoRefCount,
+                                /*AllowExplicit*/false);
+        if (ConversionState.isBad()) {
+          Match = false;
+          break;
+        }
+    }
+    // Promote additional arguments to variadic methods.
+    if (Match && Method->isVariadic()) {
+      for (unsigned i = NumNamedArgs, e = Args.size(); i < e; ++i) {
+        if (Args[i]->isTypeDependent()) {
+          Match = false;
+          break;
+        }
+        ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod,
+                                                          nullptr);
+        if (Arg.isInvalid()) {
+          Match = false;
+          break;
+        }
+      }
+    } else
+      // Check for extra arguments to non-variadic methods.
+      if (Args.size() != NumNamedArgs)
+        Match = false;
+
+    if (Match)
+      return Method;
+  }
+  return nullptr;
+}
+
 static bool IsNotEnableIfAttr(Attr *A) { return !isa<EnableIfAttr>(A); }
 
 EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,

Added: cfe/trunk/test/SemaObjC/resolve-method-in-global-pool.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/resolve-method-in-global-pool.m?rev=215577&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/resolve-method-in-global-pool.m (added)
+++ cfe/trunk/test/SemaObjC/resolve-method-in-global-pool.m Wed Aug 13 16:07:35 2014
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -fblocks -Wno-objc-root-class %s
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fsyntax-only -verify -fblocks -Wno-objc-root-class %s
+// expected-no-diagnostics
+
+// rdar://16808765
+
+ at interface NSObject @end
+
+ at class NSDictionary;
+ at class NSError;
+
+ at interface Foo : NSObject
+- (void)getDonuts:(void (^)(NSDictionary *, NSError *))replyBlock;
+- (void)getCake:(int*)arg, ...;
+ at end
+
+ at protocol Protocol
+ at required
+- (void)getDonuts:(void (^)(NSDictionary *))replyBlock;
+- (void)getCake:(float*)arg, ...;
+ at end
+
+ at implementation Foo
+{
+  float g;
+}
+
+- (void)getDonuts:(void (^)(NSDictionary *, NSError *))replyBlock {
+    [(id) 0 getDonuts:^(NSDictionary *replyDict) { }];
+}
+
+- (void) getCake:(int*)arg, ... {
+    [(id)0 getCake: &g, 1,3.14];
+}
+ at end

Modified: cfe/trunk/test/SemaObjC/warn-strict-selector-match.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/warn-strict-selector-match.m?rev=215577&r1=215576&r2=215577&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/warn-strict-selector-match.m (original)
+++ cfe/trunk/test/SemaObjC/warn-strict-selector-match.m Wed Aug 13 16:07:35 2014
@@ -29,8 +29,7 @@ id foo(void) {
 }
 
 @protocol MyObject
-- (id)initWithData:(Object *)data;	// expected-note {{using}} \
-					// expected-note {{passing argument to parameter 'data' here}}
+- (id)initWithData:(Object *)data;	// expected-note {{using}} 
 @end
 
 @protocol SomeOther
@@ -54,8 +53,7 @@ id foo(void) {
 }
 + (NTGridDataObject*)dataObject:(id<MyObject, MyCoding>)data
 {
-    NTGridDataObject *result = [(id)0 initWithData:data]; // expected-warning {{multiple methods named 'initWithData:' found}} \
-    expected-warning {{sending 'id<MyObject,MyCoding>' to parameter of incompatible type 'Object *'}}
+    NTGridDataObject *result = [(id)0 initWithData:data]; // expected-warning {{multiple methods named 'initWithData:' found}} 
     return result;
 }
 @end





More information about the cfe-commits mailing list