From: Fariborz Jahanian Date: Wed, 28 Mar 2012 17:56:49 +0000 (+0000) Subject: objective-c: Improve diagnostics and X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a78eca20429e55b041bffcea1938cd0df07a6ebd;p=clang objective-c: Improve diagnostics and provide 'fixit' hint when dictionary index is not of proper type. // rdar://11062080 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153584 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7df189d5f9..2b8d0b774c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3780,7 +3780,10 @@ def err_objc_multiple_subscript_type_conversion : Error< "multiple type conversion functions">; def err_objc_subscript_type_conversion : Error< "indexing expression is invalid because subscript type %0 is not an intergal" - "or objective-C pointer type">; + " or objective-C pointer type">; +def err_objc_subscript_pointer : Error< + "indexing expression is invalid because subscript type %0 is not an" + " objective-C pointer">; def err_objc_indexing_method_result_type : Error< "method for accessing %select{dictionary|array}1 element must have Objective-C" " object return type instead of %0">; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index ae5257fecb..6b30643db9 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3115,19 +3115,19 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, BaseExpr = LHSExp; IndexExpr = RHSExp; ResultType = PTy->getPointeeType(); - } else if (const PointerType *PTy = RHSTy->getAs()) { - // Handle the uncommon case of "123[Ptr]". - BaseExpr = RHSExp; - IndexExpr = LHSExp; - ResultType = PTy->getPointeeType(); } else if (const ObjCObjectPointerType *PTy = - LHSTy->getAs()) { + LHSTy->getAs()) { BaseExpr = LHSExp; IndexExpr = RHSExp; Result = BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0); if (!Result.isInvalid()) return Owned(Result.take()); ResultType = PTy->getPointeeType(); + } else if (const PointerType *PTy = RHSTy->getAs()) { + // Handle the uncommon case of "123[Ptr]". + BaseExpr = RHSExp; + IndexExpr = LHSExp; + ResultType = PTy->getPointeeType(); } else if (const ObjCObjectPointerType *PTy = RHSTy->getAs()) { // Handle the uncommon case of "123[Ptr]". diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index effb372303..aebc0eb608 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -842,14 +842,20 @@ Sema::ObjCSubscriptKind // If we don't have a class type in C++, there's no way we can get an // expression of integral or enumeration type. const RecordType *RecordTy = T->getAs(); - if (!RecordTy) + if (!RecordTy && T->isObjCObjectPointerType()) // All other scalar cases are assumed to be dictionary indexing which // caller handles, with diagnostics if needed. return OS_Dictionary; - if (!getLangOpts().CPlusPlus || RecordTy->isIncompleteType()) { + if (!getLangOpts().CPlusPlus || + !RecordTy || RecordTy->isIncompleteType()) { // No indexing can be done. Issue diagnostics and quit. - Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) - << FromE->getType(); + const Expr *IndexExpr = FromE->IgnoreParenImpCasts(); + if (isa(IndexExpr)) + Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer) + << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@"); + else + Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) + << T; return OS_Error; } diff --git a/test/SemaObjC/objc-container-subscripting-2.m b/test/SemaObjC/objc-container-subscripting-2.m index 2564975f4d..45f82e5c74 100644 --- a/test/SemaObjC/objc-container-subscripting-2.m +++ b/test/SemaObjC/objc-container-subscripting-2.m @@ -16,8 +16,8 @@ typedef unsigned int size_t; id func() { NSMutableArray *array; float f; - array[f] = array; // expected-error {{expected method to write dictionary element not found on object of type 'NSMutableArray *'}} - return array[3.14]; // expected-error {{expected method to read dictionary element not found on object of type 'NSMutableArray *'}} + array[f] = array; // expected-error {{indexing expression is invalid because subscript type 'float' is not an intergal or objective-C pointer type}} + return array[3.14]; // expected-error {{indexing expression is invalid because subscript type 'double' is not an intergal or objective-C pointer type}} } void test_unused() { diff --git a/test/SemaObjC/objc-dictionary-literal.m b/test/SemaObjC/objc-dictionary-literal.m new file mode 100644 index 0000000000..2acbc39e38 --- /dev/null +++ b/test/SemaObjC/objc-dictionary-literal.m @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// rdar://11062080 + +@interface NSNumber ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithInt:(int)value; +@end + +@protocol NSCopying @end +typedef unsigned long NSUInteger; +typedef long NSInteger; + +@interface NSDictionary ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(NSUInteger)cnt; +- (void)setObject:(id)object forKeyedSubscript:(id)key; +@end + +@interface NSString +@end + +@interface NSArray +- (id)objectAtIndexedSubscript:(NSInteger)index; +- (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; +@end + +int main() { + NSDictionary *dict = @{ @"name":@666 }; + dict[@"name"] = @666; + + dict["name"] = @666; // expected-error {{indexing expression is invalid because subscript type 'char *' is not an objective-C pointer}} + + return 0; +} + diff --git a/test/SemaObjCXX/objc-container-subscripting.mm b/test/SemaObjCXX/objc-container-subscripting.mm index ccbc45e3b4..7591c3b098 100644 --- a/test/SemaObjCXX/objc-container-subscripting.mm +++ b/test/SemaObjCXX/objc-container-subscripting.mm @@ -32,8 +32,8 @@ template void test_dictionary_subscripts(NSMutableDictionary*, id, int); // expe template void test_array_subscripts(T base, U index, O obj) { - base[index] = obj; // expected-error {{expected method to write dictionary element not found on object of type 'NSMutableArray *'}} - obj = base[index]; // expected-error {{expected method to read dictionary element not found on object of type 'NSMutableArray *'}} + base[index] = obj; // expected-error {{indexing expression is invalid because subscript type 'double' is not an intergal or objective-C pointer type}} + obj = base[index]; // expected-error {{indexing expression is invalid because subscript type 'double' is not an intergal or objective-C pointer type}} } template void test_array_subscripts(NSMutableArray *, int, id);