Home | History | Annotate | Download | only in SemaObjC
      1 // RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only -verify -fblocks %s
      2 
      3 #define bool _Bool
      4 @protocol NSObject;
      5 
      6 void bar(id(^)(void));
      7 void foo(id <NSObject>(^objectCreationBlock)(void)) {
      8     return bar(objectCreationBlock);
      9 }
     10 
     11 void bar2(id(*)(void));
     12 void foo2(id <NSObject>(*objectCreationBlock)(void)) {
     13     return bar2(objectCreationBlock);
     14 }
     15 
     16 void bar3(id(*)());
     17 void foo3(id (*objectCreationBlock)(int)) {
     18     return bar3(objectCreationBlock);
     19 }
     20 
     21 void bar4(id(^)());
     22 void foo4(id (^objectCreationBlock)(int)) {
     23     return bar4(objectCreationBlock);
     24 }
     25 
     26 void bar5(id(^)(void)); // expected-note 3{{passing argument to parameter here}}
     27 void foo5(id (^objectCreationBlock)(bool)) {
     28     bar5(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)(bool)' to parameter of type 'id (^)(void)'}}
     29 #undef bool
     30     bar5(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)(_Bool)' to parameter of type 'id (^)(void)'}}
     31 #define bool int
     32     bar5(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)(_Bool)' to parameter of type 'id (^)(void)'}}
     33 }
     34 
     35 void bar6(id(^)(int));
     36 void foo6(id (^objectCreationBlock)()) {
     37     return bar6(objectCreationBlock);
     38 }
     39 
     40 void foo7(id (^x)(int)) {
     41   if (x) { }
     42 }
     43 
     44 @interface itf
     45 @end
     46 
     47 void foo8() {
     48   void *P = ^(itf x) {};  // expected-error {{interface type 'itf' cannot be passed by value; did you forget * in 'itf'}}
     49   P = ^itf(int x) {};     // expected-error {{interface type 'itf' cannot be returned by value; did you forget * in 'itf'}}
     50   P = ^itf() {};          // expected-error {{interface type 'itf' cannot be returned by value; did you forget * in 'itf'}}
     51   P = ^itf{};             // expected-error {{interface type 'itf' cannot be returned by value; did you forget * in 'itf'}}
     52 }
     53 
     54 
     55 int foo9() {
     56   typedef void (^DVTOperationGroupScheduler)();
     57   id _suboperationSchedulers;
     58 
     59   for (DVTOperationGroupScheduler scheduler in _suboperationSchedulers) {
     60             ;
     61         }
     62 
     63 }
     64 
     65 // rdar 7725203
     66 @class NSString;
     67 
     68 extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
     69 
     70 void foo10() {
     71     void(^myBlock)(void) = ^{
     72     };
     73     NSLog(@"%@", myBlock);
     74 }
     75 
     76 
     77 // In C, enum constants have the type of the underlying integer type, not the
     78 // enumeration they are part of. We pretend the constants have enum type if
     79 // all the returns seem to be playing along.
     80 enum CStyleEnum {
     81   CSE_Value = 1,
     82   CSE_Value2 = 2
     83 };
     84 enum CStyleEnum getCSE();
     85 typedef enum CStyleEnum (^cse_block_t)();
     86 
     87 void testCStyleEnumInference(bool arg) {
     88   cse_block_t a;
     89   enum CStyleEnum value;
     90 
     91   // No warnings here.
     92   a = ^{ return getCSE(); };
     93   a = ^{ return value; };
     94 
     95   a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
     96     return 1;
     97   };
     98 
     99   // No warning here.
    100   a = ^{
    101     return CSE_Value;
    102   };
    103 
    104   // No warnings here.
    105   a = ^{ if (arg) return CSE_Value; else return getCSE();  };
    106   a = ^{ if (arg) return getCSE();  else return CSE_Value; };
    107   a = ^{ if (arg) return value;     else return CSE_Value; };
    108 
    109   // These two blocks actually return 'int'
    110   a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
    111     if (arg)
    112       return 1;
    113     else
    114       return CSE_Value;
    115   };
    116 
    117   a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
    118     if (arg)
    119       return CSE_Value;
    120     else
    121       return 1;
    122   };
    123 
    124   a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
    125     if (arg)
    126       return 1;
    127     else
    128       return value; // expected-error {{return type 'enum CStyleEnum' must match previous return type 'int'}}
    129   };
    130 
    131   // rdar://13200889
    132   extern void check_enum(void);
    133   a = ^{
    134     return (arg ? (CSE_Value) : (check_enum(), (!arg ? CSE_Value2 : getCSE())));
    135   };
    136   a = ^{
    137     return (arg ? (CSE_Value) : ({check_enum(); CSE_Value2; }));
    138   };
    139 }
    140 
    141 
    142 enum FixedTypeEnum : unsigned {
    143   FTE_Value = 1U
    144 };
    145 enum FixedTypeEnum getFTE();
    146 typedef enum FixedTypeEnum (^fte_block_t)();
    147 
    148 void testFixedTypeEnumInference(bool arg) {
    149   fte_block_t a;
    150   
    151   // No warnings here.
    152   a = ^{ return getFTE(); };
    153 
    154   // Since we fixed the underlying type of the enum, this is considered a
    155   // compatible block type.
    156   a = ^{
    157     return 1U;
    158   };
    159   a = ^{
    160     return FTE_Value;
    161   };
    162 
    163   // No warnings here.
    164   a = ^{ if (arg) return FTE_Value; else return FTE_Value; };
    165   a = ^{ if (arg) return getFTE();  else return getFTE();  };
    166   a = ^{ if (arg) return FTE_Value; else return getFTE();  };
    167   a = ^{ if (arg) return getFTE();  else return FTE_Value; };
    168   
    169   // These two blocks actually return 'unsigned'.
    170   a = ^{
    171     if (arg)
    172       return 1U;
    173     else
    174       return FTE_Value;
    175   };
    176   
    177   a = ^{
    178     if (arg)
    179       return FTE_Value;
    180     else
    181       return 1U;
    182   };
    183 }
    184 
    185 
    186 enum {
    187   AnonymousValue = 1
    188 };
    189 
    190 enum : short {
    191   FixedAnonymousValue = 1
    192 };
    193 
    194 typedef enum {
    195   TDE_Value
    196 } TypeDefEnum;
    197 TypeDefEnum getTDE();
    198 
    199 typedef enum : short {
    200   TDFTE_Value
    201 } TypeDefFixedTypeEnum;
    202 TypeDefFixedTypeEnum getTDFTE();
    203 
    204 typedef int (^int_block_t)();
    205 typedef short (^short_block_t)();
    206 void testAnonymousEnumTypes(int arg) {
    207   int_block_t IB;
    208   IB = ^{ return AnonymousValue; };
    209   IB = ^{ if (arg) return TDE_Value; else return getTDE(); };
    210   IB = ^{ if (arg) return getTDE(); else return TDE_Value; };
    211 
    212   // Since we fixed the underlying type of the enum, these are considered
    213   // compatible block types anyway.
    214   short_block_t SB;
    215   SB = ^{ return FixedAnonymousValue; };
    216   SB = ^{ if (arg) return TDFTE_Value; else return getTDFTE(); };
    217   SB = ^{ if (arg) return getTDFTE(); else return TDFTE_Value; };
    218 }
    219 
    220 static inline void inlinefunc() {
    221   ^{}();
    222 }
    223 void inlinefunccaller() { inlinefunc(); }
    224