|  | // RUN: %clang_cc1 -triple %itanium_abi_triple -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; | 
|  | 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(); } |