f4a2713ac8
Change-Id: Ia40e9ffdf29b5dab2f122f673ff6802a58bc690f
223 lines
5.8 KiB
Objective-C
223 lines
5.8 KiB
Objective-C
// 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;
|
|
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(); }
|