Add some block-pointer conversions in C++

llvm-svn: 61359
This commit is contained in:
Douglas Gregor 2008-12-23 00:53:59 +00:00
parent 164274eeb1
commit 033f56d533
3 changed files with 50 additions and 11 deletions

View File

@ -135,7 +135,7 @@ bool StandardConversionSequence::isPointerConversionToBool() const
// check for their presence as well as checking whether FromType is
// a pointer.
if (ToType->isBooleanType() &&
(FromType->isPointerType() ||
(FromType->isPointerType() || FromType->isBlockPointerType() ||
First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer))
return true;
@ -547,7 +547,8 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
else if (ToType->isBooleanType() &&
(FromType->isArithmeticType() ||
FromType->isEnumeralType() ||
FromType->isPointerType())) {
FromType->isPointerType() ||
FromType->isBlockPointerType())) {
SCS.Second = ICK_Boolean_Conversion;
FromType = Context.BoolTy;
} else {
@ -857,25 +858,33 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
return true;
}
// Beyond this point, both types need to be pointers or block pointers.
QualType ToPointeeType;
const PointerType* ToTypePtr = ToType->getAsPointerType();
if (!ToTypePtr)
if (ToTypePtr)
ToPointeeType = ToTypePtr->getPointeeType();
else if (const BlockPointerType *ToBlockPtr = ToType->getAsBlockPointerType())
ToPointeeType = ToBlockPtr->getPointeeType();
else
return false;
// Beyond this point, both types need to be pointers.
QualType FromPointeeType;
const PointerType *FromTypePtr = FromType->getAsPointerType();
if (!FromTypePtr)
if (FromTypePtr)
FromPointeeType = FromTypePtr->getPointeeType();
else if (const BlockPointerType *FromBlockPtr
= FromType->getAsBlockPointerType())
FromPointeeType = FromBlockPtr->getPointeeType();
else
return false;
QualType FromPointeeType = FromTypePtr->getPointeeType();
QualType ToPointeeType = ToTypePtr->getPointeeType();
// Objective C++: We're able to convert from a pointer to an
// interface to a pointer to a different interface.
const ObjCInterfaceType* FromIface = FromPointeeType->getAsObjCInterfaceType();
const ObjCInterfaceType* ToIface = ToPointeeType->getAsObjCInterfaceType();
if (FromIface && ToIface &&
Context.canAssignObjCInterfaces(ToIface, FromIface)) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
ToType, Context);
return true;
@ -887,7 +896,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
// interfaces, which is permitted. However, we're going to
// complain about it.
IncompatibleObjC = true;
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
ToType, Context);
return true;
@ -924,7 +933,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
return true;
}
// If we have pointers to functions, check whether the only
// If we have pointers to functions or blocks, check whether the only
// differences in the argument and result types are in Objective-C
// pointer conversions. If so, we permit the conversion (but
// complain about it).

View File

@ -20,3 +20,7 @@ void bar4(id(^)());
void foo4(id (^objectCreationBlock)(int)) {
return bar4(objectCreationBlock); // expected-warning{{incompatible block pointer types passing 'id (^)(int)', expected 'id (^)()'}}
}
void foo5(id (^x)(int)) {
if (x) { }
}

View File

@ -0,0 +1,26 @@
// RUN: clang -fsyntax-only -verify -fblocks %s
@protocol NSObject;
void bar(id(^)(void));
void foo(id <NSObject>(^objectCreationBlock)(void)) {
return bar(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (^)(void)', expected 'id<NSObject> (^)(void)'}}
}
void bar2(id(*)(void));
void foo2(id <NSObject>(*objectCreationBlock)(void)) {
return bar2(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (*)(void)', expected 'id<NSObject> (*)(void)'}}
}
void bar3(id(*)());
void foo3(id (*objectCreationBlock)(int)) {
return bar3(objectCreationBlock); // expected-error{{incompatible type passing 'id (*)(int)', expected 'id (*)(void)'}}
}
void bar4(id(^)());
void foo4(id (^objectCreationBlock)(int)) {
return bar4(objectCreationBlock); // expected-error{{incompatible type passing 'id (^)(int)', expected 'id (^)(void)'}}
}
void foo5(id (^x)(int)) {
if (x) { }
}