summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExprObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaExprObjC.cpp')
-rw-r--r--lib/Sema/SemaExprObjC.cpp446
1 files changed, 111 insertions, 335 deletions
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 7bb6b44c39cf9..d7e4e4a67fe96 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -20,7 +20,7 @@
using namespace clang;
-Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
+Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
ExprTy **strings,
unsigned NumStrings) {
StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings);
@@ -30,40 +30,40 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
// each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one
// StringLiteral for ObjCStringLiteral to hold onto.
StringLiteral *S = Strings[0];
-
+
// If we have a multi-part string, merge it all together.
if (NumStrings != 1) {
// Concatenate objc strings.
llvm::SmallString<128> StrBuf;
llvm::SmallVector<SourceLocation, 8> StrLocs;
-
+
for (unsigned i = 0; i != NumStrings; ++i) {
S = Strings[i];
-
+
// ObjC strings can't be wide.
if (S->isWide()) {
Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant)
<< S->getSourceRange();
return true;
}
-
+
// Get the string data.
StrBuf.append(S->getStrData(), S->getStrData()+S->getByteLength());
-
+
// Get the locations of the string tokens.
StrLocs.append(S->tokloc_begin(), S->tokloc_end());
-
+
// Free the temporary string.
S->Destroy(Context);
}
-
+
// Create the aggregate string with the appropriate content and location
// information.
S = StringLiteral::Create(Context, &StrBuf[0], StrBuf.size(), false,
Context.getPointerType(Context.CharTy),
&StrLocs[0], StrLocs.size());
}
-
+
// Verify that this composite string is acceptable for ObjC strings.
if (CheckObjCString(S))
return true;
@@ -74,29 +74,29 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
// interface private (even though it appears in the header files).
QualType Ty = Context.getObjCConstantStringInterface();
if (!Ty.isNull()) {
- Ty = Context.getPointerType(Ty);
+ Ty = Context.getObjCObjectPointerType(Ty);
} else {
IdentifierInfo *NSIdent = &Context.Idents.get("NSString");
- NamedDecl *IF = LookupName(TUScope, NSIdent, LookupOrdinaryName);
+ NamedDecl *IF = LookupSingleName(TUScope, NSIdent, LookupOrdinaryName);
if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) {
Context.setObjCConstantStringInterface(StrIF);
Ty = Context.getObjCConstantStringInterface();
- Ty = Context.getPointerType(Ty);
+ Ty = Context.getObjCObjectPointerType(Ty);
} else {
// If there is no NSString interface defined then treat constant
// strings as untyped objects and let the runtime figure it out later.
Ty = Context.getObjCIdType();
}
}
-
+
return new (Context) ObjCStringLiteral(S, Ty, AtLocs[0]);
}
-Expr *Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
+Expr *Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
QualType EncodedType,
SourceLocation RParenLoc) {
QualType StrTy;
- if (EncodedType->isDependentType())
+ if (EncodedType->isDependentType())
StrTy = Context.DependentTy;
else {
std::string Str;
@@ -111,7 +111,7 @@ Expr *Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1),
ArrayType::Normal, 0);
}
-
+
return new (Context) ObjCEncodeExpr(StrTy, EncodedType, AtLoc, RParenLoc);
}
@@ -120,7 +120,8 @@ Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
SourceLocation LParenLoc,
TypeTy *ty,
SourceLocation RParenLoc) {
- QualType EncodedType = QualType::getFromOpaquePtr(ty);
+ // FIXME: Preserve type source info ?
+ QualType EncodedType = GetTypeFromParser(ty);
return BuildObjCEncodeExpression(AtLoc, EncodedType, RParenLoc);
}
@@ -130,8 +131,8 @@ Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
SourceLocation SelLoc,
SourceLocation LParenLoc,
SourceLocation RParenLoc) {
- ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
- SourceRange(LParenLoc, RParenLoc));
+ ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
+ SourceRange(LParenLoc, RParenLoc), false);
if (!Method)
Method = LookupFactoryMethodInGlobalPool(Sel,
SourceRange(LParenLoc, RParenLoc));
@@ -152,19 +153,19 @@ Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
return true;
}
-
+
QualType Ty = Context.getObjCProtoType();
if (Ty.isNull())
return true;
- Ty = Context.getPointerType(Ty);
+ Ty = Context.getObjCObjectPointerType(Ty);
return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc);
}
-bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
- Selector Sel, ObjCMethodDecl *Method,
+bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
+ Selector Sel, ObjCMethodDecl *Method,
bool isClassMessage,
SourceLocation lbrac, SourceLocation rbrac,
- QualType &ReturnType) {
+ QualType &ReturnType) {
if (!Method) {
// Apply default argument promotion as for (C99 6.5.2.2p6).
for (unsigned i = 0; i != NumArgs; i++)
@@ -177,9 +178,9 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
ReturnType = Context.getObjCIdType();
return false;
}
-
+
ReturnType = Method->getResultType();
-
+
unsigned NumNamedArgs = Sel.getNumArgs();
assert(NumArgs >= NumNamedArgs && "Too few arguments for selector!");
@@ -187,22 +188,22 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
for (unsigned i = 0; i < NumNamedArgs; i++) {
Expr *argExpr = Args[i];
assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
-
+
QualType lhsType = Method->param_begin()[i]->getType();
QualType rhsType = argExpr->getType();
- // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
+ // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8].
if (lhsType->isArrayType())
lhsType = Context.getArrayDecayedType(lhsType);
else if (lhsType->isFunctionType())
lhsType = Context.getPointerType(lhsType);
- AssignConvertType Result =
+ AssignConvertType Result =
CheckSingleAssignmentConstraints(lhsType, argExpr);
if (Args[i] != argExpr) // The expression was converted.
Args[i] = argExpr; // Make sure we store the converted expression.
-
- IsError |=
+
+ IsError |=
DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType,
argExpr, "sending");
}
@@ -214,7 +215,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
} else {
// Check for extra arguments to non-variadic methods.
if (NumArgs != NumNamedArgs) {
- Diag(Args[NumNamedArgs]->getLocStart(),
+ Diag(Args[NumNamedArgs]->getLocStart(),
diag::err_typecheck_call_too_many_args)
<< 2 /*method*/ << Method->getSourceRange()
<< SourceRange(Args[NumNamedArgs]->getLocStart(),
@@ -241,29 +242,24 @@ ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel,
ObjCMethodDecl *Method = 0;
// lookup in class and all superclasses
while (ClassDecl && !Method) {
- if (ObjCImplementationDecl *ImpDecl
- = LookupObjCImplementation(ClassDecl->getIdentifier()))
+ if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
Method = ImpDecl->getClassMethod(Sel);
-
+
// Look through local category implementations associated with the class.
- if (!Method) {
- for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) {
- if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl)
- Method = ObjCCategoryImpls[i]->getClassMethod(Sel);
- }
- }
-
+ if (!Method)
+ Method = ClassDecl->getCategoryClassMethod(Sel);
+
// Before we give up, check if the selector is an instance method.
// But only in the root. This matches gcc's behaviour and what the
// runtime expects.
if (!Method && !ClassDecl->getSuperClass()) {
Method = ClassDecl->lookupInstanceMethod(Sel);
- // Look through local category implementations associated
+ // Look through local category implementations associated
// with the root class.
- if (!Method)
+ if (!Method)
Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
}
-
+
ClassDecl = ClassDecl->getSuperClass();
}
return Method;
@@ -274,17 +270,12 @@ ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel,
ObjCMethodDecl *Method = 0;
while (ClassDecl && !Method) {
// If we have implementations in scope, check "private" methods.
- if (ObjCImplementationDecl *ImpDecl
- = LookupObjCImplementation(ClassDecl->getIdentifier()))
+ if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
Method = ImpDecl->getInstanceMethod(Sel);
-
+
// Look through local category implementations associated with the class.
- if (!Method) {
- for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) {
- if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl)
- Method = ObjCCategoryImpls[i]->getInstanceMethod(Sel);
- }
- }
+ if (!Method)
+ Method = ClassDecl->getCategoryInstanceMethod(Sel);
ClassDecl = ClassDecl->getSuperClass();
}
return Method;
@@ -295,11 +286,11 @@ Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
IdentifierInfo &propertyName,
SourceLocation &receiverNameLoc,
SourceLocation &propertyNameLoc) {
-
+
ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(&receiverName);
-
+
// Search for a declared property first.
-
+
Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName);
ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel);
@@ -307,8 +298,7 @@ Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
if (!Getter)
if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
- if (ObjCImplementationDecl *ImpDecl
- = LookupObjCImplementation(ClassDecl->getIdentifier()))
+ if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
Getter = ImpDecl->getClassMethod(Sel);
if (Getter) {
@@ -317,29 +307,24 @@ Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
if (DiagnoseUseOfDecl(Getter, propertyNameLoc))
return ExprError();
}
-
+
// Look for the matching setter, in case it is needed.
- Selector SetterSel =
- SelectorTable::constructSetterName(PP.getIdentifierTable(),
+ Selector SetterSel =
+ SelectorTable::constructSetterName(PP.getIdentifierTable(),
PP.getSelectorTable(), &propertyName);
-
+
ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
if (!Setter) {
// If this reference is in an @implementation, also check for 'private'
// methods.
if (ObjCMethodDecl *CurMeth = getCurMethodDecl())
if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
- if (ObjCImplementationDecl *ImpDecl
- = LookupObjCImplementation(ClassDecl->getIdentifier()))
+ if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation())
Setter = ImpDecl->getClassMethod(SetterSel);
}
// Look through local category implementations associated with the class.
- if (!Setter) {
- for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Setter; i++) {
- if (ObjCCategoryImpls[i]->getClassInterface() == IFace)
- Setter = ObjCCategoryImpls[i]->getClassMethod(SetterSel);
- }
- }
+ if (!Setter)
+ Setter = IFace->getCategoryClassMethod(SetterSel);
if (Setter && DiagnoseUseOfDecl(Setter, propertyNameLoc))
return ExprError();
@@ -354,7 +339,8 @@ Action::OwningExprResult Sema::ActOnClassPropertyRefExpr(
E = Setter->param_end(); PI != E; ++PI)
PType = (*PI)->getType();
}
- return Owned(new (Context) ObjCKVCRefExpr(Getter, PType, Setter,
+ return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(
+ Getter, PType, Setter,
propertyNameLoc, IFace, receiverNameLoc));
}
return ExprError(Diag(propertyNameLoc, diag::err_property_not_found)
@@ -369,32 +355,31 @@ Sema::ExprResult Sema::ActOnClassMessage(
Scope *S,
IdentifierInfo *receiverName, Selector Sel,
SourceLocation lbrac, SourceLocation receiverLoc,
- SourceLocation selectorLoc, SourceLocation rbrac,
- ExprTy **Args, unsigned NumArgs)
-{
+ SourceLocation selectorLoc, SourceLocation rbrac,
+ ExprTy **Args, unsigned NumArgs) {
assert(receiverName && "missing receiver class name");
Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
ObjCInterfaceDecl* ClassDecl = 0;
bool isSuper = false;
-
+
if (receiverName->isStr("super")) {
if (getCurMethodDecl()) {
isSuper = true;
ObjCInterfaceDecl *OID = getCurMethodDecl()->getClassInterface();
if (!OID)
- return Diag(lbrac, diag::error_no_super_class_message)
+ return Diag(lbrac, diag::error_no_super_class_message)
<< getCurMethodDecl()->getDeclName();
ClassDecl = OID->getSuperClass();
if (!ClassDecl)
return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName();
if (getCurMethodDecl()->isInstanceMethod()) {
QualType superTy = Context.getObjCInterfaceType(ClassDecl);
- superTy = Context.getPointerType(superTy);
+ superTy = Context.getObjCObjectPointerType(superTy);
ExprResult ReceiverExpr = new (Context) ObjCSuperExpr(SourceLocation(),
superTy);
// We are really in an instance method, redirect.
- return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
+ return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
selectorLoc, rbrac, Args, NumArgs);
}
// We are sending a message to 'super' within a class method. Do nothing,
@@ -402,20 +387,21 @@ Sema::ExprResult Sema::ActOnClassMessage(
} else {
// 'super' has been used outside a method context. If a variable named
// 'super' has been declared, redirect. If not, produce a diagnostic.
- NamedDecl *SuperDecl = LookupName(S, receiverName, LookupOrdinaryName);
+ NamedDecl *SuperDecl
+ = LookupSingleName(S, receiverName, LookupOrdinaryName);
ValueDecl *VD = dyn_cast_or_null<ValueDecl>(SuperDecl);
if (VD) {
- ExprResult ReceiverExpr = new (Context) DeclRefExpr(VD, VD->getType(),
+ ExprResult ReceiverExpr = new (Context) DeclRefExpr(VD, VD->getType(),
receiverLoc);
// We are really in an instance method, redirect.
- return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
+ return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac,
selectorLoc, rbrac, Args, NumArgs);
}
return Diag(receiverLoc, diag::err_undeclared_var_use) << receiverName;
- }
+ }
} else
ClassDecl = getObjCInterfaceDecl(receiverName);
-
+
// The following code allows for the following GCC-ism:
//
// typedef XCElementDisplayRect XCElementGraphicsRect;
@@ -427,10 +413,11 @@ Sema::ExprResult Sema::ActOnClassMessage(
//
// If necessary, the following lookup could move to getObjCInterfaceDecl().
if (!ClassDecl) {
- NamedDecl *IDecl = LookupName(TUScope, receiverName, LookupOrdinaryName);
+ NamedDecl *IDecl
+ = LookupSingleName(TUScope, receiverName, LookupOrdinaryName);
if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(IDecl)) {
const ObjCInterfaceType *OCIT;
- OCIT = OCTD->getUnderlyingType()->getAsObjCInterfaceType();
+ OCIT = OCTD->getUnderlyingType()->getAs<ObjCInterfaceType>();
if (!OCIT) {
Diag(receiverLoc, diag::err_invalid_receiver_to_message);
return true;
@@ -446,25 +433,25 @@ Sema::ExprResult Sema::ActOnClassMessage(
Diag(lbrac, diag::warn_receiver_forward_class) << ClassDecl->getDeclName();
Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac,rbrac));
if (Method)
- Diag(Method->getLocation(), diag::note_method_sent_forward_class)
+ Diag(Method->getLocation(), diag::note_method_sent_forward_class)
<< Method->getDeclName();
}
if (!Method)
Method = ClassDecl->lookupClassMethod(Sel);
-
+
// If we have an implementation in scope, check "private" methods.
if (!Method)
Method = LookupPrivateClassMethod(Sel, ClassDecl);
if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
return true;
-
- if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, true,
+
+ if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, true,
lbrac, rbrac, returnType))
return true;
returnType = returnType.getNonReferenceType();
-
+
// 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.
@@ -483,19 +470,19 @@ Sema::ExprResult Sema::ActOnClassMessage(
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
- SourceLocation lbrac,
+ SourceLocation lbrac,
SourceLocation receiverLoc,
SourceLocation rbrac,
ExprTy **Args, unsigned NumArgs) {
assert(receiver && "missing receiver expression");
-
+
Expr **ArgExprs = reinterpret_cast<Expr **>(Args);
Expr *RExpr = static_cast<Expr *>(receiver);
-
+
// If necessary, apply function/array conversion to the receiver.
// C99 6.7.5.3p[7,8].
DefaultFunctionArrayConversion(RExpr);
-
+
QualType returnType;
QualType ReceiverCType =
Context.getCanonicalType(RExpr->getType()).getUnqualifiedType();
@@ -508,8 +495,8 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface())
if (ObjCInterfaceDecl *SuperDecl = ClassDecl->getSuperClass()) {
Method = SuperDecl->lookupInstanceMethod(Sel);
-
- if (!Method)
+
+ if (!Method)
// If we have implementations in scope, check "private" methods.
Method = LookupPrivateInstanceMethod(Sel, SuperDecl);
}
@@ -521,39 +508,42 @@ 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(RExpr, Sel, returnType, Method, lbrac,
rbrac, ArgExprs, NumArgs);
}
// Handle messages to id.
- if (ReceiverCType == Context.getCanonicalType(Context.getObjCIdType()) ||
- ReceiverCType->isBlockPointerType() ||
+ if (ReceiverCType->isObjCIdType() || ReceiverCType->isBlockPointerType() ||
Context.isObjCNSObjectType(RExpr->getType())) {
ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(
Sel, SourceRange(lbrac,rbrac));
if (!Method)
Method = LookupFactoryMethodInGlobalPool(Sel, SourceRange(lbrac, rbrac));
- if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
+ if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
lbrac, rbrac, returnType))
return true;
returnType = returnType.getNonReferenceType();
return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
rbrac, ArgExprs, NumArgs);
}
-
+
// Handle messages to Class.
- if (ReceiverCType == Context.getCanonicalType(Context.getObjCClassType())) {
+ if (ReceiverCType->isObjCClassType() ||
+ ReceiverCType->isObjCQualifiedClassType()) {
ObjCMethodDecl *Method = 0;
-
+
if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
// First check the public methods in the class interface.
Method = ClassDecl->lookupClassMethod(Sel);
-
+
if (!Method)
Method = LookupPrivateClassMethod(Sel, ClassDecl);
+
+ // FIXME: if we still haven't found a method, we need to look in
+ // protocols (if we have qualifiers).
}
if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
return true;
@@ -584,13 +574,13 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac,
rbrac, ArgExprs, NumArgs);
}
-
+
ObjCMethodDecl *Method = 0;
ObjCInterfaceDecl* ClassDecl = 0;
-
- // We allow sending a message to a qualified ID ("id<foo>"), which is ok as
+
+ // 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 =
+ if (const ObjCObjectPointerType *QIdTy =
ReceiverCType->getAsObjCQualifiedIdType()) {
// Search protocols for instance methods.
for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
@@ -602,19 +592,19 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
break;
}
- } else if (const ObjCInterfaceType *OCIType =
- ReceiverCType->getAsPointerToObjCInterfaceType()) {
+ } else if (const ObjCObjectPointerType *OCIType =
+ ReceiverCType->getAsObjCInterfacePointerType()) {
// We allow sending a message to a pointer to an interface (an object).
-
- ClassDecl = OCIType->getDecl();
+
+ 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 (ObjCQualifiedInterfaceType::qual_iterator QI = OCIType->qual_begin(),
+ for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(),
E = OCIType->qual_end(); QI != E; ++QI) {
if ((Method = (*QI)->lookupInstanceMethod(Sel)))
break;
@@ -623,7 +613,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
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
@@ -631,9 +621,9 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
if (OCIType->qual_empty()) {
Method = LookupInstanceMethodInGlobalPool(
Sel, SourceRange(lbrac,rbrac));
- if (Method && !OCIType->getDecl()->isForwardDecl())
- Diag(lbrac, diag::warn_maynot_respond)
- << OCIType->getDecl()->getIdentifier()->getName() << Sel;
+ if (Method && !OCIType->getInterfaceDecl()->isForwardDecl())
+ Diag(lbrac, diag::warn_maynot_respond)
+ << OCIType->getInterfaceDecl()->getIdentifier()->getName() << Sel;
}
}
}
@@ -641,7 +631,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
return true;
} else if (!Context.getObjCIdType().isNull() &&
(ReceiverCType->isPointerType() ||
- (ReceiverCType->isIntegerType() &&
+ (ReceiverCType->isIntegerType() &&
ReceiverCType->isScalarType()))) {
// Implicitly convert integers and pointers to 'id' but emit a warning.
Diag(lbrac, diag::warn_bad_receiver_type)
@@ -653,7 +643,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
<< RExpr->getType() << RExpr->getSourceRange();
return true;
}
-
+
if (Method)
DiagnoseSentinelCalls(Method, receiverLoc, ArgExprs, NumArgs);
if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
@@ -664,217 +654,3 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
rbrac, ArgExprs, NumArgs);
}
-//===----------------------------------------------------------------------===//
-// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's.
-//===----------------------------------------------------------------------===//
-
-/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the
-/// inheritance hierarchy of 'rProto'.
-static bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
- ObjCProtocolDecl *rProto) {
- if (lProto == rProto)
- return true;
- for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(),
- E = rProto->protocol_end(); PI != E; ++PI)
- if (ProtocolCompatibleWithProtocol(lProto, *PI))
- return true;
- return false;
-}
-
-/// ClassImplementsProtocol - Checks that 'lProto' protocol
-/// has been implemented in IDecl class, its super class or categories (if
-/// lookupCategory is true).
-static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
- ObjCInterfaceDecl *IDecl,
- bool lookupCategory,
- bool RHSIsQualifiedID = false) {
-
- // 1st, look up the class.
- const ObjCList<ObjCProtocolDecl> &Protocols =
- IDecl->getReferencedProtocols();
-
- for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(),
- E = Protocols.end(); PI != E; ++PI) {
- if (ProtocolCompatibleWithProtocol(lProto, *PI))
- return true;
- // This is dubious and is added to be compatible with gcc. In gcc, it is
- // also allowed assigning a protocol-qualified 'id' type to a LHS object
- // when protocol in qualified LHS is in list of protocols in the rhs 'id'
- // object. This IMO, should be a bug.
- // FIXME: Treat this as an extension, and flag this as an error when GCC
- // extensions are not enabled.
- if (RHSIsQualifiedID && ProtocolCompatibleWithProtocol(*PI, lProto))
- return true;
- }
-
- // 2nd, look up the category.
- if (lookupCategory)
- for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl;
- CDecl = CDecl->getNextClassCategory()) {
- for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(),
- E = CDecl->protocol_end(); PI != E; ++PI)
- if (ProtocolCompatibleWithProtocol(lProto, *PI))
- return true;
- }
-
- // 3rd, look up the super class(s)
- if (IDecl->getSuperClass())
- return
- ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory,
- RHSIsQualifiedID);
-
- return false;
-}
-
-/// QualifiedIdConformsQualifiedId - compare id<p,...> with id<p1,...>
-/// return true if lhs's protocols conform to rhs's protocol; false
-/// otherwise.
-bool Sema::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) {
- if (lhs->isObjCQualifiedIdType() && rhs->isObjCQualifiedIdType())
- return ObjCQualifiedIdTypesAreCompatible(lhs, rhs, false);
- return false;
-}
-
-/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an
-/// ObjCQualifiedIDType.
-/// FIXME: Move to ASTContext::typesAreCompatible() and friends.
-bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
- bool compare) {
- // Allow id<P..> and an 'id' or void* type in all cases.
- if (const PointerType *PT = lhs->getAsPointerType()) {
- QualType PointeeTy = PT->getPointeeType();
- if (PointeeTy->isVoidType() ||
- Context.isObjCIdStructType(PointeeTy) ||
- Context.isObjCClassStructType(PointeeTy))
- return true;
- } else if (const PointerType *PT = rhs->getAsPointerType()) {
- QualType PointeeTy = PT->getPointeeType();
- if (PointeeTy->isVoidType() ||
- Context.isObjCIdStructType(PointeeTy) ||
- Context.isObjCClassStructType(PointeeTy))
- return true;
- }
-
- if (const ObjCObjectPointerType *lhsQID = lhs->getAsObjCQualifiedIdType()) {
- const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType();
- const ObjCQualifiedInterfaceType *rhsQI = 0;
- QualType rtype;
-
- if (!rhsQID) {
- // Not comparing two ObjCQualifiedIdType's?
- if (!rhs->isPointerType()) return false;
-
- rtype = rhs->getAsPointerType()->getPointeeType();
- rhsQI = rtype->getAsObjCQualifiedInterfaceType();
- if (rhsQI == 0) {
- // If the RHS is a unqualified interface pointer "NSString*",
- // make sure we check the class hierarchy.
- if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) {
- ObjCInterfaceDecl *rhsID = IT->getDecl();
- for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
- E = lhsQID->qual_end(); I != E; ++I) {
- // when comparing an id<P> on lhs with a static type on rhs,
- // see if static class implements all of id's protocols, directly or
- // through its super class and categories.
- if (!ClassImplementsProtocol(*I, rhsID, true))
- return false;
- }
- return true;
- }
- }
- }
-
- ObjCObjectPointerType::qual_iterator RHSProtoI, RHSProtoE;
- if (rhsQI) { // We have a qualified interface (e.g. "NSObject<Proto> *").
- RHSProtoI = rhsQI->qual_begin();
- RHSProtoE = rhsQI->qual_end();
- } else if (rhsQID) { // We have a qualified id (e.g. "id<Proto> *").
- RHSProtoI = rhsQID->qual_begin();
- RHSProtoE = rhsQID->qual_end();
- } else {
- return false;
- }
-
- for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
- E = lhsQID->qual_end(); I != E; ++I) {
- ObjCProtocolDecl *lhsProto = *I;
- bool match = false;
-
- // when comparing an id<P> on lhs with a static type on rhs,
- // see if static class implements all of id's protocols, directly or
- // through its super class and categories.
- for (; RHSProtoI != RHSProtoE; ++RHSProtoI) {
- ObjCProtocolDecl *rhsProto = *RHSProtoI;
- if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
- (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) {
- match = true;
- break;
- }
- }
- if (rhsQI) {
- // If the RHS is a qualified interface pointer "NSString<P>*",
- // make sure we check the class hierarchy.
- if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) {
- ObjCInterfaceDecl *rhsID = IT->getDecl();
- for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
- E = lhsQID->qual_end(); I != E; ++I) {
- // when comparing an id<P> on lhs with a static type on rhs,
- // see if static class implements all of id's protocols, directly or
- // through its super class and categories.
- if (ClassImplementsProtocol(*I, rhsID, true)) {
- match = true;
- break;
- }
- }
- }
- }
- if (!match)
- return false;
- }
-
- return true;
- }
-
- const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType();
- assert(rhsQID && "One of the LHS/RHS should be id<x>");
-
- if (!lhs->isPointerType())
- return false;
-
- QualType ltype = lhs->getAsPointerType()->getPointeeType();
- if (const ObjCQualifiedInterfaceType *lhsQI =
- ltype->getAsObjCQualifiedInterfaceType()) {
- ObjCObjectPointerType::qual_iterator LHSProtoI = lhsQI->qual_begin();
- ObjCObjectPointerType::qual_iterator LHSProtoE = lhsQI->qual_end();
- for (; LHSProtoI != LHSProtoE; ++LHSProtoI) {
- bool match = false;
- ObjCProtocolDecl *lhsProto = *LHSProtoI;
- for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(),
- E = rhsQID->qual_end(); I != E; ++I) {
- ObjCProtocolDecl *rhsProto = *I;
- if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
- (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) {
- match = true;
- break;
- }
- }
- if (!match)
- return false;
- }
- return true;
- }
-
- if (const ObjCInterfaceType *IT = ltype->getAsObjCInterfaceType()) {
- // for static type vs. qualified 'id' type, check that class implements
- // all of 'id's protocols.
- ObjCInterfaceDecl *lhsID = IT->getDecl();
- for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(),
- E = rhsQID->qual_end(); I != E; ++I) {
- if (!ClassImplementsProtocol(*I, lhsID, compare, true))
- return false;
- }
- return true;
- }
- return false;
-}
-