aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.def2
-rw-r--r--lib/AST/Decl.cpp5
-rw-r--r--lib/AST/DeclObjC.cpp40
-rw-r--r--lib/Sema/SemaExprObjC.cpp39
-rw-r--r--test/SemaObjC/property-11.m5
-rw-r--r--test/SemaObjC/protocol-id-test-1.m2
-rw-r--r--test/SemaObjC/protocol-id-test-2.m4
7 files changed, 57 insertions, 40 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def
index fb9f36399b..2549df6b93 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.def
+++ b/include/clang/Basic/DiagnosticSemaKinds.def
@@ -916,8 +916,6 @@ DIAG(error_no_super_class, ERROR,
"no super class declared in @interface for %0")
DIAG(err_invalid_receiver_to_message, ERROR,
"invalid receiver to message expression")
-DIAG(warn_method_not_found_in_protocol, WARNING,
- "method %objcinstance0 not found in protocol (return type defaults to 'id')")
DIAG(error_bad_receiver_type, ERROR,
"bad receiver type %0")
DIAG(error_objc_throw_expects_object, ERROR,
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 387f79a013..f7608529d4 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -13,6 +13,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Expr.h"
@@ -194,6 +195,10 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
// For function declarations, we keep track of redeclarations.
return FD->getPreviousDeclaration() == OldD;
+ // For method declarations, we keep track of redeclarations.
+ if (isa<ObjCMethodDecl>(this))
+ return false;
+
// For non-function declarations, if the declarations are of the
// same kind then this must be a redeclaration, or semantic analysis
// would not have given us the new declaration.
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 461bb9697f..a9f7922ed0 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
+#include "llvm/ADT/STLExtras.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -42,21 +43,42 @@ void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
//===----------------------------------------------------------------------===//
// Get the local instance method declared in this interface.
-// FIXME: handle overloading, instance & class methods can have the same name.
ObjCMethodDecl *ObjCContainerDecl::getInstanceMethod(Selector Sel) const {
- lookup_const_result MethodResult = lookup(Sel);
- if (MethodResult.first)
- return const_cast<ObjCMethodDecl*>(
- dyn_cast<ObjCMethodDecl>(*MethodResult.first));
+ // Since instance & class methods can have the same name, the loop below
+ // ensures we get the correct method.
+ //
+ // @interface Whatever
+ // - (int) class_method;
+ // + (float) class_method;
+ // @end
+ //
+ lookup_const_iterator Meth, MethEnd;
+ for (llvm::tie(Meth, MethEnd) = lookup(Sel);
+ Meth != MethEnd; ++Meth) {
+ ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
+ if (MD && MD->isInstanceMethod())
+ return MD;
+ }
return 0;
}
// Get the local class method declared in this interface.
ObjCMethodDecl *ObjCContainerDecl::getClassMethod(Selector Sel) const {
- lookup_const_result MethodResult = lookup(Sel);
- if (MethodResult.first)
- return const_cast<ObjCMethodDecl*>(
- dyn_cast<ObjCMethodDecl>(*MethodResult.first));
+ // Since instance & class methods can have the same name, the loop below
+ // ensures we get the correct method.
+ //
+ // @interface Whatever
+ // - (int) class_method;
+ // + (float) class_method;
+ // @end
+ //
+ lookup_const_iterator Meth, MethEnd;
+ for (llvm::tie(Meth, MethEnd) = lookup(Sel);
+ Meth != MethEnd; ++Meth) {
+ ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth);
+ if (MD && MD->isClassMethod())
+ return MD;
+ }
return 0;
}
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index e5fefd3e3a..d8f3fd4cf7 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -397,9 +397,6 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
break;
}
- if (!Method)
- Diag(lbrac, diag::warn_method_not_found_in_protocol)
- << Sel << RExpr->getSourceRange();
// Check for GCC extension "Class<foo>".
} else if (ObjCQualifiedClassType *QIT =
dyn_cast<ObjCQualifiedClassType>(ReceiverCType)) {
@@ -409,9 +406,6 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
break;
}
- if (!Method)
- Diag(lbrac, diag::warn_method_not_found_in_protocol)
- << Sel << RExpr->getSourceRange();
} else if (const ObjCInterfaceType *OCIReceiver =
ReceiverCType->getAsPointerToObjCInterfaceType()) {
// We allow sending a message to a pointer to an interface (an object).
@@ -422,19 +416,29 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
// The idea is to add class info to InstanceMethodPool.
Method = ClassDecl->lookupInstanceMethod(Sel);
+ bool haveQualifiers = false;
if (!Method) {
// Search protocol qualifiers.
for (ObjCQualifiedIdType::qual_iterator QI = OCIReceiver->qual_begin(),
E = OCIReceiver->qual_end(); QI != E; ++QI) {
+ haveQualifiers = true;
if ((Method = (*QI)->lookupInstanceMethod(Sel)))
break;
}
}
-
- if (!Method && !OCIReceiver->qual_empty())
- Diag(lbrac, diag::warn_method_not_found_in_protocol)
- << Sel << SourceRange(lbrac, rbrac);
-
+ if (!Method) {
+ // If we have an implementation in scope, check "private" methods.
+ if (ClassDecl)
+ if (ObjCImplementationDecl *ImpDecl =
+ ObjCImplementations[ClassDecl->getIdentifier()])
+ Method = ImpDecl->getInstanceMethod(Sel);
+ // 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
+ // compatibility. FIXME: should we deviate??
+ if (!Method && !haveQualifiers)
+ Method = LookupInstanceMethodInGlobalPool(
+ Sel, SourceRange(lbrac,rbrac));
+ }
if (Method && DiagnoseUseOfDecl(Method, receiverLoc))
return true;
} else {
@@ -443,19 +447,6 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,
return true;
}
- if (!Method) {
- // If we have an implementation in scope, check "private" methods.
- if (ClassDecl)
- if (ObjCImplementationDecl *ImpDecl =
- ObjCImplementations[ClassDecl->getIdentifier()])
- Method = ImpDecl->getInstanceMethod(Sel);
- // 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
- // compatibility.
- if (!Method)
- Method = LookupInstanceMethodInGlobalPool(
- Sel, SourceRange(lbrac,rbrac));
- }
if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false,
lbrac, rbrac, returnType))
return true;
diff --git a/test/SemaObjC/property-11.m b/test/SemaObjC/property-11.m
index 8038328002..d28608aecf 100644
--- a/test/SemaObjC/property-11.m
+++ b/test/SemaObjC/property-11.m
@@ -22,7 +22,10 @@
NSSound *x;
id o;
- o = [x foo];
+ // GCC does *not* warn about the following. Since foo/setFoo: are not in the
+ // class or category interface for NSSound, the compiler shouldn't find them.
+ // For now, we will support GCC's behavior (sigh).
+ o = [x foo];
o = x.foo;
[x setFoo:o];
x.foo = o;
diff --git a/test/SemaObjC/protocol-id-test-1.m b/test/SemaObjC/protocol-id-test-1.m
index 765500e10d..4e636d7e1c 100644
--- a/test/SemaObjC/protocol-id-test-1.m
+++ b/test/SemaObjC/protocol-id-test-1.m
@@ -12,5 +12,5 @@
@end
@implementation INTF
-- (void)IMeth {INTF<P> *pi; [pi Meth]; } // expected-warning {{method '-Meth' not found in protocol (return type defaults to 'id')}}
+- (void)IMeth {INTF<P> *pi; [pi Meth]; } // expected-warning {{method '-Meth' not found (return type defaults to 'id')}}
@end
diff --git a/test/SemaObjC/protocol-id-test-2.m b/test/SemaObjC/protocol-id-test-2.m
index 525d2cca9e..3b4adcfb5b 100644
--- a/test/SemaObjC/protocol-id-test-2.m
+++ b/test/SemaObjC/protocol-id-test-2.m
@@ -5,10 +5,8 @@
@interface INTF<P>
- (void)IMeth;
- - (void) Meth;
@end
@implementation INTF
-- (void)IMeth { [(id<P>)self Meth]; } // expected-warning {{method '-Meth' not found in protocol (return type defaults to 'id')}}
-- (void) Meth {}
+- (void)IMeth { [(id<P>)self Meth]; } // expected-warning {{method '-Meth' not found (return type defaults to 'id')}}
@end