diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 191 |
3 files changed, 113 insertions, 111 deletions
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 4812b6d2e6..cb60f0aba1 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -2899,13 +2899,24 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { return 0; // Determine the class that we're sending the message to. - ObjCInterfaceDecl *IFace = Msg->getClassInfo().Decl; - if (!IFace) { - if (Expr *Receiver = Msg->getReceiver()) { - QualType T = Receiver->getType(); - if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>()) - IFace = Ptr->getInterfaceDecl(); - } + ObjCInterfaceDecl *IFace = 0; + switch (Msg->getReceiverKind()) { + case ObjCMessageExpr::Class: + if (const ObjCInterfaceType *IFaceType + = Msg->getClassReceiver()->getAs<ObjCInterfaceType>()) + IFace = IFaceType->getDecl(); + break; + + case ObjCMessageExpr::Instance: { + QualType T = Msg->getInstanceReceiver()->getType(); + if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>()) + IFace = Ptr->getInterfaceDecl(); + break; + } + + case ObjCMessageExpr::SuperInstance: + case ObjCMessageExpr::SuperClass: + break; } if (!IFace) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 9f33d42b47..265f44c999 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3130,10 +3130,10 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, if (DiagnoseUseOfDecl(OMD, MemberLoc)) return ExprError(); - return Owned(new (Context) ObjCMessageExpr(Context, BaseExpr, Sel, - OMD->getResultType(), - OMD, OpLoc, MemberLoc, - NULL, 0)); + return Owned(ObjCMessageExpr::Create(Context, + OMD->getResultType().getNonReferenceType(), + OpLoc, BaseExpr, Sel, + OMD, NULL, 0, MemberLoc)); } } diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 1feca6d25c..6be1e1923a 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -684,20 +684,19 @@ ActOnClassMessage(Scope *S, IdentifierInfo *receiverName, Selector Sel, returnType = returnType.getNonReferenceType(); - // FIXME: need to do a better job handling 'super' usage within a class. For - // now, we simply pass the "super" identifier through (which isn't consistent - // with instance methods. + QualType ReceiverType = Context.getObjCInterfaceType(ClassDecl); if (isSuper) - return new (Context) ObjCMessageExpr(Context, receiverName, receiverLoc, - Sel, returnType, Method, lbrac, rbrac, - ArgExprs, NumArgs); + return ObjCMessageExpr::Create(Context, returnType, lbrac, receiverLoc, + /*IsInstanceSuper=*/false,ReceiverType, + Sel, Method, ArgExprs, NumArgs, rbrac); // If we have the ObjCInterfaceDecl* for the class that is receiving the // message, use that to construct the ObjCMessageExpr. Otherwise pass on the // IdentifierInfo* for the class. - return new (Context) ObjCMessageExpr(Context, ClassDecl, receiverLoc, - Sel, returnType, Method, lbrac, rbrac, - ArgExprs, NumArgs); + TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(ReceiverType, + receiverLoc); + return ObjCMessageExpr::Create(Context, returnType, lbrac, TSInfo, Sel, + Method, ArgExprs, NumArgs, rbrac); } // ActOnInstanceMessage - used for both unary and keyword messages. @@ -717,6 +716,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, // C99 6.7.5.3p[7,8]. DefaultFunctionArrayLvalueConversion(RExpr); + ObjCMethodDecl *Method = 0; QualType returnType; QualType ReceiverCType = Context.getCanonicalType(RExpr->getType()).getUnqualifiedType(); @@ -724,24 +724,15 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, // Handle messages to id. if (ReceiverCType->isObjCIdType() || ReceiverCType->isBlockPointerType() || Context.isObjCNSObjectType(RExpr->getType())) { - ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool( - Sel, SourceRange(lbrac,rbrac)); + // FIXME: If our superclass is NSObject and we message 'super', + // we'll end up looking in the global method pool?? + + Method = LookupInstanceMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac)); if (!Method) Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac, rbrac)); - if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, - lbrac, rbrac, returnType)) - return true; - returnType = returnType.getNonReferenceType(); - return new (Context) ObjCMessageExpr(Context, RExpr, Sel, returnType, - Method, lbrac, rbrac, - ArgExprs, NumArgs); - } - - // Handle messages to Class. - if (ReceiverCType->isObjCClassType() || - ReceiverCType->isObjCQualifiedClassType()) { - ObjCMethodDecl *Method = 0; - + } else if (ReceiverCType->isObjCClassType() || + ReceiverCType->isObjCQualifiedClassType()) { + // Handle messages to Class. if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { // First check the public methods in the class interface. @@ -775,86 +766,78 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, } } } - if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, - lbrac, rbrac, returnType)) - return true; - returnType = returnType.getNonReferenceType(); - return new (Context) ObjCMessageExpr(Context, RExpr, Sel, returnType, - Method, lbrac, rbrac, - ArgExprs, NumArgs); - } - - ObjCMethodDecl *Method = 0; - ObjCInterfaceDecl* ClassDecl = 0; + } 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 = + // 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 = ReceiverCType->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; - } - } else if (const ObjCObjectPointerType *OCIType = - ReceiverCType->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) { - // Search protocol qualifiers. - for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(), - E = OCIType->qual_end(); QI != E; ++QI) { - if ((Method = (*QI)->lookupInstanceMethod(Sel))) + // 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); - - if (!Method && !isSelfExpr(RExpr)) { - // 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(lbrac,rbrac)); - if (Method && !OCIType->getInterfaceDecl()->isForwardDecl()) - Diag(lbrac, diag::warn_maynot_respond) - << OCIType->getInterfaceDecl()->getIdentifier() << Sel; + } else if (const ObjCObjectPointerType *OCIType = + ReceiverCType->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) { + // 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, receiverLoc)) + if (!Method) { + // If we have implementations in scope, check "private" methods. + Method = LookupPrivateInstanceMethod(Sel, ClassDecl); + + if (!Method && !isSelfExpr(RExpr)) { + // 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(lbrac,rbrac)); + if (Method && !OCIType->getInterfaceDecl()->isForwardDecl()) + Diag(lbrac, diag::warn_maynot_respond) + << OCIType->getInterfaceDecl()->getIdentifier() << Sel; + } + } + } + if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) + return true; + } else if (!Context.getObjCIdType().isNull() && + (ReceiverCType->isPointerType() || + (ReceiverCType->isIntegerType() && + ReceiverCType->isScalarType()))) { + // Implicitly convert integers and pointers to 'id' but emit a warning. + Diag(lbrac, diag::warn_bad_receiver_type) + << RExpr->getType() << RExpr->getSourceRange(); + if (ReceiverCType->isPointerType()) + ImpCastExprToType(RExpr, Context.getObjCIdType(), CastExpr::CK_BitCast); + else + ImpCastExprToType(RExpr, Context.getObjCIdType(), + CastExpr::CK_IntegralToPointer); + } else { + // Reject other random receiver types (e.g. structs). + Diag(lbrac, diag::err_bad_receiver_type) + << RExpr->getType() << RExpr->getSourceRange(); return true; - } else if (!Context.getObjCIdType().isNull() && - (ReceiverCType->isPointerType() || - (ReceiverCType->isIntegerType() && - ReceiverCType->isScalarType()))) { - // Implicitly convert integers and pointers to 'id' but emit a warning. - Diag(lbrac, diag::warn_bad_receiver_type) - << RExpr->getType() << RExpr->getSourceRange(); - if (ReceiverCType->isPointerType()) - ImpCastExprToType(RExpr, Context.getObjCIdType(), CastExpr::CK_BitCast); - else - ImpCastExprToType(RExpr, Context.getObjCIdType(), - CastExpr::CK_IntegralToPointer); - } else { - // Reject other random receiver types (e.g. structs). - Diag(lbrac, diag::err_bad_receiver_type) - << RExpr->getType() << RExpr->getSourceRange(); - return true; + } } if (Method) @@ -863,7 +846,15 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, lbrac, rbrac, returnType)) return true; returnType = returnType.getNonReferenceType(); - return new (Context) ObjCMessageExpr(Context, RExpr, Sel, returnType, Method, - lbrac, rbrac, ArgExprs, NumArgs); + + if (isa<ObjCSuperExpr>(RExpr)) + return ObjCMessageExpr::Create(Context, returnType, lbrac, + RExpr->getLocStart(), + /*IsInstanceSuper=*/true, + RExpr->getType(), + Sel, Method, ArgExprs, NumArgs, rbrac); + + return ObjCMessageExpr::Create(Context, returnType, lbrac, RExpr, Sel, + Method, ArgExprs, NumArgs, rbrac); } |