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.cpp65
1 files changed, 43 insertions, 22 deletions
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 9eaf747ae79..ce80db7ca6e 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -1346,7 +1346,8 @@ static QualType getBaseMessageSendResultType(Sema &S,
return transferNullability(ReceiverType);
}
-QualType Sema::getMessageSendResultType(QualType ReceiverType,
+QualType Sema::getMessageSendResultType(const Expr *Receiver,
+ QualType ReceiverType,
ObjCMethodDecl *Method,
bool isClassMessage,
bool isSuperMessage) {
@@ -1357,8 +1358,33 @@ QualType Sema::getMessageSendResultType(QualType ReceiverType,
isSuperMessage);
// If this is a class message, ignore the nullability of the receiver.
- if (isClassMessage)
+ if (isClassMessage) {
+ // In a class method, class messages to 'self' that return instancetype can
+ // be typed as the current class. We can safely do this in ARC because self
+ // can't be reassigned, and we do it unsafely outside of ARC because in
+ // practice people never reassign self in class methods and there's some
+ // virtue in not being aggressively pedantic.
+ if (Receiver && Receiver->isObjCSelfExpr()) {
+ assert(ReceiverType->isObjCClassType() && "expected a Class self");
+ QualType T = Method->getSendResultType(ReceiverType);
+ AttributedType::stripOuterNullability(T);
+ if (T == Context.getObjCInstanceType()) {
+ const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(
+ cast<ImplicitParamDecl>(
+ cast<DeclRefExpr>(Receiver->IgnoreParenImpCasts())->getDecl())
+ ->getDeclContext());
+ assert(MD->isClassMethod() && "expected a class method");
+ QualType NewResultType = Context.getObjCObjectPointerType(
+ Context.getObjCInterfaceType(MD->getClassInterface()));
+ if (auto Nullability = resultType->getNullability(Context))
+ NewResultType = Context.getAttributedType(
+ AttributedType::getNullabilityAttrKind(*Nullability),
+ NewResultType, NewResultType);
+ return NewResultType;
+ }
+ }
return resultType;
+ }
// There is nothing left to do if the result type cannot have a nullability
// specifier.
@@ -1505,15 +1531,12 @@ void Sema::EmitRelatedResultTypeNote(const Expr *E) {
<< MsgSend->getType();
}
-bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
- MultiExprArg Args,
- Selector Sel,
- ArrayRef<SourceLocation> SelectorLocs,
- ObjCMethodDecl *Method,
- bool isClassMessage, bool isSuperMessage,
- SourceLocation lbrac, SourceLocation rbrac,
- SourceRange RecRange,
- QualType &ReturnType, ExprValueKind &VK) {
+bool Sema::CheckMessageArgumentTypes(
+ const Expr *Receiver, QualType ReceiverType, MultiExprArg Args,
+ Selector Sel, ArrayRef<SourceLocation> SelectorLocs, ObjCMethodDecl *Method,
+ bool isClassMessage, bool isSuperMessage, SourceLocation lbrac,
+ SourceLocation rbrac, SourceRange RecRange, QualType &ReturnType,
+ ExprValueKind &VK) {
SourceLocation SelLoc;
if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
SelLoc = SelectorLocs.front();
@@ -1590,8 +1613,8 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
return false;
}
- ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage,
- isSuperMessage);
+ ReturnType = getMessageSendResultType(Receiver, ReceiverType, Method,
+ isClassMessage, isSuperMessage);
VK = Expr::getValueKindForType(Method->getReturnType());
unsigned NumNamedArgs = Sel.getNumArgs();
@@ -2482,12 +2505,10 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
unsigned NumArgs = ArgsIn.size();
Expr **Args = ArgsIn.data();
- if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs),
- Sel, SelectorLocs,
- Method, true,
- SuperLoc.isValid(), LBracLoc, RBracLoc,
- SourceRange(),
- ReturnType, VK))
+ if (CheckMessageArgumentTypes(/*Receiver=*/nullptr, ReceiverType,
+ MultiExprArg(Args, NumArgs), Sel, SelectorLocs,
+ Method, true, SuperLoc.isValid(), LBracLoc,
+ RBracLoc, SourceRange(), ReturnType, VK))
return ExprError();
if (Method && !Method->getReturnType()->isVoidType() &&
@@ -2982,9 +3003,9 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
ExprValueKind VK = VK_RValue;
bool ClassMessage = (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType());
- if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs),
- Sel, SelectorLocs, Method,
- ClassMessage, SuperLoc.isValid(),
+ if (CheckMessageArgumentTypes(Receiver, ReceiverType,
+ MultiExprArg(Args, NumArgs), Sel, SelectorLocs,
+ Method, ClassMessage, SuperLoc.isValid(),
LBracLoc, RBracLoc, RecRange, ReturnType, VK))
return ExprError();
OpenPOWER on IntegriCloud