diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index fe64946e14..0bef27c726 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -433,6 +433,21 @@ static bool DeduceTemplateArguments(ASTContext &Context, QualType Param, Deduced); } + // type(^)(T) + // T(^)() + // T(^)(T) + case Type::BlockPointer: { + const BlockPointerType *BlockPtrParam = cast(Param); + const BlockPointerType *BlockPtrArg = dyn_cast(Arg); + + if (!BlockPtrArg) + return false; + + return DeduceTemplateArguments(Context, + BlockPtrParam->getPointeeType(), + BlockPtrArg->getPointeeType(), Deduced); + } + case Type::TypeOfExpr: case Type::TypeOf: case Type::Typename: diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 964d3b1485..a7fdb59a20 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -274,9 +274,13 @@ TemplateTypeInstantiator::InstantiatePointerType(const PointerType *T, QualType TemplateTypeInstantiator::InstantiateBlockPointerType(const BlockPointerType *T, unsigned Quals) const { - // FIXME: Implement this - assert(false && "Cannot instantiate BlockPointerType yet"); - return QualType(); + QualType PointeeType = Instantiate(T->getPointeeType()); + if (PointeeType.isNull()) + return QualType(); + + QualType BlockTy = SemaRef.Context.getBlockPointerType(PointeeType); + + return BlockTy.getQualifiedType(Quals); } QualType diff --git a/test/SemaTemplate/temp_class_spec_blocks.cpp b/test/SemaTemplate/temp_class_spec_blocks.cpp new file mode 100644 index 0000000000..920d9c8b0c --- /dev/null +++ b/test/SemaTemplate/temp_class_spec_blocks.cpp @@ -0,0 +1,34 @@ +// RUN: clang-cc -fsyntax-only -verify %s -fblocks +template +struct is_unary_block { + static const bool value = false; +}; + +template +struct is_unary_block { + static const bool value = true; +}; + +int is_unary_block0[is_unary_block::value ? -1 : 1]; +int is_unary_block1[is_unary_block::value ? -1 : 1]; +int is_unary_block2[is_unary_block::value ? -1 : 1]; +int is_unary_block3[is_unary_block::value ? 1 : -1]; +int is_unary_block4[is_unary_block::value ? 1 : -1]; + +template +struct is_unary_block_with_same_return_type_as_argument_type { + static const bool value = false; +}; + +template +struct is_unary_block_with_same_return_type_as_argument_type { + static const bool value = true; +}; + +int is_unary_block5[is_unary_block_with_same_return_type_as_argument_type::value ? -1 : 1]; +int is_unary_block6[is_unary_block_with_same_return_type_as_argument_type::value ? -1 : 1]; +int is_unary_block7[is_unary_block_with_same_return_type_as_argument_type::value ? -1 : 1]; +int is_unary_block8[is_unary_block_with_same_return_type_as_argument_type::value ? -1 : 1]; +int is_unary_block9[is_unary_block_with_same_return_type_as_argument_type::value ? 1 : -1]; +int is_unary_block10[is_unary_block_with_same_return_type_as_argument_type::value ? -1 : 1]; +int is_unary_block11[is_unary_block_with_same_return_type_as_argument_type::value ? -1 : 1];