// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s #define bool _Bool @protocol NSObject; void bar(id(^)(void)); void foo(id (^objectCreationBlock)(void)) { return bar(objectCreationBlock); } void bar2(id(*)(void)); void foo2(id (*objectCreationBlock)(void)) { return bar2(objectCreationBlock); } void bar3(id(*)()); void foo3(id (*objectCreationBlock)(int)) { return bar3(objectCreationBlock); } void bar4(id(^)()); void foo4(id (^objectCreationBlock)(int)) { return bar4(objectCreationBlock); } void bar5(id(^)(void)); // expected-note 3{{passing argument to parameter here}} void foo5(id (^objectCreationBlock)(bool)) { bar5(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)(bool)' to parameter of type 'id (^)(void)'}} #undef bool bar5(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)(_Bool)' to parameter of type 'id (^)(void)'}} #define bool int bar5(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)(_Bool)' to parameter of type 'id (^)(void)'}} } void bar6(id(^)(int)); void foo6(id (^objectCreationBlock)()) { return bar6(objectCreationBlock); } void foo7(id (^x)(int)) { if (x) { } } @interface itf @end void foo8() { void *P = ^(itf x) {}; // expected-error {{interface type 'itf' cannot be passed by value; did you forget * in 'itf'}} P = ^itf(int x) {}; // expected-error {{interface type 'itf' cannot be returned by value; did you forget * in 'itf'}} P = ^itf() {}; // expected-error {{interface type 'itf' cannot be returned by value; did you forget * in 'itf'}} P = ^itf{}; // expected-error {{interface type 'itf' cannot be returned by value; did you forget * in 'itf'}} } int foo9() { typedef void (^DVTOperationGroupScheduler)(); id _suboperationSchedulers; for (DVTOperationGroupScheduler scheduler in _suboperationSchedulers) { ; } } // rdar 7725203 @class NSString; extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); void foo10() { void(^myBlock)(void) = ^{ }; NSLog(@"%@", myBlock); } // In C, enum constants have the type of the underlying integer type, not the // enumeration they are part of. We pretend the constants have enum type if // all the returns seem to be playing along. enum CStyleEnum { CSE_Value = 1, CSE_Value2 = 2 }; enum CStyleEnum getCSE(); typedef enum CStyleEnum (^cse_block_t)(); void testCStyleEnumInference(bool arg) { cse_block_t a; enum CStyleEnum value; // No warnings here. a = ^{ return getCSE(); }; a = ^{ return value; }; a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}} return 1; }; // No warning here. a = ^{ return CSE_Value; }; // No warnings here. a = ^{ if (arg) return CSE_Value; else return getCSE(); }; a = ^{ if (arg) return getCSE(); else return CSE_Value; }; a = ^{ if (arg) return value; else return CSE_Value; }; // These two blocks actually return 'int' a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}} if (arg) return 1; else return CSE_Value; }; a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}} if (arg) return CSE_Value; else return 1; }; a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}} if (arg) return 1; else return value; // expected-error {{return type 'enum CStyleEnum' must match previous return type 'int'}} }; // rdar://13200889 extern void check_enum(void); a = ^{ return (arg ? (CSE_Value) : (check_enum(), (!arg ? CSE_Value2 : getCSE()))); }; a = ^{ return (arg ? (CSE_Value) : ({check_enum(); CSE_Value2; })); }; } enum FixedTypeEnum : unsigned { FTE_Value = 1U }; enum FixedTypeEnum getFTE(); typedef enum FixedTypeEnum (^fte_block_t)(); void testFixedTypeEnumInference(bool arg) { fte_block_t a; // No warnings here. a = ^{ return getFTE(); }; // Since we fixed the underlying type of the enum, this is considered a // compatible block type. a = ^{ return 1U; }; a = ^{ return FTE_Value; }; // No warnings here. a = ^{ if (arg) return FTE_Value; else return FTE_Value; }; a = ^{ if (arg) return getFTE(); else return getFTE(); }; a = ^{ if (arg) return FTE_Value; else return getFTE(); }; a = ^{ if (arg) return getFTE(); else return FTE_Value; }; // These two blocks actually return 'unsigned'. a = ^{ if (arg) return 1U; else return FTE_Value; }; a = ^{ if (arg) return FTE_Value; else return 1U; }; } enum { AnonymousValue = 1 }; enum : short { FixedAnonymousValue = 1 }; typedef enum { TDE_Value } TypeDefEnum; TypeDefEnum getTDE(); typedef enum : short { TDFTE_Value } TypeDefFixedTypeEnum; TypeDefFixedTypeEnum getTDFTE(); typedef int (^int_block_t)(); typedef short (^short_block_t)(); void testAnonymousEnumTypes(int arg) { int_block_t IB; IB = ^{ return AnonymousValue; }; IB = ^{ if (arg) return TDE_Value; else return getTDE(); }; IB = ^{ if (arg) return getTDE(); else return TDE_Value; }; // Since we fixed the underlying type of the enum, these are considered // compatible block types anyway. short_block_t SB; SB = ^{ return FixedAnonymousValue; }; SB = ^{ if (arg) return TDFTE_Value; else return getTDFTE(); }; SB = ^{ if (arg) return getTDFTE(); else return TDFTE_Value; }; } static inline void inlinefunc() { ^{}(); } void inlinefunccaller() { inlinefunc(); }