aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2008-12-05 18:18:52 +0000
committerFariborz Jahanian <fjahanian@apple.com>2008-12-05 18:18:52 +0000
commit8daab970b80ed2e751fc88327180acbeff1dbb9c (patch)
treec0528779be503b4b2913a5984cf9ecf8ea23fac9
parent72c3f314d92d65c050ee1c07b7753623c044d6c7 (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.def2
-rw-r--r--lib/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaDeclObjC.cpp73
-rw-r--r--test/SemaObjC/comptypes-a.m2
-rw-r--r--test/SemaObjC/method-typecheck-1.m33
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
+