aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2007-11-11 00:10:47 +0000
committerSteve Naroff <snaroff@apple.com>2007-11-11 00:10:47 +0000
commitc43d868355374d48296ad3be2c9c536698a5e9a8 (patch)
tree322ea556f01dad6c123fc37d6c7698bf71d30ae0
parent8f2c735c0cee8da42742ae247778cbfef45b8750 (diff)
Teach Sema::ActOnInstanceMessage() about private methods. That is, methods declared in an implementation (but not listed in the interface).
This commit is only 95% of the bug fix. The last piece to this puzzle is to add the method decls to the implementation incrementally (as we encounter them). At the moment, the methods aren't added until we see an @end (which is too late). I will complete this later... git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43989 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--AST/Decl.cpp27
-rw-r--r--Sema/Sema.h2
-rw-r--r--Sema/SemaDecl.cpp5
-rw-r--r--Sema/SemaExpr.cpp6
-rw-r--r--include/clang/AST/DeclObjC.h3
-rw-r--r--test/Sema/message.m11
6 files changed, 51 insertions, 3 deletions
diff --git a/AST/Decl.cpp b/AST/Decl.cpp
index 3cfe4aeed9..2e79de3f63 100644
--- a/AST/Decl.cpp
+++ b/AST/Decl.cpp
@@ -510,4 +510,31 @@ ObjcMethodDecl *ObjcInterfaceDecl::lookupClassMethod(Selector &Sel) {
return NULL;
}
+// lookupInstanceMethod - This method returns an instance method by looking in
+// the class implementation. Unlike interfaces, we don't look outside the
+// implementation.
+ObjcMethodDecl *ObjcImplementationDecl::lookupInstanceMethod(Selector &Sel) {
+ ObjcMethodDecl **methods = getInstanceMethods();
+ int methodCount = getNumInstanceMethods();
+ for (int i = 0; i < methodCount; ++i) {
+ if (methods[i]->getSelector() == Sel) {
+ return methods[i];
+ }
+ }
+ return NULL;
+}
+
+// lookupClassMethod - This method returns an instance method by looking in
+// the class implementation. Unlike interfaces, we don't look outside the
+// implementation.
+ObjcMethodDecl *ObjcImplementationDecl::lookupClassMethod(Selector &Sel) {
+ ObjcMethodDecl **methods = getClassMethods();
+ int methodCount = getNumClassMethods();
+ for (int i = 0; i < methodCount; ++i) {
+ if (methods[i]->getSelector() == Sel) {
+ return methods[i];
+ }
+ }
+ return NULL;
+}
diff --git a/Sema/Sema.h b/Sema/Sema.h
index 2d6c42593b..de464c111a 100644
--- a/Sema/Sema.h
+++ b/Sema/Sema.h
@@ -85,7 +85,7 @@ class Sema : public Action {
/// ObjcImplementations - Keep track of all of the classes with
/// @implementation's, so that we can emit errors on duplicates.
- llvm::SmallPtrSet<IdentifierInfo*, 8> ObjcImplementations;
+ llvm::DenseMap<IdentifierInfo*, ObjcImplementationDecl*> ObjcImplementations;
/// ObjcProtocols - Keep track of all protocol declarations declared
/// with @protocol keyword, so that we can emit errors on duplicates and
diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp
index 006bb18bd1..e9c438ffc5 100644
--- a/Sema/SemaDecl.cpp
+++ b/Sema/SemaDecl.cpp
@@ -1477,9 +1477,10 @@ Sema::DeclTy *Sema::ActOnStartClassImplementation(
new ObjcImplementationDecl(AtClassImplLoc, ClassName, IDecl, SDecl);
// Check that there is no duplicate implementation of this class.
- if (!ObjcImplementations.insert(ClassName))
+ if (ObjcImplementations[ClassName])
Diag(ClassLoc, diag::err_dup_implementation_class, ClassName->getName());
-
+ else // add it to the list.
+ ObjcImplementations[ClassName] = IMPDecl;
return IMPDecl;
}
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index 47cbbcabf3..bd210c3adf 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -2126,6 +2126,12 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
// idea is to add class info to InstanceMethodPool...
Method = ClassDecl->lookupInstanceMethod(Sel);
if (!Method) {
+ // If we have an implementation in scope, check "private" methods.
+ if (ObjcImplementationDecl *ImpDecl =
+ ObjcImplementations[ClassDecl->getIdentifier()])
+ Method = ImpDecl->lookupInstanceMethod(Sel);
+ }
+ if (!Method) {
Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(),
SourceRange(lbrac, rbrac));
returnType = Context.getObjcIdType();
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 550b64791a..3fb09036e1 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -667,6 +667,9 @@ public:
ObjcMethodDecl **getClassMethods() const { return ClassMethods; }
int getNumClassMethods() const { return NumClassMethods; }
+
+ ObjcMethodDecl *lookupInstanceMethod(Selector &Sel);
+ ObjcMethodDecl *lookupClassMethod(Selector &Sel);
ObjcIvarDecl **getImplDeclIVars() const { return Ivars; }
int getImplDeclNumIvars() const { return NumIvars; }
diff --git a/test/Sema/message.m b/test/Sema/message.m
new file mode 100644
index 0000000000..517a5f6824
--- /dev/null
+++ b/test/Sema/message.m
@@ -0,0 +1,11 @@
+// RUN: clang -fsyntax-only -verify %s
+
+@interface foo
+- (void)meth;
+@end
+
+@implementation foo
+- (void) contents {} // No declaration in @interface!
+- (void) meth { [self contents]; } // expected-warning {{method '-contents' not found (return type defaults to 'id')}}
+@end
+