summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExprObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaExprObjC.cpp')
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp67
1 files changed, 63 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 8db4e0ba74a..687348c90a8 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -1170,6 +1170,35 @@ static void DiagnoseMismatchedSelectors(Sema &S, SourceLocation AtLoc,
}
}
+static void HelperToDiagnoseDirectSelectorsExpr(Sema &S, SourceLocation AtLoc,
+ Selector Sel,
+ ObjCMethodList &MethList,
+ bool &onlyDirect) {
+ ObjCMethodList *M = &MethList;
+ for (M = M->getNext(); M; M = M->getNext()) {
+ ObjCMethodDecl *Method = M->getMethod();
+ if (Method->getSelector() != Sel)
+ continue;
+ if (!Method->isDirectMethod())
+ onlyDirect = false;
+ }
+}
+
+static void DiagnoseDirectSelectorsExpr(Sema &S, SourceLocation AtLoc,
+ Selector Sel, bool &onlyDirect) {
+ for (Sema::GlobalMethodPool::iterator b = S.MethodPool.begin(),
+ e = S.MethodPool.end(); b != e; b++) {
+ // first, instance methods
+ ObjCMethodList &InstMethList = b->second.first;
+ HelperToDiagnoseDirectSelectorsExpr(S, AtLoc, Sel, InstMethList,
+ onlyDirect);
+
+ // second, class methods
+ ObjCMethodList &ClsMethList = b->second.second;
+ HelperToDiagnoseDirectSelectorsExpr(S, AtLoc, Sel, ClsMethList, onlyDirect);
+ }
+}
+
ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
SourceLocation AtLoc,
SourceLocation SelLoc,
@@ -1192,9 +1221,18 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
} else
Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
- } else
+ } else {
+ bool onlyDirect = Method->isDirectMethod();
+ DiagnoseDirectSelectorsExpr(*this, AtLoc, Sel, onlyDirect);
DiagnoseMismatchedSelectors(*this, AtLoc, Method, LParenLoc, RParenLoc,
WarnMultipleSelectors);
+ if (onlyDirect) {
+ Diag(AtLoc, diag::err_direct_selector_expression)
+ << Method->getSelector();
+ Diag(Method->getLocation(), diag::note_direct_method_declared_at)
+ << Method->getDeclName();
+ }
+ }
if (Method &&
Method->getImplementationControl() != ObjCMethodDecl::Optional &&
@@ -2767,9 +2805,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
}
}
- if (ReceiverType->isObjCIdType() && !isImplicit)
- Diag(Receiver->getExprLoc(), diag::warn_messaging_unqualified_id);
-
// 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.
@@ -2971,6 +3006,30 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
(Method && Method->getMethodFamily() == OMF_init)
? getEnclosingFunction() : nullptr;
+ if (Method && Method->isDirectMethod()) {
+ if (ReceiverType->isObjCIdType() && !isImplicit) {
+ Diag(Receiver->getExprLoc(),
+ diag::err_messaging_unqualified_id_with_direct_method);
+ Diag(Method->getLocation(), diag::note_direct_method_declared_at)
+ << Method->getDeclName();
+ }
+
+ if (ReceiverType->isObjCClassType() && !isImplicit) {
+ Diag(Receiver->getExprLoc(),
+ diag::err_messaging_class_with_direct_method);
+ Diag(Method->getLocation(), diag::note_direct_method_declared_at)
+ << Method->getDeclName();
+ }
+
+ if (SuperLoc.isValid()) {
+ Diag(SuperLoc, diag::err_messaging_super_with_direct_method);
+ Diag(Method->getLocation(), diag::note_direct_method_declared_at)
+ << Method->getDeclName();
+ }
+ } else if (ReceiverType->isObjCIdType() && !isImplicit) {
+ Diag(Receiver->getExprLoc(), diag::warn_messaging_unqualified_id);
+ }
+
if (DIFunctionScopeInfo &&
DIFunctionScopeInfo->ObjCIsDesignatedInit &&
(SuperLoc.isValid() || isSelfExpr(Receiver))) {
OpenPOWER on IntegriCloud