aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2009-04-07 18:28:06 +0000
committerFariborz Jahanian <fjahanian@apple.com>2009-04-07 18:28:06 +0000
commitef79bc9b079d838ba2cc91b37760d297025eb3e6 (patch)
tree16b67d03cb302f7fcb27e7d2dc804123fd179cb5
parentef88e58360db75cc61cf4468cb0464cc5230210e (diff)
Fixes method name lookup when method appears in
the base implementations (and not in current implementation). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68527 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaExpr.cpp28
-rw-r--r--test/SemaObjC/property-method-lookup-impl.m26
3 files changed, 48 insertions, 9 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index c71d8d726f..5582ac9f86 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -950,6 +950,9 @@ private:
std::pair<bool, LookupResult> CppLookupName(Scope *S, DeclarationName Name,
LookupNameKind NameKind,
bool RedeclarationOnly);
+ ObjCMethodDecl *FindMethodInNestedImplementations(
+ const ObjCInterfaceDecl *IFace,
+ const Selector &Sel);
public:
/// Determines whether D is a suitable lookup result according to the
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index f348f86498..d442b1fc58 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1739,6 +1739,22 @@ static Decl *FindGetterNameDecl(const ObjCQualifiedIdType *QIdTy,
return GDecl;
}
+/// FindMethodInNestedImplementations - Look up a method in current and
+/// all base class implementations.
+///
+ObjCMethodDecl *Sema::FindMethodInNestedImplementations(
+ const ObjCInterfaceDecl *IFace,
+ const Selector &Sel) {
+ ObjCMethodDecl *Method = 0;
+ if (ObjCImplementationDecl *ImpDecl =
+ Sema::ObjCImplementations[IFace->getIdentifier()])
+ Method = ImpDecl->getInstanceMethod(Sel);
+
+ if (!Method && IFace->getSuperClass())
+ return FindMethodInNestedImplementations(IFace->getSuperClass(), Sel);
+ return Method;
+}
+
Action::OwningExprResult
Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
tok::TokenKind OpKind, SourceLocation MemberLoc,
@@ -1953,9 +1969,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
// If this reference is in an @implementation, check for 'private' methods.
if (!Getter)
- if (ObjCImplementationDecl *ImpDecl =
- ObjCImplementations[IFace->getIdentifier()])
- Getter = ImpDecl->getInstanceMethod(Sel);
+ Getter = FindMethodInNestedImplementations(IFace, Sel);
// Look through local category implementations associated with the class.
if (!Getter) {
@@ -1978,9 +1992,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
if (!Setter) {
// If this reference is in an @implementation, also check for 'private'
// methods.
- if (ObjCImplementationDecl *ImpDecl =
- ObjCImplementations[IFace->getIdentifier()])
- Setter = ImpDecl->getInstanceMethod(SetterSel);
+ Setter = FindMethodInNestedImplementations(IFace, SetterSel);
}
// Look through local category implementations associated with the class.
if (!Setter) {
@@ -2061,9 +2073,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
if (!Setter) {
// If this reference is in an @implementation, also check for 'private'
// methods.
- if (ObjCImplementationDecl *ImpDecl =
- ObjCImplementations[IFace->getIdentifier()])
- Setter = ImpDecl->getInstanceMethod(SetterSel);
+ Setter = FindMethodInNestedImplementations(IFace, SetterSel);
}
// Look through local category implementations associated with the class.
if (!Setter) {
diff --git a/test/SemaObjC/property-method-lookup-impl.m b/test/SemaObjC/property-method-lookup-impl.m
new file mode 100644
index 0000000000..ed7e9bcd43
--- /dev/null
+++ b/test/SemaObjC/property-method-lookup-impl.m
@@ -0,0 +1,26 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+@interface SSyncCEList
+{
+ id _list;
+}
+@end
+
+@implementation SSyncCEList
+
+- (id) list
+{
+}
+@end
+
+@interface SSyncConflictList : SSyncCEList
+@end
+
+@implementation SSyncConflictList
+
+- (id)Meth : (SSyncConflictList*)other
+ {
+ return other.list;
+ }
+@end
+