[cfe-commits] r125445 - in /cfe/trunk: include/clang/Sema/Overload.h include/clang/Sema/Sema.h lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp test/CodeGenObjCXX/blocks.mm test/SemaCXX/block-call.cpp test/SemaObjCXX/blocks.mm
Douglas Gregor
dgregor at apple.com
Sun Feb 13 09:56:16 PST 2011
On Feb 12, 2011, at 11:07 AM, Fariborz Jahanian wrote:
> Author: fjahanian
> Date: Sat Feb 12 13:07:46 2011
> New Revision: 125445
>
> URL: http://llvm.org/viewvc/llvm-project?rev=125445&view=rev
> Log:
> Implement objective-c++'s block pointer type matching involving
> types which are contravariance in argument types and covariance
> in return types. // rdar://8979379.
Very nice! A few comments inline.
> Added:
> cfe/trunk/test/CodeGenObjCXX/blocks.mm
> cfe/trunk/test/SemaCXX/block-call.cpp
> Modified:
> cfe/trunk/include/clang/Sema/Overload.h
> cfe/trunk/include/clang/Sema/Sema.h
> cfe/trunk/lib/Sema/SemaExprCXX.cpp
> cfe/trunk/lib/Sema/SemaOverload.cpp
> cfe/trunk/test/SemaObjCXX/blocks.mm
>
> Modified: cfe/trunk/include/clang/Sema/Overload.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Overload.h?rev=125445&r1=125444&r2=125445&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Overload.h (original)
> +++ cfe/trunk/include/clang/Sema/Overload.h Sat Feb 12 13:07:46 2011
> @@ -75,6 +75,7 @@
> ICK_Vector_Conversion, ///< Vector conversions
> ICK_Vector_Splat, ///< A vector splat from an arithmetic type
> ICK_Complex_Real, ///< Complex-real conversions (C99 6.3.1.7)
> + ICK_Block_Pointer_Conversion, ///< Block Pointer conversions
> ICK_Num_Conversion_Kinds ///< The number of conversion kinds
> };
>
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=125445&r1=125444&r2=125445&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Sat Feb 12 13:07:46 2011
> @@ -1019,6 +1019,8 @@
> QualType& ConvertedType, bool &IncompatibleObjC);
> bool isObjCPointerConversion(QualType FromType, QualType ToType,
> QualType& ConvertedType, bool &IncompatibleObjC);
> + bool IsBlockPointerConversion(QualType FromType, QualType ToType,
> + QualType& ConvertedType);
> bool FunctionArgTypesAreEqual(const FunctionProtoType *OldType,
> const FunctionProtoType *NewType);
>
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=125445&r1=125444&r2=125445&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sat Feb 12 13:07:46 2011
> @@ -2199,7 +2199,12 @@
> }
> }
> break;
> -
> +
> + case ICK_Block_Pointer_Conversion: {
> + ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast, VK_RValue);
> + break;
> + }
> +
> case ICK_Lvalue_To_Rvalue:
> case ICK_Array_To_Pointer:
> case ICK_Function_To_Pointer:
>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=125445&r1=125444&r2=125445&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Sat Feb 12 13:07:46 2011
> @@ -1166,6 +1166,8 @@
> // 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 @@
> 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;
The getTypeQuals() check isn't necessary, since block pointers can't have qualifiers on the function type itself.
> + 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();
FWIW, you don't actually have to operate on the canonical types here; hasQualifiers() and getUnqualifiedType() do the right thing on non-canonical types, too.
Also, due to attribute overloadable, we can actually end up here in C code... so the !CanRHS->isRecordType() check should be (!getLangOptions().CPlusPlus || !CanRHS->isRecordType()).
> + if (Context.getCanonicalType(CanRHS)
> + == Context.getCanonicalType(CanLHS)) {
> + // OK exact match.
Context.hasSameType() is often easier to read (and works on non-canonical types).
> + // 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.
Same comment about Context.hasSameType() here.
- Doug
More information about the cfe-commits
mailing list