2012-04-07 02:12:22 +08:00
|
|
|
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wno-objc-root-class %s
|
2011-02-08 10:14:35 +08:00
|
|
|
|
|
|
|
struct X {
|
|
|
|
void f() const;
|
|
|
|
~X();
|
|
|
|
};
|
|
|
|
|
|
|
|
@interface A {
|
|
|
|
X x_;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (const X&)x;
|
|
|
|
- (void)setx:(const X&)other;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation A
|
|
|
|
|
|
|
|
- (const X&)x { return x_; }
|
|
|
|
- (void)setx:(const X&)other { x_ = other; }
|
|
|
|
- (void)method {
|
|
|
|
self.x.f();
|
2011-11-15 09:35:18 +08:00
|
|
|
}
|
2011-02-08 10:14:35 +08:00
|
|
|
@end
|
|
|
|
|
2011-11-15 09:35:18 +08:00
|
|
|
// rdar://problem/10444030
|
|
|
|
@interface Test2
|
|
|
|
- (void) setY: (int) y;
|
|
|
|
- (int) z;
|
|
|
|
@end
|
|
|
|
void test2(Test2 *a) {
|
2012-11-29 11:13:49 +08:00
|
|
|
auto y = a.y; // expected-error {{no getter method for read from property}}
|
2011-11-15 09:35:18 +08:00
|
|
|
auto z = a.z;
|
|
|
|
}
|
2012-01-11 08:14:46 +08:00
|
|
|
|
|
|
|
// rdar://problem/10672108
|
|
|
|
@interface Test3
|
|
|
|
- (int) length;
|
|
|
|
@end
|
|
|
|
void test3(Test3 *t) {
|
2012-01-11 09:35:55 +08:00
|
|
|
char vla[t.length] = {}; // expected-error {{variable-sized object may not be initialized}}
|
|
|
|
char *heaparray = new char[t.length];
|
2012-01-11 08:14:46 +08:00
|
|
|
}
|
2012-01-12 08:44:34 +08:00
|
|
|
|
2012-01-13 00:11:24 +08:00
|
|
|
// <rdar://problem/10672501>
|
|
|
|
namespace std {
|
|
|
|
template<typename T> void count();
|
|
|
|
}
|
|
|
|
|
2012-01-14 00:56:26 +08:00
|
|
|
@interface Test4
|
|
|
|
- (X&) prop;
|
|
|
|
@end
|
|
|
|
|
|
|
|
void test4(Test4 *t) {
|
|
|
|
(void)const_cast<const X&>(t.prop);
|
|
|
|
(void)dynamic_cast<X&>(t.prop);
|
|
|
|
(void)reinterpret_cast<int&>(t.prop);
|
|
|
|
}
|
|
|
|
|
|
|
|
@interface Test5 {
|
2012-01-13 00:11:24 +08:00
|
|
|
@public
|
|
|
|
int count;
|
|
|
|
}
|
|
|
|
@property int count;
|
2012-01-12 08:44:34 +08:00
|
|
|
@end
|
2012-01-13 00:11:24 +08:00
|
|
|
|
2012-01-14 00:56:26 +08:00
|
|
|
void test5(Test5* t5) {
|
|
|
|
if (t5.count < 2) { }
|
|
|
|
if (t5->count < 2) { }
|
2012-01-12 08:44:34 +08:00
|
|
|
}
|
2012-01-13 00:11:24 +08:00
|
|
|
|
2012-02-17 02:19:22 +08:00
|
|
|
|
|
|
|
@interface Test6
|
|
|
|
+ (Class)class;
|
|
|
|
- (Class)class;
|
|
|
|
@end
|
|
|
|
|
|
|
|
void test6(Test6 *t6) {
|
|
|
|
Class x = t6.class;
|
|
|
|
Class x2 = Test6.class;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
void test6_template(T *t6) {
|
|
|
|
Class x = t6.class;
|
|
|
|
}
|
|
|
|
|
|
|
|
template void test6_template(Test6*);
|
2012-03-09 12:08:29 +08:00
|
|
|
|
|
|
|
// rdar://problem/10965735
|
|
|
|
struct Test7PointerMaker {
|
|
|
|
operator char *() const;
|
|
|
|
};
|
|
|
|
@interface Test7
|
|
|
|
- (char*) implicit_property;
|
|
|
|
- (char) bad_implicit_property;
|
|
|
|
- (Test7PointerMaker) implicit_struct_property;
|
|
|
|
@property int *explicit_property;
|
|
|
|
@property int bad_explicit_property;
|
|
|
|
@property Test7PointerMaker explicit_struct_property;
|
|
|
|
@end
|
|
|
|
void test7(Test7 *ptr) {
|
|
|
|
delete ptr.implicit_property;
|
|
|
|
delete ptr.bad_implicit_property; // expected-error {{cannot delete expression of type 'char'}}
|
|
|
|
delete ptr.explicit_property;
|
|
|
|
delete ptr.bad_explicit_property; // expected-error {{cannot delete expression of type 'int'}}
|
|
|
|
delete ptr.implicit_struct_property;
|
|
|
|
delete ptr.explicit_struct_property;
|
|
|
|
}
|
2012-11-14 07:16:33 +08:00
|
|
|
|
|
|
|
// Make sure the returned value from property assignment is void,
|
|
|
|
// because there isn't any other viable way to handle it for
|
|
|
|
// non-trivial classes.
|
|
|
|
class NonTrivial1 {
|
|
|
|
public:
|
|
|
|
~NonTrivial1();
|
|
|
|
};
|
|
|
|
class NonTrivial2 {
|
|
|
|
public:
|
|
|
|
NonTrivial2();
|
|
|
|
NonTrivial2(const NonTrivial2&);
|
|
|
|
};
|
|
|
|
@interface TestNonTrivial
|
|
|
|
@property(assign, nonatomic) NonTrivial1 p1;
|
|
|
|
@property(assign, nonatomic) NonTrivial2 p2;
|
|
|
|
@end
|
|
|
|
TestNonTrivial *TestNonTrivialObj;
|
|
|
|
|
|
|
|
extern void* VoidType;
|
|
|
|
extern decltype(TestNonTrivialObj.p1 = NonTrivial1())* VoidType;
|
|
|
|
extern decltype(TestNonTrivialObj.p2 = NonTrivial2())* VoidType;
|
|
|
|
|
2013-03-04 09:30:55 +08:00
|
|
|
// rdar://13332183
|
|
|
|
namespace test9 {
|
|
|
|
struct CString {
|
|
|
|
const char *_data;
|
|
|
|
char operator[](int i) const { return _data[i]; }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
@interface Test9
|
|
|
|
@property test9::CString name;
|
|
|
|
@end
|
|
|
|
namespace test9 {
|
|
|
|
char test(Test9 *t) {
|
|
|
|
return t.name[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace test10 {
|
|
|
|
struct A { operator const char*(); };
|
|
|
|
struct B { operator const char*(); };
|
|
|
|
}
|
|
|
|
@interface Test10
|
|
|
|
@property test10::A a;
|
|
|
|
@property test10::B b;
|
|
|
|
@property int index;
|
|
|
|
@end
|
|
|
|
namespace test10 {
|
|
|
|
void test(Test10 *t) {
|
|
|
|
(void) t.a[6];
|
|
|
|
(void) 6[t.b];
|
|
|
|
(void) "help"[t.index];
|
|
|
|
(void) t.index["help"];
|
|
|
|
(void) t.a[t.index];
|
|
|
|
(void) t.index[t.b];
|
|
|
|
}
|
|
|
|
}
|
2013-07-09 09:38:07 +08:00
|
|
|
|
|
|
|
// <rdar://problem/14354144>
|
|
|
|
@interface PropertyOfItself
|
|
|
|
@property (readonly, nonatomic) PropertyOfItself x; // expected-error {{interface type cannot be statically allocated}}
|
|
|
|
@end
|
|
|
|
@implementation PropertyOfItself
|
|
|
|
@synthesize x;
|
|
|
|
@end
|