diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2008-12-05 18:18:52 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2008-12-05 18:18:52 +0000 |
commit | 8daab970b80ed2e751fc88327180acbeff1dbb9c (patch) | |
tree | c0528779be503b4b2913a5984cf9ecf8ea23fac9 | |
parent | 72c3f314d92d65c050ee1c07b7753623c044d6c7 (diff) |
(instance/class) Method type checking between class and its implementation.
(instance/class) Method type checking between category and its implementation.
And a test case for all.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60598 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticKinds.def | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 73 | ||||
-rw-r--r-- | test/SemaObjC/comptypes-a.m | 2 | ||||
-rw-r--r-- | test/SemaObjC/method-typecheck-1.m | 33 |
5 files changed, 88 insertions, 24 deletions
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index eea6fe4b96..31708b0112 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -573,6 +573,8 @@ DIAG(err_accessor_property_type_mismatch, ERROR, "type of property %0 does not match type of accessor %1") DIAG(err_setter_type_void, ERROR, "type of setter must be void") +DIAG(warn_conflicting_types, WARNING, + "conflicting types for %0") /// C++ parser diagnostics DIAG(err_expected_unqualified_id, ERROR, diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index f1d0ee2da0..85cd2c873b 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -490,6 +490,8 @@ public: void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, bool &IncompleteImpl); + void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod, + ObjCMethodDecl *IntfMethod); NamespaceDecl *GetStdNamespace(); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 01a453d3be..a58d1da632 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -590,6 +590,32 @@ void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, Diag(ImpLoc, diag::warn_undef_method_impl) << method->getDeclName(); } +void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, + ObjCMethodDecl *IntfMethodDecl) { + bool err = false; + QualType ImpMethodQType = + Context.getCanonicalType(ImpMethodDecl->getResultType()); + QualType IntfMethodQType = + Context.getCanonicalType(IntfMethodDecl->getResultType()); + if (!Context.typesAreCompatible(IntfMethodQType, ImpMethodQType)) + err = true; + else for (ObjCMethodDecl::param_iterator IM=ImpMethodDecl->param_begin(), + IF=IntfMethodDecl->param_begin(), + EM=ImpMethodDecl->param_end(); IM!=EM; ++IM, IF++) { + ImpMethodQType = Context.getCanonicalType((*IM)->getType()); + IntfMethodQType = Context.getCanonicalType((*IF)->getType()); + if (!Context.typesAreCompatible(IntfMethodQType, ImpMethodQType)) { + err = true; + break; + } + } + if (err) { + Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_types) + << ImpMethodDecl->getDeclName(); + Diag(IntfMethodDecl->getLocation(), diag::note_previous_definition); + } +} + /// FIXME: Type hierarchies in Objective-C can be deep. We could most /// likely improve the efficiency of selector lookups and type /// checking by associating with each protocol / interface / category @@ -651,32 +677,12 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, if (!(*I)->isSynthesized() && !InsMap.count((*I)->getSelector())) WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl); else if (!(*I)->isSynthesized()){ - bool err = false; ObjCMethodDecl *ImpMethodDecl = IMPDecl->getInstanceMethod((*I)->getSelector()); ObjCMethodDecl *IntfMethodDecl = IDecl->getInstanceMethod((*I)->getSelector()); - QualType ImpMethodQType = - Context.getCanonicalType(ImpMethodDecl->getResultType()); - QualType IntfMethodQType = - Context.getCanonicalType(IntfMethodDecl->getResultType()); - if (!Context.typesAreCompatible(IntfMethodQType, ImpMethodQType)) - err = true; - else for (ObjCMethodDecl::param_iterator IM=ImpMethodDecl->param_begin(), - IF=IntfMethodDecl->param_begin(), - EM=ImpMethodDecl->param_end(); IM!=EM; ++IM, IF++) { - ImpMethodQType = Context.getCanonicalType((*IM)->getType()); - IntfMethodQType = Context.getCanonicalType((*IF)->getType()); - if (!Context.typesAreCompatible(IntfMethodQType, ImpMethodQType)) { - err = true; - break; - } - } - if (err) { - Diag(ImpMethodDecl->getLocation(), diag::err_conflicting_types) - << ImpMethodDecl->getDeclName(); - Diag(IntfMethodDecl->getLocation(), diag::note_previous_definition); - } + WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); + } llvm::DenseSet<Selector> ClsMap; @@ -690,6 +696,14 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplementationDecl* IMPDecl, E = IDecl->classmeth_end(); I != E; ++I) if (!ClsMap.count((*I)->getSelector())) WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl); + else { + ObjCMethodDecl *ImpMethodDecl = + IMPDecl->getClassMethod((*I)->getSelector()); + ObjCMethodDecl *IntfMethodDecl = + IDecl->getClassMethod((*I)->getSelector()); + WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); + } + // Check the protocol list for unimplemented methods in the @implementation // class. @@ -717,6 +731,13 @@ void Sema::ImplCategoryMethodsVsIntfMethods(ObjCCategoryImplDecl *CatImplDecl, E = CatClassDecl->instmeth_end(); I != E; ++I) if (!InsMap.count((*I)->getSelector())) WarnUndefinedMethod(CatImplDecl->getLocation(), *I, IncompleteImpl); + else { + ObjCMethodDecl *ImpMethodDecl = + CatImplDecl->getInstanceMethod((*I)->getSelector()); + ObjCMethodDecl *IntfMethodDecl = + CatClassDecl->getInstanceMethod((*I)->getSelector()); + WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); + } llvm::DenseSet<Selector> ClsMap; // Check and see if class methods in category interface have been @@ -730,7 +751,13 @@ void Sema::ImplCategoryMethodsVsIntfMethods(ObjCCategoryImplDecl *CatImplDecl, E = CatClassDecl->classmeth_end(); I != E; ++I) if (!ClsMap.count((*I)->getSelector())) WarnUndefinedMethod(CatImplDecl->getLocation(), *I, IncompleteImpl); - + else { + ObjCMethodDecl *ImpMethodDecl = + CatImplDecl->getClassMethod((*I)->getSelector()); + ObjCMethodDecl *IntfMethodDecl = + CatClassDecl->getClassMethod((*I)->getSelector()); + WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); + } // Check the protocol list for unimplemented methods in the @implementation // class. for (ObjCCategoryDecl::protocol_iterator PI = CatClassDecl->protocol_begin(), diff --git a/test/SemaObjC/comptypes-a.m b/test/SemaObjC/comptypes-a.m index f00369f5ca..4abc9fdddb 100644 --- a/test/SemaObjC/comptypes-a.m +++ b/test/SemaObjC/comptypes-a.m @@ -23,7 +23,7 @@ NSInteger codeAssistantCaseCompareItems(id<PBXCompletionItem> a, id<PBXCompletio @implementation TedWantsToVerifyObjCDoesTheRightThing -- compareThis:(id<PBXCompletionItem>)a withThat:(id<PBXCompletionItem>)b { // expected-error {{conflicting types for 'compareThis:withThat:'}} +- compareThis:(id<PBXCompletionItem>)a withThat:(id<PBXCompletionItem>)b { // expected-warning {{conflicting types for 'compareThis:withThat:'}} return self; } diff --git a/test/SemaObjC/method-typecheck-1.m b/test/SemaObjC/method-typecheck-1.m new file mode 100644 index 0000000000..3b1b0c95a6 --- /dev/null +++ b/test/SemaObjC/method-typecheck-1.m @@ -0,0 +1,33 @@ +@interface A +- (void) setMoo: (int) x; // expected-note {{previous definition is here}} +- (int) setMoo1: (int) x; // expected-note {{previous definition is here}} +- (int) setOk : (int) x : (double) d; +@end + +@implementation A +-(void) setMoo: (float) x {} // expected-warning {{conflicting types for 'setMoo:'}} +- (char) setMoo1: (int) x {} // expected-warning {{conflicting types for 'setMoo1:'}} +- (int) setOk : (int) x : (double) d {} +@end + + + +@interface C ++ (void) cMoo: (int) x; // expected-note {{previous definition is here}} +@end + +@implementation C ++(float) cMoo: (float) x {} // expected-warning {{conflicting types for 'cMoo:'}} +@end + + +@interface A(CAT) +- (void) setCat: (int) x; // expected-note {{previous definition is here}} ++ (void) cCat: (int) x; // expected-note {{previous definition is here}} +@end + +@implementation A(CAT) +-(float) setCat: (float) x {} // expected-warning {{conflicting types for 'setCat:'}} ++ (int) cCat: (int) x {} // expected-warning {{conflicting types for 'cCat:'}} +@end + |