aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2009-07-10 23:34:53 +0000
committerSteve Naroff <snaroff@apple.com>2009-07-10 23:34:53 +0000
commit14108da7f7fc059772711e4ffee1322a27b152a7 (patch)
tree5461a189505985c1c245c3f63a48030f0cd5e929 /lib/Sema
parent7ecbfbcddd278eede10bd38fa03a95a2110b191a (diff)
This patch includes a conceptually simple, but very intrusive/pervasive change.
The idea is to segregate Objective-C "object" pointers from general C pointers (utilizing the recently added ObjCObjectPointerType). The fun starts in Sema::GetTypeForDeclarator(), where "SomeInterface *" is now represented by a single AST node (rather than a PointerType whose Pointee is an ObjCInterfaceType). Since a significant amount of code assumed ObjC object pointers where based on C pointers/structs, this patch is very tedious. It should also explain why it is hard to accomplish this in smaller, self-contained patches. This patch does most of the "heavy lifting" related to moving from PointerType->ObjCObjectPointerType. It doesn't include all potential "cleanups". The good news is additional cleanups can be done later (some are noted in the code). This patch is so large that I didn't want to include any changes that are purely aesthetic. By making the ObjC types truly built-in, they are much easier to work with (and require fewer "hacks"). For example, there is no need for ASTContext::isObjCIdStructType() or ASTContext::isObjCClassStructType()! We believe this change (and the follow-up cleanups) will pay dividends over time. Given the amount of code change, I do expect some fallout from this change (though it does pass all of the clang tests). If you notice any problems, please let us know asap! Thanks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75314 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.cpp43
-rw-r--r--lib/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaDecl.cpp12
-rw-r--r--lib/Sema/SemaDeclAttr.cpp5
-rw-r--r--lib/Sema/SemaDeclObjC.cpp2
-rw-r--r--lib/Sema/SemaExpr.cpp441
-rw-r--r--lib/Sema/SemaExprCXX.cpp3
-rw-r--r--lib/Sema/SemaExprObjC.cpp186
-rw-r--r--lib/Sema/SemaOverload.cpp126
-rw-r--r--lib/Sema/SemaType.cpp20
10 files changed, 469 insertions, 371 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 6cbb1c3712..9b58e47746 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -53,9 +53,9 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
// Don't desugar magic Objective-C types.
Ty.getUnqualifiedType() != Context.getObjCIdType() &&
+ Ty.getUnqualifiedType() != Context.getObjCClassType() &&
Ty.getUnqualifiedType() != Context.getObjCSelType() &&
Ty.getUnqualifiedType() != Context.getObjCProtoType() &&
- Ty.getUnqualifiedType() != Context.getObjCClassType() &&
// Not va_list.
Ty.getUnqualifiedType() != Context.getBuiltinVaListType()) {
@@ -140,17 +140,6 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
Context.setObjCSelType(Context.getTypeDeclType(SelTypedef));
}
- if (Context.getObjCClassType().isNull()) {
- RecordDecl *ClassTag = CreateStructDecl(Context, "objc_class");
- QualType ClassT = Context.getPointerType(Context.getTagDeclType(ClassTag));
- TypedefDecl *ClassTypedef =
- TypedefDecl::Create(Context, CurContext, SourceLocation(),
- &Context.Idents.get("Class"), ClassT);
- PushOnScopeChains(ClassTag, TUScope);
- PushOnScopeChains(ClassTypedef, TUScope);
- Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
- }
-
// Synthesize "@class Protocol;
if (Context.getObjCProtoType().isNull()) {
ObjCInterfaceDecl *ProtocolDecl =
@@ -160,20 +149,38 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
PushOnScopeChains(ProtocolDecl, TUScope);
}
-
- // Synthesize "typedef struct objc_object { Class isa; } *id;"
+ // Create the built-in decls/typedefs for 'id' and 'Class'.
if (Context.getObjCIdType().isNull()) {
- RecordDecl *ObjectTag = CreateStructDecl(Context, "objc_object");
+ ObjCInterfaceDecl *IdIDecl =
+ ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
+ &Context.Idents.get("id"),
+ SourceLocation(), true);
+ QualType IdIType = Context.getObjCInterfaceType(IdIDecl);
+ QualType ObjCIdType = Context.getObjCObjectPointerType(IdIType);
- QualType ObjT = Context.getPointerType(Context.getTagDeclType(ObjectTag));
- PushOnScopeChains(ObjectTag, TUScope);
TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext,
SourceLocation(),
&Context.Idents.get("id"),
- ObjT);
+ ObjCIdType);
PushOnScopeChains(IdTypedef, TUScope);
Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
}
+ // Create the built-in decls/typedefs and type for "Class".
+ if (Context.getObjCClassType().isNull()) {
+ ObjCInterfaceDecl *ClassIDecl =
+ ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
+ &Context.Idents.get("Class"),
+ SourceLocation(), true);
+ QualType ClassIType = Context.getObjCInterfaceType(ClassIDecl);
+ QualType ObjCClassType = Context.getObjCObjectPointerType(ClassIType);
+
+ TypedefDecl *ClassTypedef = TypedefDecl::Create(Context, CurContext,
+ SourceLocation(),
+ &Context.Idents.get("Class"),
+ ObjCClassType);
+ PushOnScopeChains(ClassTypedef, TUScope);
+ Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
+ }
}
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 58fccc3e01..10ea5146a0 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3037,6 +3037,8 @@ public:
// Helper function for CheckAssignmentConstraints (C99 6.5.16.1p1)
AssignConvertType CheckPointerTypesForAssignment(QualType lhsType,
QualType rhsType);
+ AssignConvertType CheckPointeeTypesForAssignment(QualType lhsType,
+ QualType rhsType);
// Helper function for CheckAssignmentConstraints involving two
// block pointer types.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 1a8cec11b7..2c24dc976e 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -516,8 +516,6 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
if (New->isInvalidDecl() || OldD->isInvalidDecl())
return New->setInvalidDecl();
- bool objc_types = false;
-
// Allow multiple definitions for ObjC built-in typedefs.
// FIXME: Verify the underlying types are equivalent!
if (getLangOptions().ObjC1) {
@@ -527,13 +525,15 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
case 2:
if (!TypeID->isStr("id"))
break;
- Context.setObjCIdType(Context.getTypeDeclType(New));
- objc_types = true;
+ // Install the built-in type for 'id', ignoring the current definition.
+ New->setTypeForDecl(Context.getObjCIdType().getTypePtr());
+ return;
break;
case 5:
if (!TypeID->isStr("Class"))
break;
- Context.setObjCClassType(Context.getTypeDeclType(New));
+ // Install the built-in type for 'Class', ignoring the current definition.
+ New->setTypeForDecl(Context.getObjCClassType().getTypePtr());
return;
case 3:
if (!TypeID->isStr("SEL"))
@@ -578,7 +578,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
return New->setInvalidDecl();
}
- if (objc_types || getLangOptions().Microsoft)
+ if (getLangOptions().Microsoft)
return;
// C++ [dcl.typedef]p2:
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 2b71df7224..bdf6ca13a3 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -117,7 +117,7 @@ static bool isFunctionOrMethodVariadic(Decl *d) {
}
static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
- const PointerType *PT = T->getAsPointerType();
+ const ObjCObjectPointerType *PT = T->getAsObjCObjectPointerType();
if (!PT)
return false;
@@ -1690,7 +1690,8 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
return;
}
- if (!(S.Context.isObjCNSObjectType(RetTy) || RetTy->getAsPointerType())) {
+ if (!(S.Context.isObjCNSObjectType(RetTy) || RetTy->getAsPointerType()
+ || RetTy->getAsObjCObjectPointerType())) {
S.Diag(Attr.getLoc(), diag::warn_ns_attribute_wrong_return_type)
<< Attr.getName();
return;
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 62d28f326f..b8a9834b50 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -2048,7 +2048,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
<< property->getDeclName() << Ivar->getDeclName();
// Fall thru - see previous comment
}
- if ((Context.isObjCObjectPointerType(property->getType()) ||
+ if ((property->getType()->isObjCObjectPointerType() ||
PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
getLangOptions().getGCMode() != LangOptions::NonGC) {
Diag(PropertyLoc, diag::error_strong_property)
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 820c1775ae..8611fd5461 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -925,8 +925,8 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
QualType T;
if (getCurMethodDecl()->isInstanceMethod())
- T = Context.getPointerType(Context.getObjCInterfaceType(
- getCurMethodDecl()->getClassInterface()));
+ T = Context.getObjCObjectPointerType(Context.getObjCInterfaceType(
+ getCurMethodDecl()->getClassInterface()));
else
T = Context.getObjCClassType();
return Owned(new (Context) ObjCSuperExpr(Loc, T));
@@ -1844,6 +1844,17 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,
BaseExpr = RHSExp;
IndexExpr = LHSExp;
ResultType = PTy->getPointeeType();
+ } else if (const ObjCObjectPointerType *PTy =
+ LHSTy->getAsObjCObjectPointerType()) {
+ BaseExpr = LHSExp;
+ IndexExpr = RHSExp;
+ ResultType = PTy->getPointeeType();
+ } else if (const ObjCObjectPointerType *PTy =
+ RHSTy->getAsObjCObjectPointerType()) {
+ // Handle the uncommon case of "123[Ptr]".
+ BaseExpr = RHSExp;
+ IndexExpr = LHSExp;
+ ResultType = PTy->getPointeeType();
} else if (const VectorType *VTy = LHSTy->getAsVectorType()) {
BaseExpr = LHSExp; // vectors: V[123]
IndexExpr = RHSExp;
@@ -2089,6 +2100,8 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
MemberLoc));
else if (const PointerType *PT = BaseType->getAsPointerType())
BaseType = PT->getPointeeType();
+ else if (BaseType->isObjCObjectPointerType())
+ ;
else if (getLangOptions().CPlusPlus && BaseType->isRecordType())
return Owned(BuildOverloadedArrowExpr(S, BaseExpr, OpLoc,
MemberLoc, Member));
@@ -2212,12 +2225,71 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
<< DeclarationName(&Member) << int(OpKind == tok::arrow));
}
+ // Handle properties on ObjC 'Class' types.
+ if (OpKind == tok::period && (BaseType->isObjCClassType())) {
+ // Also must look for a getter name which uses property syntax.
+ Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
+ if (ObjCMethodDecl *MD = getCurMethodDecl()) {
+ ObjCInterfaceDecl *IFace = MD->getClassInterface();
+ ObjCMethodDecl *Getter;
+ // FIXME: need to also look locally in the implementation.
+ if ((Getter = IFace->lookupClassMethod(Sel))) {
+ // Check the use of this method.
+ if (DiagnoseUseOfDecl(Getter, MemberLoc))
+ return ExprError();
+ }
+ // If we found a getter then this may be a valid dot-reference, we
+ // will look for the matching setter, in case it is needed.
+ Selector SetterSel =
+ SelectorTable::constructSetterName(PP.getIdentifierTable(),
+ PP.getSelectorTable(), &Member);
+ ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
+ if (!Setter) {
+ // If this reference is in an @implementation, also check for 'private'
+ // methods.
+ Setter = FindMethodInNestedImplementations(IFace, 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 && DiagnoseUseOfDecl(Setter, MemberLoc))
+ return ExprError();
+
+ if (Getter || Setter) {
+ QualType PType;
+
+ if (Getter)
+ PType = Getter->getResultType();
+ else {
+ for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(),
+ E = Setter->param_end(); PI != E; ++PI)
+ PType = (*PI)->getType();
+ }
+ // FIXME: we must check that the setter has property type.
+ return Owned(new (Context) ObjCKVCRefExpr(Getter, PType,
+ Setter, MemberLoc, BaseExpr));
+ }
+ return ExprError(Diag(MemberLoc, diag::err_property_not_found)
+ << &Member << BaseType);
+ }
+ }
// Handle access to Objective-C instance variables, such as "Obj->ivar" and
// (*Obj).ivar.
- if (const ObjCInterfaceType *IFTy = BaseType->getAsObjCInterfaceType()) {
+ if ((OpKind == tok::arrow && BaseType->isObjCObjectPointerType()) ||
+ (OpKind == tok::period && BaseType->isObjCInterfaceType())) {
+ const ObjCObjectPointerType *OPT = BaseType->getAsObjCObjectPointerType();
+ const ObjCInterfaceType *IFaceT =
+ OPT ? OPT->getInterfaceType() : BaseType->getAsObjCInterfaceType();
+ ObjCInterfaceDecl *IDecl = IFaceT->getDecl();
ObjCInterfaceDecl *ClassDeclared;
- if (ObjCIvarDecl *IV = IFTy->getDecl()->lookupInstanceVariable(&Member,
- ClassDeclared)) {
+
+ if (ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(&Member,
+ ClassDeclared)) {
// If the decl being referenced had an error, return an error for this
// sub-expr without emitting another error, in order to avoid cascading
// error cases.
@@ -2249,12 +2321,12 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
}
if (IV->getAccessControl() == ObjCIvarDecl::Private) {
- if (ClassDeclared != IFTy->getDecl() ||
+ if (ClassDeclared != IDecl ||
ClassOfMethodDecl != ClassDeclared)
Diag(MemberLoc, diag::error_private_ivar_access) << IV->getDeclName();
}
// @protected
- else if (!IFTy->getDecl()->isSuperClassOf(ClassOfMethodDecl))
+ else if (!IDecl->isSuperClassOf(ClassOfMethodDecl))
Diag(MemberLoc, diag::error_protected_ivar_access) << IV->getDeclName();
}
@@ -2263,18 +2335,46 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
OpKind == tok::arrow));
}
return ExprError(Diag(MemberLoc, diag::err_typecheck_member_reference_ivar)
- << IFTy->getDecl()->getDeclName() << &Member
+ << IDecl->getDeclName() << &Member
<< BaseExpr->getSourceRange());
}
+ // Handle properties on qualified "id" protocols.
+ const ObjCObjectPointerType *QIdTy;
+ if (OpKind == tok::period && (QIdTy = BaseType->getAsObjCQualifiedIdType())) {
+ // Check protocols on qualified interfaces.
+ Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
+ if (Decl *PMDecl = FindGetterNameDecl(QIdTy, Member, Sel, Context)) {
+ if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) {
+ // Check the use of this declaration
+ if (DiagnoseUseOfDecl(PD, MemberLoc))
+ return ExprError();
+
+ return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
+ MemberLoc, BaseExpr));
+ }
+ if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {
+ // Check the use of this method.
+ if (DiagnoseUseOfDecl(OMD, MemberLoc))
+ return ExprError();
+
+ return Owned(new (Context) ObjCMessageExpr(BaseExpr, Sel,
+ OMD->getResultType(),
+ OMD, OpLoc, MemberLoc,
+ NULL, 0));
+ }
+ }
+ return ExprError(Diag(MemberLoc, diag::err_property_not_found)
+ << &Member << BaseType);
+ }
// Handle Objective-C property access, which is "Obj.property" where Obj is a
// pointer to a (potentially qualified) interface type.
- const PointerType *PTy;
- const ObjCInterfaceType *IFTy;
- if (OpKind == tok::period && (PTy = BaseType->getAsPointerType()) &&
- (IFTy = PTy->getPointeeType()->getAsObjCInterfaceType())) {
- ObjCInterfaceDecl *IFace = IFTy->getDecl();
-
+ const ObjCObjectPointerType *OPT;
+ if (OpKind == tok::period &&
+ (OPT = BaseType->getAsObjCInterfacePointerType())) {
+ const ObjCInterfaceType *IFaceT = OPT->getInterfaceType();
+ ObjCInterfaceDecl *IFace = IFaceT->getDecl();
+
// Search for a declared property first.
if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(&Member)) {
// Check whether we can reference this property.
@@ -2288,10 +2388,9 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
MemberLoc, BaseExpr));
}
-
// Check protocols on qualified interfaces.
- for (ObjCInterfaceType::qual_iterator I = IFTy->qual_begin(),
- E = IFTy->qual_end(); I != E; ++I)
+ for (ObjCObjectPointerType::qual_iterator I = IFaceT->qual_begin(),
+ E = IFaceT->qual_end(); I != E; ++I)
if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member)) {
// Check whether we can reference this property.
if (DiagnoseUseOfDecl(PD, MemberLoc))
@@ -2300,7 +2399,16 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
MemberLoc, BaseExpr));
}
+ for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
+ E = OPT->qual_end(); I != E; ++I)
+ if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member)) {
+ // Check whether we can reference this property.
+ if (DiagnoseUseOfDecl(PD, MemberLoc))
+ return ExprError();
+ return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
+ MemberLoc, BaseExpr));
+ }
// If that failed, look for an "implicit" property by seeing if the nullary
// selector is implemented.
@@ -2365,88 +2473,6 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
return ExprError(Diag(MemberLoc, diag::err_property_not_found)
<< &Member << BaseType);
}
- // Handle properties on qualified "id" protocols.
- const ObjCObjectPointerType *QIdTy;
- if (OpKind == tok::period && (QIdTy = BaseType->getAsObjCQualifiedIdType())) {
- // Check protocols on qualified interfaces.
- Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
- if (Decl *PMDecl = FindGetterNameDecl(QIdTy, Member, Sel, Context)) {
- if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) {
- // Check the use of this declaration
- if (DiagnoseUseOfDecl(PD, MemberLoc))
- return ExprError();
-
- return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
- MemberLoc, BaseExpr));
- }
- if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) {
- // Check the use of this method.
- if (DiagnoseUseOfDecl(OMD, MemberLoc))
- return ExprError();
-
- return Owned(new (Context) ObjCMessageExpr(BaseExpr, Sel,
- OMD->getResultType(),
- OMD, OpLoc, MemberLoc,
- NULL, 0));
- }
- }
-
- return ExprError(Diag(MemberLoc, diag::err_property_not_found)
- << &Member << BaseType);
- }
- // Handle properties on ObjC 'Class' types.
- if (OpKind == tok::period && (BaseType == Context.getObjCClassType())) {
- // Also must look for a getter name which uses property syntax.
- Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
- if (ObjCMethodDecl *MD = getCurMethodDecl()) {
- ObjCInterfaceDecl *IFace = MD->getClassInterface();
- ObjCMethodDecl *Getter;
- // FIXME: need to also look locally in the implementation.
- if ((Getter = IFace->lookupClassMethod(Sel))) {
- // Check the use of this method.
- if (DiagnoseUseOfDecl(Getter, MemberLoc))
- return ExprError();
- }
- // If we found a getter then this may be a valid dot-reference, we
- // will look for the matching setter, in case it is needed.
- Selector SetterSel =
- SelectorTable::constructSetterName(PP.getIdentifierTable(),
- PP.getSelectorTable(), &Member);
- ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel);
- if (!Setter) {
- // If this reference is in an @implementation, also check for 'private'
- // methods.
- Setter = FindMethodInNestedImplementations(IFace, 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 && DiagnoseUseOfDecl(Setter, MemberLoc))
- return ExprError();
-
- if (Getter || Setter) {
- QualType PType;
-
- if (Getter)
- PType = Getter->getResultType();
- else {
- for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(),
- E = Setter->param_end(); PI != E; ++PI)
- PType = (*PI)->getType();
- }
- // FIXME: we must check that the setter has property type.
- return Owned(new (Context) ObjCKVCRefExpr(Getter, PType,
- Setter, MemberLoc, BaseExpr));
- }
- return ExprError(Diag(MemberLoc, diag::err_property_not_found)
- << &Member << BaseType);
- }
- }
// Handle 'field access' to vectors, such as 'V.xx'.
if (BaseType->isExtVectorType()) {
@@ -3069,13 +3095,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// C99 6.5.15p6 - "if one operand is a null pointer constant, the result has
// the type of the other operand."
if ((LHSTy->isPointerType() || LHSTy->isBlockPointerType() ||
- Context.isObjCObjectPointerType(LHSTy)) &&
+ LHSTy->isObjCObjectPointerType()) &&
RHS->isNullPointerConstant(Context)) {
ImpCastExprToType(RHS, LHSTy); // promote the null to a pointer.
return LHSTy;
}
if ((RHSTy->isPointerType() || RHSTy->isBlockPointerType() ||
- Context.isObjCObjectPointerType(RHSTy)) &&
+ RHSTy->isObjCObjectPointerType()) &&
LHS->isNullPointerConstant(Context)) {
ImpCastExprToType(LHS, RHSTy); // promote the null to a pointer.
return RHSTy;
@@ -3119,46 +3145,15 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
ImpCastExprToType(RHS, LHSTy);
return LHSTy;
}
- // Need to handle "id<xx>" explicitly. Unlike "id", whose canonical type
- // evaluates to "struct objc_object *" (and is handled above when comparing
- // id with statically typed objects).
- if (LHSTy->isObjCQualifiedIdType() || RHSTy->isObjCQualifiedIdType()) {
- // GCC allows qualified id and any Objective-C type to devolve to
- // id. Currently localizing to here until clear this should be
- // part of ObjCQualifiedIdTypesAreCompatible.
- if (ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true) ||
- (LHSTy->isObjCQualifiedIdType() &&
- Context.isObjCObjectPointerType(RHSTy)) ||
- (RHSTy->isObjCQualifiedIdType() &&
- Context.isObjCObjectPointerType(LHSTy))) {
- // FIXME: This is not the correct composite type. This only happens to
- // work because id can more or less be used anywhere, however this may
- // change the type of method sends.
-
- // FIXME: gcc adds some type-checking of the arguments and emits
- // (confusing) incompatible comparison warnings in some
- // cases. Investigate.
- QualType compositeType = Context.getObjCIdType();
- ImpCastExprToType(LHS, compositeType);
- ImpCastExprToType(RHS, compositeType);
- return compositeType;
- }
- }
// Check constraints for Objective-C object pointers types.
- if (Context.isObjCObjectPointerType(LHSTy) &&
- Context.isObjCObjectPointerType(RHSTy)) {
+ if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) {
if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
// Two identical object pointer types are always compatible.
return LHSTy;
}
- // No need to check for block pointer types or qualified id types (they
- // were handled above).
- assert((LHSTy->isPointerType() && RHSTy->isPointerType()) &&
- "Sema::CheckConditionalOperands(): Unexpected type");
- QualType lhptee = LHSTy->getAsPointerType()->getPointeeType();
- QualType rhptee = RHSTy->getAsPointerType()->getPointeeType();
-
+ const ObjCObjectPointerType *LHSOPT = LHSTy->getAsObjCObjectPointerType();
+ const ObjCObjectPointerType *RHSOPT = RHSTy->getAsObjCObjectPointerType();
QualType compositeType = LHSTy;
// If both operands are interfaces and either operand can be
@@ -3174,16 +3169,19 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// FIXME: Consider unifying with 'areComparableObjCPointerTypes'.
// It could return the composite type.
- const ObjCInterfaceType* LHSIface = lhptee->getAsObjCInterfaceType();
- const ObjCInterfaceType* RHSIface = rhptee->getAsObjCInterfaceType();
- if (LHSIface && RHSIface &&
- Context.canAssignObjCInterfaces(LHSIface, RHSIface)) {
+ if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) {
compositeType = LHSTy;
- } else if (LHSIface && RHSIface &&
- Context.canAssignObjCInterfaces(RHSIface, LHSIface)) {
+ } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) {
compositeType = RHSTy;
- } else if (Context.isObjCIdStructType(lhptee) ||
- Context.isObjCIdStructType(rhptee)) {
+ } else if ((LHSTy->isObjCQualifiedIdType() ||
+ RHSTy->isObjCQualifiedIdType()) &&
+ ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) {
+ // Need to handle "id<xx>" explicitly.
+ // GCC allows qualified id and any Objective-C type to devolve to
+ // id. Currently localizing to here until clear this should be
+ // part of ObjCQualifiedIdTypesAreCompatible.
+ compositeType = Context.getObjCIdType();
+ } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) {
compositeType = Context.getObjCIdType();
} else {
Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)
@@ -3312,6 +3310,11 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
lhptee = lhsType->getAsPointerType()->getPointeeType();
rhptee = rhsType->getAsPointerType()->getPointeeType();
+ return CheckPointeeTypesForAssignment(lhptee, rhptee);
+}
+
+Sema::AssignConvertType
+Sema::CheckPointeeTypesForAssignment(QualType lhptee, QualType rhptee) {
// make sure we operate on the canonical type
lhptee = Context.getCanonicalType(lhptee);
rhptee = Context.getCanonicalType(rhptee);
@@ -3443,7 +3446,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
return Compatible;
return Incompatible;
}
-
+ // FIXME: Look into removing. With ObjCObjectPointerType, I don't see a need.
if (lhsType->isObjCQualifiedIdType() || rhsType->isObjCQualifiedIdType()) {
if (ObjCQualifiedIdTypesAreCompatible(lhsType, rhsType, false))
return Compatible;
@@ -3454,7 +3457,6 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
return PointerToInt;
return IncompatibleObjCQualifiedId;
}
-
// Allow scalar to ExtVector assignments, and assignments of an ExtVector type
// to the same ExtVector type.
if (lhsType->isExtVectorType()) {
@@ -3486,13 +3488,18 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
if (isa<PointerType>(rhsType))
return CheckPointerTypesForAssignment(lhsType, rhsType);
+ if (isa<ObjCObjectPointerType>(rhsType)) {
+ QualType rhptee = rhsType->getAsObjCObjectPointerType()->getPointeeType();
+ QualType lhptee = lhsType->getAsPointerType()->getPointeeType();
+ return CheckPointeeTypesForAssignment(lhptee, rhptee);
+ }
+
if (rhsType->getAsBlockPointerType()) {
if (lhsType->getAsPointerType()->getPointeeType()->isVoidType())
return Compatible;
// Treat block pointers as objects.
- if (getLangOptions().ObjC1 &&
- lhsType == Context.getCanonicalType(Context.getObjCIdType()))
+ if (getLangOptions().ObjC1 && lhsType->isObjCIdType())
return Compatible;
}
return Incompatible;
@@ -3503,8 +3510,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
return IntToBlockPointer;
// Treat block pointers as objects.
- if (getLangOptions().ObjC1 &&
- rhsType == Context.getCanonicalType(Context.getObjCIdType()))
+ if (getLangOptions().ObjC1 && rhsType->isObjCIdType())
return Compatible;
if (rhsType->isBlockPointerType())
@@ -3517,6 +3523,29 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
return Incompatible;
}
+ if (isa<ObjCObjectPointerType>(lhsType)) {
+ if (rhsType->isIntegerType())
+ return IntToPointer;
+
+ if (isa<PointerType>(rhsType)) {
+ QualType lhptee = lhsType->getAsObjCObjectPointerType()->getPointeeType();
+ QualType rhptee = rhsType->getAsPointerType()->getPointeeType();
+ return CheckPointeeTypesForAssignment(lhptee, rhptee);
+ }
+ if (rhsType->isObjCObjectPointerType()) {
+ QualType lhptee = lhsType->getAsObjCObjectPointerType()->getPointeeType();
+ QualType rhptee = rhsType->getAsObjCObjectPointerType()->getPointeeType();
+ return CheckPointeeTypesForAssignment(lhptee, rhptee);
+ }
+ if (const PointerType *RHSPT = rhsType->getAsPointerType()) {
+ if (RHSPT->getPointeeType()->isVoidType())
+ return Compatible;
+ }
+ // Treat block pointers as objects.
+ if (rhsType->isBlockPointerType())
+ return Compatible;
+ return Incompatible;
+ }
if (isa<PointerType>(rhsType)) {
// C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
if (lhsType == Context.BoolTy)
@@ -3533,6 +3562,24 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
return Compatible;
return Incompatible;
}
+ if (isa<ObjCObjectPointerType>(rhsType)) {
+ // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
+ if (lhsType == Context.BoolTy)
+ return Compatible;
+
+ if (lhsType->isIntegerType())
+ return PointerToInt;
+
+ if (isa<PointerType>(lhsType)) {
+ QualType rhptee = lhsType->getAsObjCObjectPointerType()->getPointeeType();
+ QualType lhptee = rhsType->getAsPointerType()->getPointeeType();
+ return CheckPointeeTypesForAssignment(lhptee, rhptee);
+ }
+ if (isa<BlockPointerType>(lhsType) &&
+ rhsType->getAsPointerType()->getPointeeType()->isVoidType())
+ return Compatible;
+ return Incompatible;
+ }
if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
if (Context.typesAreCompatible(lhsType, rhsType))
@@ -3628,7 +3675,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
// C99 6.5.16.1p1: the left operand is a pointer and the right is
// a null pointer constant.
if ((lhsType->isPointerType() ||
- lhsType->isObjCQualifiedIdType() ||
+ lhsType->isObjCObjectPointerType() ||
lhsType->isBlockPointerType())
&& rExpr->isNullPointerConstant(Context)) {
ImpCastExprToType(rExpr, lhsType);
@@ -3776,12 +3823,23 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
// Put any potential pointer into PExp
Expr* PExp = lex, *IExp = rex;
- if (IExp->getType()->isPointerType())
+ if (IExp->getType()->isPointerType() ||
+ IExp->getType()->isObjCObjectPointerType())
std::swap(PExp, IExp);
- if (const PointerType *PTy = PExp->getType()->getAsPointerType()) {
+ if (PExp->getType()->isPointerType() ||
+ PExp->getType()->isObjCObjectPointerType()) {
+
if (IExp->getType()->isIntegerType()) {
- QualType PointeeTy = PTy->getPointeeType();
+ QualType PointeeTy;
+ const PointerType *PTy;
+ const ObjCObjectPointerType *OPT;
+
+ if ((PTy = PExp->getType()->getAsPointerType()))
+ PointeeTy = PTy->getPointeeType();
+ else if ((OPT = PExp->getType()->getAsObjCObjectPointerType()))
+ PointeeTy = OPT->getPointeeType();
+
// Check for arithmetic on pointers to incomplete types.
if (PointeeTy->isVoidType()) {
if (getLangOptions().CPlusPlus) {
@@ -3803,7 +3861,7 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
// GNU extension: arithmetic on pointer to function
Diag(Loc, diag::ext_gnu_ptr_func_arith)
<< lex->getType() << lex->getSourceRange();
- } else if (!PTy->isDependentType() &&
+ } else if (((PTy && !PTy->isDependentType()) || OPT) &&
RequireCompleteType(Loc, PointeeTy,
diag::err_typecheck_arithmetic_incomplete_type,
PExp->getSourceRange(), SourceRange(),
@@ -3855,10 +3913,16 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
-
+
// Either ptr - int or ptr - ptr.
- if (const PointerType *LHSPTy = lex->getType()->getAsPointerType()) {
- QualType lpointee = LHSPTy->getPointeeType();
+ if (lex->getType()->isPointerType() ||
+ lex->getType()->isObjCObjectPointerType()) {
+ QualType lpointee;
+ if (const PointerType *LHSPTy = lex->getType()->getAsPointerType())
+ lpointee = LHSPTy->getPointeeType();
+ else if (const ObjCObjectPointerType *OPT =
+ lex->getType()->getAsObjCObjectPointerType())
+ lpointee = OPT->getPointeeType();
// The LHS must be an completely-defined object type.
@@ -4156,8 +4220,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (!LHSIsNull && !RHSIsNull && // C99 6.5.9p2
!LCanPointeeTy->isVoidType() && !RCanPointeeTy->isVoidType() &&
!Context.typesAreCompatible(LCanPointeeTy.ge