aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2009-09-22 16:48:37 +0000
committerFariborz Jahanian <fjahanian@apple.com>2009-09-22 16:48:37 +0000
commitb2ef1beb812988ce45804d655c9a72bc523d5014 (patch)
treea08c4d6ff3b8b15ebf46de5852de13e437c61608
parent9c6a0e92dbf89897eae6106b24bfd017f269bfd0 (diff)
Fix a regression in accessing class getter using the dot-syntax
notation. There is still an issue accessing field of a 'Class''s isa in legacy code using dot field access notation (as noted in the test case) but unrelated to this patch. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82555 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaExpr.cpp112
-rw-r--r--test/SemaObjC/class-getter-using-dotsyntax.m39
2 files changed, 96 insertions, 55 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 3eed4fcde3..9695814860 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2029,13 +2029,65 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
BaseType = Context.ObjCIdRedefinitionType;
ImpCastExprToType(BaseExpr, BaseType);
}
- } else if (BaseType->isObjCClassType() &&
- BaseType != Context.ObjCClassRedefinitionType) {
- BaseType = Context.ObjCClassRedefinitionType;
- ImpCastExprToType(BaseExpr, BaseType);
}
assert(!BaseType.isNull() && "no type for member expression");
+ // Handle properties on ObjC 'Class' types.
+ if (OpKind == tok::period && BaseType->isObjCClassType()) {
+ // Also must look for a getter name which uses property syntax.
+ IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
+ 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)
+ Setter = IFace->getCategoryClassMethod(SetterSel);
+
+ if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
+ return ExprError();
+
+ if (Getter || Setter) {
+ QualType PType;
+
+ if (Getter)
+ PType = Getter->getResultType();
+ else
+ // Get the expression type from Setter's incoming parameter.
+ PType = (*(Setter->param_end() -1))->getType();
+ // FIXME: we must check that the setter has property type.
+ return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter,
+ PType,
+ Setter, MemberLoc, BaseExpr));
+ }
+ return ExprError(Diag(MemberLoc, diag::err_property_not_found)
+ << MemberName << BaseType);
+ }
+ }
+
+ if (BaseType->isObjCClassType() &&
+ BaseType != Context.ObjCClassRedefinitionType) {
+ BaseType = Context.ObjCClassRedefinitionType;
+ ImpCastExprToType(BaseExpr, BaseType);
+ }
+
// Get the type being accessed in BaseType. If this is an arrow, the BaseExpr
// must have pointer type, and the accessed type is the pointee.
if (OpKind == tok::arrow) {
@@ -2067,8 +2119,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
return ExprError(Diag(MemberLoc,
diag::err_typecheck_member_reference_arrow)
<< BaseType << BaseExpr->getSourceRange());
- } else {
- if (BaseType->isDependentType()) {
+ } else if (BaseType->isDependentType()) {
// Require that the base type isn't a pointer type
// (so we'll report an error for)
// T* t;
@@ -2103,7 +2154,6 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
RAngleLoc));
}
}
- }
// Handle field access to simple records. This also handles access to fields
// of the ObjC 'id' struct.
@@ -2303,54 +2353,6 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
MemberLoc));
}
- // Handle properties on ObjC 'Class' types.
- if (OpKind == tok::period && BaseType->isObjCClassType()) {
- // Also must look for a getter name which uses property syntax.
- IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
- 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)
- Setter = IFace->getCategoryClassMethod(SetterSel);
-
- if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc))
- return ExprError();
-
- if (Getter || Setter) {
- QualType PType;
-
- if (Getter)
- PType = Getter->getResultType();
- else
- // Get the expression type from Setter's incoming parameter.
- PType = (*(Setter->param_end() -1))->getType();
- // FIXME: we must check that the setter has property type.
- return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType,
- Setter, MemberLoc, BaseExpr));
- }
- return ExprError(Diag(MemberLoc, diag::err_property_not_found)
- << MemberName << BaseType);
- }
- }
// Handle access to Objective-C instance variables, such as "Obj->ivar" and
// (*Obj).ivar.
if ((OpKind == tok::arrow && BaseType->isObjCObjectPointerType()) ||
diff --git a/test/SemaObjC/class-getter-using-dotsyntax.m b/test/SemaObjC/class-getter-using-dotsyntax.m
new file mode 100644
index 0000000000..ba42590c34
--- /dev/null
+++ b/test/SemaObjC/class-getter-using-dotsyntax.m
@@ -0,0 +1,39 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+typedef struct objc_class *Class;
+
+struct objc_class {
+ Class isa;
+};
+
+typedef struct objc_object {
+ Class isa;
+} *id;
+
+@interface XCActivityLogSection
++ (unsigned)serializationFormatVersion;
++ (unsigned)sectionByDeserializingData;
++ (Class)retursClass;
+@end
+
+@implementation XCActivityLogSection
+
++ (unsigned)serializationFormatVersion
+{
+
+ return 0;
+}
++ (unsigned)sectionByDeserializingData {
+ unsigned version;
+ return self.serializationFormatVersion;
+}
+
++ (Class)retursClass {
+ Class version;
+ // FIXIT. (*version).isa does not work. Results in compiler error.
+ return version->isa;
+}
+
+@end
+
+