forked from OSchip/llvm-project
objective-c: Improve diagnostics and
provide 'fixit' hint when dictionary index is not of proper type. // rdar://11062080 llvm-svn: 153584
This commit is contained in:
parent
726bc52a2e
commit
ba0afde486
clang
include/clang/Basic
lib/Sema
test
|
@ -3780,7 +3780,10 @@ def err_objc_multiple_subscript_type_conversion : Error<
|
||||||
"multiple type conversion functions">;
|
"multiple type conversion functions">;
|
||||||
def err_objc_subscript_type_conversion : Error<
|
def err_objc_subscript_type_conversion : Error<
|
||||||
"indexing expression is invalid because subscript type %0 is not an intergal"
|
"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<
|
def err_objc_indexing_method_result_type : Error<
|
||||||
"method for accessing %select{dictionary|array}1 element must have Objective-C"
|
"method for accessing %select{dictionary|array}1 element must have Objective-C"
|
||||||
" object return type instead of %0">;
|
" object return type instead of %0">;
|
||||||
|
|
|
@ -3115,19 +3115,19 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
|
||||||
BaseExpr = LHSExp;
|
BaseExpr = LHSExp;
|
||||||
IndexExpr = RHSExp;
|
IndexExpr = RHSExp;
|
||||||
ResultType = PTy->getPointeeType();
|
ResultType = PTy->getPointeeType();
|
||||||
} else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) {
|
|
||||||
// Handle the uncommon case of "123[Ptr]".
|
|
||||||
BaseExpr = RHSExp;
|
|
||||||
IndexExpr = LHSExp;
|
|
||||||
ResultType = PTy->getPointeeType();
|
|
||||||
} else if (const ObjCObjectPointerType *PTy =
|
} else if (const ObjCObjectPointerType *PTy =
|
||||||
LHSTy->getAs<ObjCObjectPointerType>()) {
|
LHSTy->getAs<ObjCObjectPointerType>()) {
|
||||||
BaseExpr = LHSExp;
|
BaseExpr = LHSExp;
|
||||||
IndexExpr = RHSExp;
|
IndexExpr = RHSExp;
|
||||||
Result = BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0);
|
Result = BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, 0, 0);
|
||||||
if (!Result.isInvalid())
|
if (!Result.isInvalid())
|
||||||
return Owned(Result.take());
|
return Owned(Result.take());
|
||||||
ResultType = PTy->getPointeeType();
|
ResultType = PTy->getPointeeType();
|
||||||
|
} else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) {
|
||||||
|
// Handle the uncommon case of "123[Ptr]".
|
||||||
|
BaseExpr = RHSExp;
|
||||||
|
IndexExpr = LHSExp;
|
||||||
|
ResultType = PTy->getPointeeType();
|
||||||
} else if (const ObjCObjectPointerType *PTy =
|
} else if (const ObjCObjectPointerType *PTy =
|
||||||
RHSTy->getAs<ObjCObjectPointerType>()) {
|
RHSTy->getAs<ObjCObjectPointerType>()) {
|
||||||
// Handle the uncommon case of "123[Ptr]".
|
// Handle the uncommon case of "123[Ptr]".
|
||||||
|
|
|
@ -842,14 +842,20 @@ Sema::ObjCSubscriptKind
|
||||||
// If we don't have a class type in C++, there's no way we can get an
|
// If we don't have a class type in C++, there's no way we can get an
|
||||||
// expression of integral or enumeration type.
|
// expression of integral or enumeration type.
|
||||||
const RecordType *RecordTy = T->getAs<RecordType>();
|
const RecordType *RecordTy = T->getAs<RecordType>();
|
||||||
if (!RecordTy)
|
if (!RecordTy && T->isObjCObjectPointerType())
|
||||||
// All other scalar cases are assumed to be dictionary indexing which
|
// All other scalar cases are assumed to be dictionary indexing which
|
||||||
// caller handles, with diagnostics if needed.
|
// caller handles, with diagnostics if needed.
|
||||||
return OS_Dictionary;
|
return OS_Dictionary;
|
||||||
if (!getLangOpts().CPlusPlus || RecordTy->isIncompleteType()) {
|
if (!getLangOpts().CPlusPlus ||
|
||||||
|
!RecordTy || RecordTy->isIncompleteType()) {
|
||||||
// No indexing can be done. Issue diagnostics and quit.
|
// No indexing can be done. Issue diagnostics and quit.
|
||||||
Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
|
const Expr *IndexExpr = FromE->IgnoreParenImpCasts();
|
||||||
<< FromE->getType();
|
if (isa<StringLiteral>(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;
|
return OS_Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ typedef unsigned int size_t;
|
||||||
id func() {
|
id func() {
|
||||||
NSMutableArray *array;
|
NSMutableArray *array;
|
||||||
float f;
|
float f;
|
||||||
array[f] = array; // expected-error {{expected method to write 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 {{expected method to read dictionary element not found on object of type 'NSMutableArray *'}}
|
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() {
|
void test_unused() {
|
||||||
|
|
|
@ -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 <NSCopying> [])keys count:(NSUInteger)cnt;
|
||||||
|
- (void)setObject:(id)object forKeyedSubscript:(id)key;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface NSString<NSCopying>
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
|
@ -32,8 +32,8 @@ template void test_dictionary_subscripts(NSMutableDictionary*, id, int); // expe
|
||||||
|
|
||||||
template<typename T, typename U, typename O>
|
template<typename T, typename U, typename O>
|
||||||
void test_array_subscripts(T base, U index, O obj) {
|
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 *'}}
|
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 {{expected method to read dictionary element not found on object of type 'NSMutableArray *'}}
|
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);
|
template void test_array_subscripts(NSMutableArray *, int, id);
|
||||||
|
|
Loading…
Reference in New Issue