| // RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s |
| |
| #define bool _Bool |
| @protocol NSObject; |
| |
| void bar(id(^)(void)); |
| void foo(id <NSObject>(^objectCreationBlock)(void)) { |
| return bar(objectCreationBlock); |
| } |
| |
| void bar2(id(*)(void)); |
| void foo2(id <NSObject>(*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; |
| |
| // No warnings here. |
| a = ^{ return getCSE(); }; |
| |
| 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; }; |
| |
| // 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; |
| }; |
| |
| // 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(); }; // expected-error {{incompatible block pointer}} |
| IB = ^{ if (arg) return getTDE(); else return TDE_Value; }; // expected-error {{incompatible block pointer}} |
| |
| // 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; }; |
| } |