"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,
#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"
// 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.
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Stmt.h"
+#include "llvm/ADT/STLExtras.h"
using namespace clang;
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// 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;
}
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)) {
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).
// 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 {
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;
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;
@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
@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