2009-12-16 04:14:24 +08:00
|
|
|
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s
|
2011-09-28 06:38:19 +08:00
|
|
|
|
|
|
|
#define bool _Bool
|
2008-12-11 01:49:55 +08:00
|
|
|
@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)) {
|
2009-04-01 09:17:39 +08:00
|
|
|
return bar4(objectCreationBlock);
|
2008-12-11 01:49:55 +08:00
|
|
|
}
|
2008-12-23 08:53:59 +08:00
|
|
|
|
2011-09-28 07:30:47 +08:00
|
|
|
void bar5(id(^)(void)); // expected-note 3{{passing argument to parameter here}}
|
2011-09-28 06:38:19 +08:00
|
|
|
void foo5(id (^objectCreationBlock)(bool)) {
|
2011-09-28 07:30:47 +08:00
|
|
|
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)'}}
|
2009-04-01 09:17:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void bar6(id(^)(int));
|
|
|
|
void foo6(id (^objectCreationBlock)()) {
|
2009-06-08 12:24:21 +08:00
|
|
|
return bar6(objectCreationBlock);
|
2009-04-01 09:17:39 +08:00
|
|
|
}
|
|
|
|
|
2009-04-12 03:17:25 +08:00
|
|
|
void foo7(id (^x)(int)) {
|
2008-12-23 08:53:59 +08:00
|
|
|
if (x) { }
|
|
|
|
}
|
2009-04-12 03:17:25 +08:00
|
|
|
|
|
|
|
@interface itf
|
|
|
|
@end
|
|
|
|
|
|
|
|
void foo8() {
|
2011-12-15 08:38:15 +08:00
|
|
|
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'}}
|
2009-04-12 03:17:25 +08:00
|
|
|
}
|
2009-08-15 05:53:27 +08:00
|
|
|
|
|
|
|
|
|
|
|
int foo9() {
|
|
|
|
typedef void (^DVTOperationGroupScheduler)();
|
|
|
|
id _suboperationSchedulers;
|
|
|
|
|
|
|
|
for (DVTOperationGroupScheduler scheduler in _suboperationSchedulers) {
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2010-03-10 02:34:52 +08:00
|
|
|
|
|
|
|
// rdar 7725203
|
|
|
|
@class NSString;
|
|
|
|
|
|
|
|
extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
|
|
|
|
|
|
|
|
void foo10() {
|
|
|
|
void(^myBlock)(void) = ^{
|
|
|
|
};
|
|
|
|
NSLog(@"%@", myBlock);
|
|
|
|
}
|
|
|
|
|
2012-06-21 13:54:55 +08:00
|
|
|
|
|
|
|
// In C, enum constants have the type of the underlying integer type, not the
|
2013-03-09 08:54:31 +08:00
|
|
|
// enumeration they are part of. We pretend the constants have enum type if
|
|
|
|
// all the returns seem to be playing along.
|
2012-06-21 13:54:55 +08:00
|
|
|
enum CStyleEnum {
|
2013-03-09 08:54:31 +08:00
|
|
|
CSE_Value = 1,
|
|
|
|
CSE_Value2 = 2
|
2012-06-21 13:54:55 +08:00
|
|
|
};
|
|
|
|
enum CStyleEnum getCSE();
|
|
|
|
typedef enum CStyleEnum (^cse_block_t)();
|
|
|
|
|
|
|
|
void testCStyleEnumInference(bool arg) {
|
|
|
|
cse_block_t a;
|
2013-05-08 11:34:22 +08:00
|
|
|
enum CStyleEnum value;
|
2012-06-21 13:54:55 +08:00
|
|
|
|
|
|
|
// No warnings here.
|
|
|
|
a = ^{ return getCSE(); };
|
2013-05-08 11:34:22 +08:00
|
|
|
a = ^{ return value; };
|
2012-06-21 13:54:55 +08:00
|
|
|
|
|
|
|
a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
|
|
|
|
return 1;
|
|
|
|
};
|
2013-03-09 08:54:31 +08:00
|
|
|
|
|
|
|
// No warning here.
|
|
|
|
a = ^{
|
2012-07-03 05:19:23 +08:00
|
|
|
return CSE_Value;
|
|
|
|
};
|
2012-06-21 13:54:55 +08:00
|
|
|
|
|
|
|
// No warnings here.
|
|
|
|
a = ^{ if (arg) return CSE_Value; else return getCSE(); };
|
|
|
|
a = ^{ if (arg) return getCSE(); else return CSE_Value; };
|
2013-05-08 11:34:22 +08:00
|
|
|
a = ^{ if (arg) return value; else return CSE_Value; };
|
2012-06-21 13:54:55 +08:00
|
|
|
|
2012-07-03 05:19:23 +08:00
|
|
|
// These two blocks actually return 'int'
|
2012-06-21 13:54:55 +08:00
|
|
|
a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
|
|
|
|
if (arg)
|
|
|
|
return 1;
|
|
|
|
else
|
2012-07-03 05:19:23 +08:00
|
|
|
return CSE_Value;
|
2012-06-21 13:54:55 +08:00
|
|
|
};
|
|
|
|
|
2012-07-03 05:19:23 +08:00
|
|
|
a = ^{ // expected-error {{incompatible block pointer types assigning to 'cse_block_t' (aka 'enum CStyleEnum (^)()') from 'int (^)(void)'}}
|
2012-06-21 13:54:55 +08:00
|
|
|
if (arg)
|
|
|
|
return CSE_Value;
|
|
|
|
else
|
2012-07-03 05:19:23 +08:00
|
|
|
return 1;
|
2012-06-21 13:54:55 +08:00
|
|
|
};
|
2013-03-09 08:54:31 +08:00
|
|
|
|
2013-05-08 11:34:22 +08:00
|
|
|
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'}}
|
|
|
|
};
|
|
|
|
|
2013-03-09 08:54:31 +08:00
|
|
|
// 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; }));
|
|
|
|
};
|
2012-06-21 13:54:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
};
|
2012-07-03 05:19:23 +08:00
|
|
|
a = ^{
|
|
|
|
return FTE_Value;
|
|
|
|
};
|
|
|
|
|
2012-06-21 13:54:55 +08:00
|
|
|
// 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; };
|
|
|
|
|
2012-07-03 05:19:23 +08:00
|
|
|
// These two blocks actually return 'unsigned'.
|
2012-06-21 13:54:55 +08:00
|
|
|
a = ^{
|
|
|
|
if (arg)
|
|
|
|
return 1U;
|
|
|
|
else
|
2012-07-03 05:19:23 +08:00
|
|
|
return FTE_Value;
|
2012-06-21 13:54:55 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
a = ^{
|
|
|
|
if (arg)
|
|
|
|
return FTE_Value;
|
|
|
|
else
|
2012-07-03 05:19:23 +08:00
|
|
|
return 1U;
|
2012-06-21 13:54:55 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
AnonymousValue = 1
|
|
|
|
};
|
|
|
|
|
|
|
|
enum : short {
|
|
|
|
FixedAnonymousValue = 1
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
TDE_Value
|
|
|
|
} TypeDefEnum;
|
2012-07-03 05:19:23 +08:00
|
|
|
TypeDefEnum getTDE();
|
2012-06-21 13:54:55 +08:00
|
|
|
|
|
|
|
typedef enum : short {
|
|
|
|
TDFTE_Value
|
|
|
|
} TypeDefFixedTypeEnum;
|
2012-07-03 05:19:23 +08:00
|
|
|
TypeDefFixedTypeEnum getTDFTE();
|
2012-06-21 13:54:55 +08:00
|
|
|
|
|
|
|
typedef int (^int_block_t)();
|
|
|
|
typedef short (^short_block_t)();
|
2012-07-03 05:19:23 +08:00
|
|
|
void testAnonymousEnumTypes(int arg) {
|
2012-06-21 13:54:55 +08:00
|
|
|
int_block_t IB;
|
|
|
|
IB = ^{ return AnonymousValue; };
|
2013-03-21 08:10:07 +08:00
|
|
|
IB = ^{ if (arg) return TDE_Value; else return getTDE(); };
|
|
|
|
IB = ^{ if (arg) return getTDE(); else return TDE_Value; };
|
2012-06-21 13:54:55 +08:00
|
|
|
|
2012-07-03 05:19:23 +08:00
|
|
|
// Since we fixed the underlying type of the enum, these are considered
|
|
|
|
// compatible block types anyway.
|
2012-06-21 13:54:55 +08:00
|
|
|
short_block_t SB;
|
|
|
|
SB = ^{ return FixedAnonymousValue; };
|
2012-07-03 05:19:23 +08:00
|
|
|
SB = ^{ if (arg) return TDFTE_Value; else return getTDFTE(); };
|
|
|
|
SB = ^{ if (arg) return getTDFTE(); else return TDFTE_Value; };
|
2012-06-21 13:54:55 +08:00
|
|
|
}
|
2013-09-13 06:36:24 +08:00
|
|
|
|
|
|
|
static inline void inlinefunc() {
|
|
|
|
^{}();
|
|
|
|
}
|
|
|
|
void inlinefunccaller() { inlinefunc(); }
|