diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 21 | ||||
-rw-r--r-- | test/CodeGenObjC/for-in.m | 4 | ||||
-rw-r--r-- | test/SemaObjCXX/instantiate-stmt.mm | 1 |
4 files changed, 26 insertions, 2 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 9663acc6a3..ba156b16cf 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3170,6 +3170,8 @@ def err_selector_element_type : Error< "selector element type %0 is not a valid object">; def err_collection_expr_type : Error< "collection expression type %0 is not a valid object">; +def warn_collection_expr_type : Warning< + "collection expression type %0 may not respond to %1">; def err_invalid_conversion_between_ext_vectors : Error< "invalid conversion between ext-vector type %0 and %1">; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 097ea68655..73e142c782 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -941,6 +941,27 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, if (!SecondType->isObjCObjectPointerType()) Diag(ForLoc, diag::err_collection_expr_type) << SecondType << Second->getSourceRange(); + else if (const ObjCObjectPointerType *OPT = + SecondType->getAsObjCInterfacePointerType()) { + llvm::SmallVector<IdentifierInfo *, 4> KeyIdents; + IdentifierInfo* selIdent = + &Context.Idents.get("countByEnumeratingWithState"); + KeyIdents.push_back(selIdent); + selIdent = &Context.Idents.get("objects"); + KeyIdents.push_back(selIdent); + selIdent = &Context.Idents.get("count"); + KeyIdents.push_back(selIdent); + Selector CSelector = Context.Selectors.getSelector(3, &KeyIdents[0]); + if (ObjCInterfaceDecl *IDecl = OPT->getInterfaceDecl()) { + if (!IDecl->isForwardDecl() && + !IDecl->lookupInstanceMethod(CSelector)) { + // Must further look into privaye implementation methods. + if (!LookupPrivateInstanceMethod(CSelector, IDecl)) + Diag(ForLoc, diag::warn_collection_expr_type) + << SecondType << CSelector << Second->getSourceRange(); + } + } + } } first.release(); second.release(); diff --git a/test/CodeGenObjC/for-in.m b/test/CodeGenObjC/for-in.m index 354ff32c0e..7e6098a7eb 100644 --- a/test/CodeGenObjC/for-in.m +++ b/test/CodeGenObjC/for-in.m @@ -23,7 +23,7 @@ void t0() { p("array.length: %d\n", [array count]); unsigned index = 0; - for (NSString *i in array) { + for (NSString *i in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}} p("element %d: %s\n", index++, [i cString]); } } @@ -33,7 +33,7 @@ void t1() { p("array.length: %d\n", [array count]); unsigned index = 0; - for (NSString *i in array) { + for (NSString *i in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}} index++; if (index == 10) continue; diff --git a/test/SemaObjCXX/instantiate-stmt.mm b/test/SemaObjCXX/instantiate-stmt.mm index e92f8e8d4f..5e8ec61573 100644 --- a/test/SemaObjCXX/instantiate-stmt.mm +++ b/test/SemaObjCXX/instantiate-stmt.mm @@ -25,6 +25,7 @@ template void synchronized_test(int); // expected-note{{in instantiation of}} // fast enumeration @interface NSArray +- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount; @end @interface NSString |