diff options
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 42e24116bf..70cc566059 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1166,6 +1166,8 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // Floating-integral conversions (C++ 4.9). SCS.Second = ICK_Floating_Integral; FromType = ToType.getUnqualifiedType(); + } else if (S.IsBlockPointerConversion(FromType, ToType, FromType)) { + SCS.Second = ICK_Block_Pointer_Conversion; } else if (S.IsPointerConversion(From, FromType, ToType, InOverloadResolution, FromType, IncompatibleObjC)) { // Pointer conversions (C++ 4.10). @@ -1782,6 +1784,92 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, return false; } +bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType, + QualType& ConvertedType) { + QualType ToPointeeType; + if (const BlockPointerType *ToBlockPtr = + ToType->getAs<BlockPointerType>()) + ToPointeeType = ToBlockPtr->getPointeeType(); + else + return false; + + QualType FromPointeeType; + if (const BlockPointerType *FromBlockPtr = + FromType->getAs<BlockPointerType>()) + FromPointeeType = FromBlockPtr->getPointeeType(); + else + return false; + // We have pointer to blocks, check whether the only + // differences in the argument and result types are in Objective-C + // pointer conversions. If so, we permit the conversion. + + const FunctionProtoType *FromFunctionType + = FromPointeeType->getAs<FunctionProtoType>(); + const FunctionProtoType *ToFunctionType + = ToPointeeType->getAs<FunctionProtoType>(); + + if (FromFunctionType && ToFunctionType) { + if (Context.getCanonicalType(FromPointeeType) + == Context.getCanonicalType(ToPointeeType)) + return true; + + // Perform the quick checks that will tell us whether these + // function types are obviously different. + if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() || + FromFunctionType->isVariadic() != ToFunctionType->isVariadic() || + FromFunctionType->getTypeQuals() != ToFunctionType->getTypeQuals()) + return false; + + bool IncompatibleObjC = false; + if (Context.getCanonicalType(FromFunctionType->getResultType()) + == Context.getCanonicalType(ToFunctionType->getResultType())) { + // Okay, the types match exactly. Nothing to do. + } else { + QualType RHS = FromFunctionType->getResultType(); + QualType CanRHS = Context.getCanonicalType(RHS); + QualType LHS = ToFunctionType->getResultType(); + QualType CanLHS = Context.getCanonicalType(LHS); + if (!CanRHS->isRecordType() && + !CanRHS.hasQualifiers() && CanLHS.hasQualifiers()) + CanLHS = CanLHS.getUnqualifiedType(); + + if (Context.getCanonicalType(CanRHS) + == Context.getCanonicalType(CanLHS)) { + // OK exact match. + } else if (isObjCPointerConversion(CanRHS, CanLHS, + ConvertedType, IncompatibleObjC)) { + if (IncompatibleObjC) + return false; + // Okay, we have an Objective-C pointer conversion. + } + else + return false; + } + + // Check argument types. + for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs(); + ArgIdx != NumArgs; ++ArgIdx) { + IncompatibleObjC = false; + QualType FromArgType = FromFunctionType->getArgType(ArgIdx); + QualType ToArgType = ToFunctionType->getArgType(ArgIdx); + if (Context.getCanonicalType(FromArgType) + == Context.getCanonicalType(ToArgType)) { + // Okay, the types match exactly. Nothing to do. + } else if (isObjCPointerConversion(ToArgType, FromArgType, + ConvertedType, IncompatibleObjC)) { + if (IncompatibleObjC) + return false; + // Okay, we have an Objective-C pointer conversion. + } else + // Argument types are too different. Abort. + return false; + } + ConvertedType = ToType; + return true; + } + return false; +} + /// FunctionArgTypesAreEqual - This routine checks two function proto types /// for equlity of their argument types. Caller has already checked that /// they have same number of arguments. This routine assumes that Objective-C |