[cfe-commits] r156719 - in /cfe/trunk: lib/Sema/SemaExprObjC.cpp test/SemaObjC/objc-literal-sig.m
Jordy Rose
jediknil at belkadan.com
Sat May 12 10:32:56 PDT 2012
Author: jrose
Date: Sat May 12 12:32:56 2012
New Revision: 156719
URL: http://llvm.org/viewvc/llvm-project?rev=156719&view=rev
Log:
Only check NSArray/NSDictionary boxing method params once.
Once we've found a "good" method, we don't need to check its argument types
again. (Even if we might have later found a "bad" method, we were already
caching the method we first looked up.)
Modified:
cfe/trunk/lib/Sema/SemaExprObjC.cpp
cfe/trunk/test/SemaObjC/objc-literal-sig.m
Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=156719&r1=156718&r2=156719&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Sat May 12 12:32:56 2012
@@ -655,35 +655,38 @@
if (!validateBoxingMethod(*this, SR.getBegin(), NSArrayDecl, Sel, Method))
return ExprError();
+ // Dig out the type that all elements should be converted to.
+ QualType T = Method->param_begin()[0]->getType();
+ const PointerType *PtrT = T->getAs<PointerType>();
+ if (!PtrT ||
+ !Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) {
+ Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
+ << Sel;
+ Diag(Method->param_begin()[0]->getLocation(),
+ diag::note_objc_literal_method_param)
+ << 0 << T
+ << Context.getPointerType(IdT.withConst());
+ return ExprError();
+ }
+
+ // Check that the 'count' parameter is integral.
+ if (!Method->param_begin()[1]->getType()->isIntegerType()) {
+ Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
+ << Sel;
+ Diag(Method->param_begin()[1]->getLocation(),
+ diag::note_objc_literal_method_param)
+ << 1
+ << Method->param_begin()[1]->getType()
+ << "integral";
+ return ExprError();
+ }
+
+ // We've found a good +arrayWithObjects:count: method. Save it!
ArrayWithObjectsMethod = Method;
}
- // Dig out the type that all elements should be converted to.
- QualType T = ArrayWithObjectsMethod->param_begin()[0]->getType();
- const PointerType *PtrT = T->getAs<PointerType>();
- if (!PtrT ||
- !Context.hasSameUnqualifiedType(PtrT->getPointeeType(), IdT)) {
- Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
- << ArrayWithObjectsMethod->getSelector();
- Diag(ArrayWithObjectsMethod->param_begin()[0]->getLocation(),
- diag::note_objc_literal_method_param)
- << 0 << T
- << Context.getPointerType(IdT.withConst());
- return ExprError();
- }
- T = PtrT->getPointeeType();
-
- // Check that the 'count' parameter is integral.
- if (!ArrayWithObjectsMethod->param_begin()[1]->getType()->isIntegerType()) {
- Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
- << ArrayWithObjectsMethod->getSelector();
- Diag(ArrayWithObjectsMethod->param_begin()[1]->getLocation(),
- diag::note_objc_literal_method_param)
- << 1
- << ArrayWithObjectsMethod->param_begin()[1]->getType()
- << "integral";
- return ExprError();
- }
+ QualType ObjectsType = ArrayWithObjectsMethod->param_begin()[0]->getType();
+ QualType RequiredType = ObjectsType->castAs<PointerType>()->getPointeeType();
// Check that each of the elements provided is valid in a collection literal,
// performing conversions as necessary.
@@ -691,7 +694,7 @@
for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
ExprResult Converted = CheckObjCCollectionLiteralElement(*this,
ElementsBuffer[I],
- T);
+ RequiredType);
if (Converted.isInvalid())
return ExprError();
@@ -781,73 +784,76 @@
Method))
return ExprError();
- DictionaryWithObjectsMethod = Method;
- }
-
- // Dig out the type that all values should be converted to.
- QualType ValueT = DictionaryWithObjectsMethod->param_begin()[0]->getType();
- const PointerType *PtrValue = ValueT->getAs<PointerType>();
- if (!PtrValue ||
- !Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) {
- Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
- << DictionaryWithObjectsMethod->getSelector();
- Diag(DictionaryWithObjectsMethod->param_begin()[0]->getLocation(),
- diag::note_objc_literal_method_param)
- << 0 << ValueT
- << Context.getPointerType(IdT.withConst());
- return ExprError();
- }
- ValueT = PtrValue->getPointeeType();
+ // Dig out the type that all values should be converted to.
+ QualType ValueT = Method->param_begin()[0]->getType();
+ const PointerType *PtrValue = ValueT->getAs<PointerType>();
+ if (!PtrValue ||
+ !Context.hasSameUnqualifiedType(PtrValue->getPointeeType(), IdT)) {
+ Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
+ << Sel;
+ Diag(Method->param_begin()[0]->getLocation(),
+ diag::note_objc_literal_method_param)
+ << 0 << ValueT
+ << Context.getPointerType(IdT.withConst());
+ return ExprError();
+ }
- // Dig out the type that all keys should be converted to.
- QualType KeyT = DictionaryWithObjectsMethod->param_begin()[1]->getType();
- const PointerType *PtrKey = KeyT->getAs<PointerType>();
- if (!PtrKey ||
- !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
- IdT)) {
- bool err = true;
- if (PtrKey) {
- if (QIDNSCopying.isNull()) {
- // key argument of selector is id<NSCopying>?
- if (ObjCProtocolDecl *NSCopyingPDecl =
- LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) {
- ObjCProtocolDecl *PQ[] = {NSCopyingPDecl};
- QIDNSCopying =
- Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
- (ObjCProtocolDecl**) PQ,1);
- QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying);
+ // Dig out the type that all keys should be converted to.
+ QualType KeyT = Method->param_begin()[1]->getType();
+ const PointerType *PtrKey = KeyT->getAs<PointerType>();
+ if (!PtrKey ||
+ !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
+ IdT)) {
+ bool err = true;
+ if (PtrKey) {
+ if (QIDNSCopying.isNull()) {
+ // key argument of selector is id<NSCopying>?
+ if (ObjCProtocolDecl *NSCopyingPDecl =
+ LookupProtocol(&Context.Idents.get("NSCopying"), SR.getBegin())) {
+ ObjCProtocolDecl *PQ[] = {NSCopyingPDecl};
+ QIDNSCopying =
+ Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
+ (ObjCProtocolDecl**) PQ,1);
+ QIDNSCopying = Context.getObjCObjectPointerType(QIDNSCopying);
+ }
}
+ if (!QIDNSCopying.isNull())
+ err = !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
+ QIDNSCopying);
}
- if (!QIDNSCopying.isNull())
- err = !Context.hasSameUnqualifiedType(PtrKey->getPointeeType(),
- QIDNSCopying);
- }
- if (err) {
+ if (err) {
+ Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
+ << Sel;
+ Diag(Method->param_begin()[1]->getLocation(),
+ diag::note_objc_literal_method_param)
+ << 1 << KeyT
+ << Context.getPointerType(IdT.withConst());
+ return ExprError();
+ }
+ }
+
+ // Check that the 'count' parameter is integral.
+ QualType CountType = Method->param_begin()[2]->getType();
+ if (!CountType->isIntegerType()) {
Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
- << DictionaryWithObjectsMethod->getSelector();
- Diag(DictionaryWithObjectsMethod->param_begin()[1]->getLocation(),
+ << Sel;
+ Diag(Method->param_begin()[2]->getLocation(),
diag::note_objc_literal_method_param)
- << 1 << KeyT
- << Context.getPointerType(IdT.withConst());
+ << 2 << CountType
+ << "integral";
return ExprError();
}
- }
- KeyT = PtrKey->getPointeeType();
- // Check that the 'count' parameter is integral.
- if (!DictionaryWithObjectsMethod->param_begin()[2]->getType()
- ->isIntegerType()) {
- Diag(SR.getBegin(), diag::err_objc_literal_method_sig)
- << DictionaryWithObjectsMethod->getSelector();
- Diag(DictionaryWithObjectsMethod->param_begin()[2]->getLocation(),
- diag::note_objc_literal_method_param)
- << 2
- << DictionaryWithObjectsMethod->param_begin()[2]->getType()
- << "integral";
- return ExprError();
+ // We've found a good +dictionaryWithObjects:keys:count: method; save it!
+ DictionaryWithObjectsMethod = Method;
}
+ QualType ValuesT = DictionaryWithObjectsMethod->param_begin()[0]->getType();
+ QualType ValueT = ValuesT->castAs<PointerType>()->getPointeeType();
+ QualType KeysT = DictionaryWithObjectsMethod->param_begin()[1]->getType();
+ QualType KeyT = KeysT->castAs<PointerType>()->getPointeeType();
+
// Check that each of the keys and values provided is valid in a collection
// literal, performing conversions as necessary.
bool HasPackExpansions = false;
Modified: cfe/trunk/test/SemaObjC/objc-literal-sig.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objc-literal-sig.m?rev=156719&r1=156718&r2=156719&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/objc-literal-sig.m (original)
+++ cfe/trunk/test/SemaObjC/objc-literal-sig.m Sat May 12 12:32:56 2012
@@ -16,30 +16,36 @@
+ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
+ (NSNumber *)numberWithFloat:(float)value;
+ (NSNumber *)numberWithDouble:(double)value;
-+ (int)numberWithBool:(BOOL)value; // expected-note{{method returns unexpected type 'int' (should be an object type)}}
++ (int)numberWithBool:(BOOL)value; // expected-note 2 {{method returns unexpected type 'int' (should be an object type)}}
@end
@interface NSString
-+ (char)stringWithUTF8String:(const char *)value; // expected-note{{method returns unexpected type 'char' (should be an object type)}}
++ (char)stringWithUTF8String:(const char *)value; // expected-note 2 {{method returns unexpected type 'char' (should be an object type)}}
@end
@interface NSArray
@end
@interface NSArray (NSArrayCreation)
-+ (id)arrayWithObjects:(const int [])objects // expected-note{{first parameter has unexpected type 'const int *' (should be 'const id *')}}
++ (id)arrayWithObjects:(const int [])objects // expected-note 2 {{first parameter has unexpected type 'const int *' (should be 'const id *')}}
count:(unsigned long)cnt;
@end
@interface NSDictionary
+ (id)dictionaryWithObjects:(const id [])objects
- forKeys:(const int [])keys // expected-note{{second parameter has unexpected type 'const int *' (should be 'const id *')}}
+ forKeys:(const int [])keys // expected-note 2 {{second parameter has unexpected type 'const int *' (should be 'const id *')}}
count:(unsigned long)cnt;
@end
+// All tests are doubled to make sure that a bad method is not saved
+// and then used un-checked.
void test_sig() {
(void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
+ (void)@__objc_yes; // expected-error{{literal construction method 'numberWithBool:' has incompatible signature}}
id array = @[ @17 ]; // expected-error{{literal construction method 'arrayWithObjects:count:' has incompatible signature}}
+ id array2 = @[ @17 ]; // expected-error{{literal construction method 'arrayWithObjects:count:' has incompatible signature}}
id dict = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
+ id dict2 = @{ @"hello" : @17 }; // expected-error{{literal construction method 'dictionaryWithObjects:forKeys:count:' has incompatible signature}}
id str = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
+ id str2 = @("hello"); // expected-error{{literal construction method 'stringWithUTF8String:' has incompatible signature}}
}
More information about the cfe-commits
mailing list