diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-05-17 23:13:29 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-05-17 23:13:29 +0000 |
commit | 0a4a23a6afd6db4bdcedd4e9f39d8baf4a446f15 (patch) | |
tree | 6732406d14673e5bf18c863b85c1619337450461 | |
parent | 593b91f628bcb7d308867730784c87af0f9db601 (diff) |
A selector match between two Objective-C methods does *not* guarantee
that the methods have the same number of parameters, although we
certainly assumed this in many places. Objective-C can be insane
sometimes. Fixes <rdar://problem/11460990>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@157025 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 31 | ||||
-rw-r--r-- | test/SemaObjC/related-result-type-inference.m | 6 |
3 files changed, 27 insertions, 15 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index be1ab69a56..cc42720a7b 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2227,10 +2227,11 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, mergeDeclAttributes(newMethod, oldMethod, mergeDeprecation); // Merge attributes from the parameters. - ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(); + ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(), + oe = oldMethod->param_end(); for (ObjCMethodDecl::param_iterator ni = newMethod->param_begin(), ne = newMethod->param_end(); - ni != ne; ++ni, ++oi) + ni != ne && oi != oe; ++ni, ++oi) mergeParamDeclAttributes(*ni, *oi, Context); CheckObjCMethodOverride(newMethod, oldMethod, true); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 10bc1c27f0..9e640b4540 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -173,10 +173,11 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, Diag(Overridden->getLocation(), diag::note_previous_decl) << "method"; } - ObjCMethodDecl::param_const_iterator oi = Overridden->param_begin(); + ObjCMethodDecl::param_const_iterator oi = Overridden->param_begin(), + oe = Overridden->param_end(); for (ObjCMethodDecl::param_iterator ni = NewMethod->param_begin(), ne = NewMethod->param_end(); - ni != ne; ++ni, ++oi) { + ni != ne && oi != oe; ++ni, ++oi) { const ParmVarDecl *oldDecl = (*oi); ParmVarDecl *newDecl = (*ni); if (newDecl->hasAttr<NSConsumedAttr>() != @@ -1399,8 +1400,9 @@ void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, true); for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(), - IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(); - IM != EM; ++IM, ++IF) { + IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(), + EF = MethodDecl->param_end(); + IM != EM && IF != EF; ++IM, ++IF) { CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF, IsProtocolMethodDecl, false, true); } @@ -1421,8 +1423,9 @@ void Sema::CheckConflictingOverridingMethod(ObjCMethodDecl *Method, true); for (ObjCMethodDecl::param_iterator IM = Method->param_begin(), - IF = Overridden->param_begin(), EM = Method->param_end(); - IM != EM; ++IM, ++IF) { + IF = Overridden->param_begin(), EM = Method->param_end(), + EF = Overridden->param_end(); + IM != EM && IF != EF; ++IM, ++IF) { CheckMethodOverrideParam(*this, Method, Overridden, *IM, *IF, IsProtocolMethodDecl, true, true); } @@ -1454,8 +1457,9 @@ void Sema::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl, IsProtocolMethodDecl, false, false); if (match) for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(), - IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(); - IM != EM; ++IM, ++IF) { + IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(), + EF = MethodDecl->param_end(); + IM != EM && IF != EF; ++IM, ++IF) { match = CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF, IsProtocolMethodDecl, false, false); @@ -1954,9 +1958,10 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left, return false; ObjCMethodDecl::param_const_iterator - li = left->param_begin(), le = left->param_end(), ri = right->param_begin(); + li = left->param_begin(), le = left->param_end(), ri = right->param_begin(), + re = right->param_end(); - for (; li != le; ++li, ++ri) { + for (; li != le && ri != re; ++li, ++ri) { assert(ri != right->param_end() && "Param mismatch"); const ParmVarDecl *lparm = *li, *rparm = *ri; @@ -2673,9 +2678,9 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, isa<ObjCInterfaceDecl>(overridden->getDeclContext())) { ObjCMethodDecl::param_iterator ParamI = ObjCMethod->param_begin(), E = ObjCMethod->param_end(); - ObjCMethodDecl::param_iterator PrevI = overridden->param_begin(); - for (; ParamI != E; ++ParamI, ++PrevI) { - // Number of parameters are the same and is guaranteed by selector match. + ObjCMethodDecl::param_iterator PrevI = overridden->param_begin(), + PrevE = overridden->param_end(); + for (; ParamI != E && PrevI != PrevE; ++ParamI, ++PrevI) { assert(PrevI != overridden->param_end() && "Param mismatch"); QualType T1 = Context.getCanonicalType((*ParamI)->getType()); QualType T2 = Context.getCanonicalType((*PrevI)->getType()); diff --git a/test/SemaObjC/related-result-type-inference.m b/test/SemaObjC/related-result-type-inference.m index 124767cd66..90671145a6 100644 --- a/test/SemaObjC/related-result-type-inference.m +++ b/test/SemaObjC/related-result-type-inference.m @@ -178,3 +178,9 @@ void test_inference() { return (id)self; // expected-warning {{returning 'Fail *' from a function with incompatible result type 'id<X>'}} } @end + +// <rdar://problem/11460990> + +@interface WeirdNSString : NSString +- (id)initWithCString:(const char*)string, void *blah; +@end |