From: Steve Naroff Date: Tue, 16 Oct 2007 20:39:36 +0000 (+0000) Subject: Emit diagnostics for methods not found. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=983df5b2280980e59b0b062bcc2882230465a61e;p=clang Emit diagnostics for methods not found. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43037 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 046b92bb07..daa1a7c141 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -1930,11 +1930,17 @@ Sema::ExprResult Sema::ActOnClassMessage( ObjcInterfaceDecl* ClassDecl = getObjCInterfaceDecl(receiverName); ObjcMethodDecl *Method = ClassDecl->lookupClassMethod(Sel); - assert(Method && "missing method declaration"); - QualType retType = Method->getMethodType(); + QualType returnType; + if (!Method) { + Diag(lbrac, diag::warn_method_not_found, std::string("+"), Sel.getName(), + SourceRange(lbrac, rbrac)); + returnType = GetObjcIdType(); + } else { + returnType = Method->getMethodType(); + } // Expr *RExpr = global reference to the class symbol... Expr **ArgExprs = reinterpret_cast(Args); - return new ObjCMessageExpr(receiverName, Sel, retType, lbrac, rbrac, + return new ObjCMessageExpr(receiverName, Sel, returnType, lbrac, rbrac, ArgExprs); } @@ -1953,9 +1959,13 @@ Sema::ExprResult Sema::ActOnInstanceMessage( if (receiverType == GetObjcIdType()) { ObjcMethodDecl *Method = InstanceMethodPool[Sel].Method; - // FIXME: emit a diagnostic. For now, I want a hard error... - assert(Method && "missing method declaration"); - returnType = Method->getMethodType(); + if (!Method) { + Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(), + SourceRange(lbrac, rbrac)); + returnType = GetObjcIdType(); + } else { + returnType = Method->getMethodType(); + } } else { // FIXME (snaroff): checking in this code from Patrick. Needs to be // revisited. how do we get the ClassDecl from the receiver expression? @@ -1968,10 +1978,17 @@ Sema::ExprResult Sema::ActOnInstanceMessage( "bad receiver type"); ObjcInterfaceDecl* ClassDecl = static_cast( receiverType.getTypePtr())->getDecl(); + // FIXME: consider using InstanceMethodPool, since it will be faster + // than the following method (which can do *many* linear searches). The + // idea is to add class info to InstanceMethodPool... ObjcMethodDecl *Method = ClassDecl->lookupInstanceMethod(Sel); - // FIXME: emit a diagnostic. For now, I want a hard error... - assert(Method && "missing method declaration"); - returnType = Method->getMethodType(); + if (!Method) { + Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(), + SourceRange(lbrac, rbrac)); + returnType = GetObjcIdType(); + } else { + returnType = Method->getMethodType(); + } } Expr **ArgExprs = reinterpret_cast(Args); return new ObjCMessageExpr(RExpr, Sel, returnType, lbrac, rbrac, ArgExprs); diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 090cc52c67..bf0bf55123 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -157,12 +157,14 @@ public: // CURRENTLY UNUSED (10/15/07). ObjCStringLiteral now uses the hook below. QualType getCFConstantStringType(); - // This setter/getter represents the actual ObjC type for an NSConstantString. + // This setter/getter represents the ObjC type for an NSConstantString. void setObjcConstantStringInterface(ObjcInterfaceDecl *Decl); QualType getObjcConstantStringInterface() const { return ObjcConstantStringType; } + // This setter/getter repreents the ObjC 'id' type. It is setup lazily, by + // Sema. void setObjcIdType(TypedefDecl *Decl); QualType getObjcIdType() const { return ObjcIdType; } diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 5325c025ef..bad641962b 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -454,6 +454,8 @@ DIAG(err_conflicting_aliasing_type, ERROR, "conflicting types for alias %0'") DIAG(err_statically_allocated_object, ERROR, "statically allocated Objective-c object '%0'") +DIAG(warn_method_not_found, WARNING, + "method '%0%1' not found (return type defaults to 'id')") //===----------------------------------------------------------------------===// // Semantic Analysis diff --git a/test/Sema/method-not-defined.m b/test/Sema/method-not-defined.m new file mode 100644 index 0000000000..adb8a67fc8 --- /dev/null +++ b/test/Sema/method-not-defined.m @@ -0,0 +1,14 @@ +// RUN: clang -fsyntax-only -verify %s + +typedef struct objc_object *id; +@interface Foo +@end + +void test() { + Foo *fooObj; + id obj; + + [[Foo alloc] init]; // expected-warning {{method '+alloc' not found (return type defaults to 'id')}} expected-warning {{method '-init' not found (return type defaults to 'id')}} + [fooObj notdefined]; // expected-warning {{method '-notdefined' not found (return type defaults to 'id')}} + [obj whatever:1 :2 :3]; // expected-warning {{method '-whatever:::' not found (return type defaults to 'id'))}} +}