summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2014-08-13 21:07:35 +0000
committerFariborz Jahanian <fjahanian@apple.com>2014-08-13 21:07:35 +0000
commit30ae8d44139baea8e5e8941d56aa6cc92e5f0239 (patch)
treebc63f90474c9d9fbedf44ddeafd668a5eccca264 /clang/lib
parentabea99f65a97248974c02a5544eaf25fc4240056 (diff)
downloadbcm5719-llvm-30ae8d44139baea8e5e8941d56aa6cc92e5f0239.tar.gz
bcm5719-llvm-30ae8d44139baea8e5e8941d56aa6cc92e5f0239.zip
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 llvm-svn: 215577
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp17
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp7
-rw-r--r--clang/lib/Sema/SemaOverload.cpp73
3 files changed, 97 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 469e45c7535..8e3e85ed281 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -2315,6 +2315,23 @@ static bool isAcceptableMethodMismatch(ObjCMethodDecl *chosen,
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) {
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 3e7b6204661..6cc1658934d 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -2418,6 +2418,13 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
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.
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index d719b84c96c..660d60da2a3 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -5677,6 +5677,79 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
}
}
+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,
OpenPOWER on IntegriCloud