diff options
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/CXX/basic/basic.scope/basic.scope.local/p4-0x.cpp | 68 | ||||
-rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp | 44 | ||||
-rw-r--r-- | clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp | 210 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp | 4 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/for-range-temporaries.cpp | 131 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/for-range.cpp | 128 | ||||
-rw-r--r-- | clang/test/PCH/cxx-for-range.cpp | 19 | ||||
-rw-r--r-- | clang/test/PCH/cxx-for-range.h | 35 | ||||
-rw-r--r-- | clang/test/SemaCXX/for-range-examples.cpp | 150 | ||||
-rw-r--r-- | clang/test/SemaCXX/for-range-no-std.cpp | 37 |
10 files changed, 826 insertions, 0 deletions
diff --git a/clang/test/CXX/basic/basic.scope/basic.scope.local/p4-0x.cpp b/clang/test/CXX/basic/basic.scope/basic.scope.local/p4-0x.cpp new file mode 100644 index 00000000000..d930f97ce79 --- /dev/null +++ b/clang/test/CXX/basic/basic.scope/basic.scope.local/p4-0x.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +void f() { + int b; + int arr[] = {1, 2, 3}; + + if (bool b = true) // expected-note 2{{previous definition}} + bool b; // expected-error {{redefinition}} + else + int b; // expected-error {{redefinition}} + while (bool b = true) // expected-note {{previous definition}} + int b; // expected-error {{redefinition}} + for (int c; // expected-note 2{{previous definition}} + bool c = true;) // expected-error {{redefinition}} + double c; // expected-error {{redefinition}} + switch (int n = 37 + 5) // expected-note {{previous definition}} + int n; // expected-error {{redefinition}} + for (int a : arr) // expected-note {{previous definition}} + int a = 0; // expected-error {{redefinition}} + + if (bool b = true) { // expected-note 2{{previous definition}} + int b; // expected-error {{redefinition}} + } else { + int b; // expected-error {{redefinition}} + } + while (bool b = true) { // expected-note {{previous definition}} + int b; // expected-error {{redefinition}} + } + for (int c; // expected-note 2{{previous definition}} + bool c = true;) { // expected-error {{redefinition}} + double c; // expected-error {{redefinition}} + } + switch (int n = 37 + 5) { // expected-note {{previous definition}} + int n; // expected-error {{redefinition}} + } + for (int &a : arr) { // expected-note {{previous definition}} + int a = 0; // expected-error {{redefinition}} + } + + if (bool b = true) {{ // expected-note {{previous definition}} + bool b; + }} else { + int b; // expected-error {{redefinition}} + } + if (bool b = true) { // expected-note {{previous definition}} + bool b; // expected-error {{redefinition}} + } else {{ + int b; + }} + if (bool b = true) {{ + bool b; + }} else {{ + int b; + }} + while (bool b = true) {{ + int b; + }} + for (int c; // expected-note {{previous definition}} + bool c = true; ) {{ // expected-error {{redefinition}} + double c; + }} + switch (int n = 37 + 5) {{ + int n; + }} + for (int &a : arr) {{ + int a = 0; + }} +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp new file mode 100644 index 00000000000..10184a058f1 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// FIXME: when clang supports alias-declarations. +#if 0 +using X = struct { // ok +}; +#endif + +class K { + virtual ~K(); + // FIXME: the diagnostic here isn't very good + operator struct S {} (); // expected-error 2{{}} +}; + +void f() { + int arr[3] = {1,2,3}; + + for (struct S { S(int) {} } s : arr) { // expected-error {{types may not be defined in a for range declaration}} + } + + new struct T {}; // expected-error {{allocation of incomplete type}} expected-note {{forward declaration}} + + // FIXME: the diagnostic here isn't very good + try {} catch (struct U {}); // expected-error 3{{}} expected-note 2{{}} + + (void)(struct V { V(int); })0; // expected-error {{'V' can not be defined in a type specifier}} + + (void)dynamic_cast<struct W {}*>((K*)0); // expected-error {{'W' can not be defined in a type specifier}} + (void)static_cast<struct X {}*>(0); // expected-error {{'X' can not be defined in a type specifier}} + (void)reinterpret_cast<struct Y {}*>(0); // expected-error {{'Y' can not be defined in a type specifier}} + (void)const_cast<struct Z {}*>((const Z*)0); // expected-error {{'Z' can not be defined in a type specifier}} +} + +void g() throw (struct Ex {}) { // expected-error {{'Ex' can not be defined in a type specifier}} +} + +// FIXME: this currently gives a strange error because alignas is not recognised as a keyword yet. +int alignas(struct Aa {}) x; // expected-error {{'Aa' can not be defined in a parameter type}} expected-error {{expected function body}} + +int a = sizeof(struct So {}); // expected-error {{'So' can not be defined in a type specifier}} +int b = alignof(struct Ao {}); // expected-error {{'Ao' can not be defined in a type specifier}} + +namespace std { struct type_info; } +const std::type_info &ti = typeid(struct Ti {}); // expected-error {{'Ti' can not be defined in a type specifier}} diff --git a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp new file mode 100644 index 00000000000..12acde143c4 --- /dev/null +++ b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp @@ -0,0 +1,210 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +namespace std { + template<typename T> + auto begin(T &&t) -> decltype(t.begin()) { return t.begin(); } // expected-note 4{{ignored: substitution failure}} + template<typename T> + auto end(T &&t) -> decltype(t.end()) { return t.end(); } // expected-note {{candidate template ignored: substitution failure [with T = }} + + template<typename T> + auto begin(T &&t) -> decltype(t.alt_begin()) { return t.alt_begin(); } // expected-note {{selected 'begin' template [with T = }} \ + expected-note 4{{candidate template ignored: substitution failure [with T = }} + template<typename T> + auto end(T &&t) -> decltype(t.alt_end()) { return t.alt_end(); } // expected-note {{candidate template ignored: substitution failure [with T = }} + + namespace inner { + // These should never be considered. + int begin(int); + int end(int); + } + + using namespace inner; +} + +struct A { // expected-note {{candidate constructor}} + A(); + int *begin(); // expected-note 3{{selected 'begin' function with iterator type 'int *'}} expected-note {{'begin' declared here}} + int *end(); +}; + +struct B { + B(); + int *alt_begin(); + int *alt_end(); +}; + +void f(); // expected-note {{candidate}} +void f(int); // expected-note {{candidate}} + +void g() { + for (int a : A()) + A __begin; + for (char *a : A()) { // expected-error {{cannot initialize a variable of type 'char *' with an lvalue of type 'int'}} + } + for (char *a : B()) { // expected-error {{cannot initialize a variable of type 'char *' with an lvalue of type 'int'}} + } + // FIXME: Terrible diagnostic here. auto deduction should fail, but does not! + for (double a : f) { // expected-error {{address of overloaded function 'f' does not match required type '<overloaded function type>'}} + } + for (auto a : A()) { + } + for (auto a : B()) { + } + for (auto *a : A()) { // expected-error {{variable 'a' with type 'auto *' has incompatible initializer of type 'int'}} + } + // : is not a typo for :: here. + for (A NS:A()) { // expected-error {{no viable conversion from 'int' to 'A'}} + } + for (auto not_in_scope : not_in_scope) { // expected-error {{use of undeclared identifier 'not_in_scope'}} + } + + for (auto a : A()) + for (auto b : A()) { + __range.begin(); // expected-error {{use of undeclared identifier '__range'}} + ++__begin; // expected-error {{use of undeclared identifier '__begin'}} + --__end; // expected-error {{use of undeclared identifier '__end'}} + } + + for (char c : "test") + ; + for (auto a : f()) // expected-error {{cannot use type 'void' as a range}} + ; + + extern int incomplete[]; + for (auto a : incomplete) // expected-error {{cannot use incomplete type 'int []' as a range}} + ; + extern struct Incomplete also_incomplete[2]; // expected-note {{forward declaration}} + for (auto &a : also_incomplete) // expected-error {{cannot use incomplete type 'struct Incomplete [2]' as a range}} + ; + + struct VoidBegin { + void begin(); // expected-note {{selected 'begin' function with iterator type 'void'}} + void end(); + }; + for (auto a : VoidBegin()) // expected-error {{cannot use type 'void' as an iterator}} + ; + + struct null_t { + operator int*(); + }; + struct Differ { + int *begin(); // expected-note {{selected 'begin' function with iterator type 'int *'}} + null_t end(); // expected-note {{selected 'end' function with iterator type 'null_t'}} + }; + for (auto a : Differ()) // expected-error {{'begin' and 'end' must return the same type (got 'int *' and 'null_t')}} + ; + + for (void f() : "error") // expected-error {{for range declaration must declare a variable}} + ; + + for (extern int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'extern'}} + for (static int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'static'}} + for (register int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'register'}} + // FIXME: when clang supports constexpr, this should be rejected. + for (constexpr int a : A()) {} // desired-error {{loop variable 'a' may not be declared 'constexpr'}} + + struct NoBeginADL { + null_t alt_end(); + }; + struct NoEndADL { + null_t alt_begin(); + }; + for (auto u : NoBeginADL()) { // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type 'NoBeginADL'}} + } + for (auto u : NoEndADL()) { // expected-error {{no matching function for call to 'end'}} expected-note {{range has type 'NoEndADL'}} + } + + struct NoBegin { + null_t end(); + }; + struct NoEnd { + null_t begin(); + }; + for (auto u : NoBegin()) { // expected-error {{range type 'NoBegin' has 'end' member but no 'begin' member}} + } + for (auto u : NoEnd()) { // expected-error {{range type 'NoEnd' has 'begin' member but no 'end' member}} + } + + struct NoIncr { + void *begin(); // expected-note {{selected 'begin' function with iterator type 'void *'}} + void *end(); + }; + for (auto u : NoIncr()) { // expected-error {{arithmetic on pointer to void type}} + } + + struct NoNotEq { + NoNotEq begin(); // expected-note {{selected 'begin' function with iterator type 'NoNotEq'}} + NoNotEq end(); + void operator++(); + }; + for (auto u : NoNotEq()) { // expected-error {{invalid operands to binary expression}} + } + + struct NoCopy { + NoCopy(); + NoCopy(const NoCopy &) = delete; + int *begin(); + int *end(); + }; + for (int n : NoCopy()) { // ok + } + + for (int n : 42) { // expected-error {{no matching function for call to 'begin'}} \ + expected-note {{range has type 'int'}} + } + + for (auto a : *also_incomplete) { // expected-error {{cannot use incomplete type 'struct Incomplete' as a range}} + } +} + +template<typename T, typename U> +void h(T t) { + for (U u : t) { // expected-error {{no viable conversion from 'A' to 'int'}} + } + for (auto u : t) { + } +} + +template void h<A, int>(A); +template void h<A(&)[4], A &>(A(&)[4]); +template void h<A(&)[13], A>(A(&)[13]); +template void h<A(&)[13], int>(A(&)[13]); // expected-note {{requested here}} + +template<typename T> +void i(T t) { + for (auto u : t) { // expected-error {{no matching function for call to 'begin'}} \ + expected-error {{member function 'begin' not viable}} \ + expected-note {{range has type}} + } +} +template void i<A[13]>(A*); // expected-note {{requested here}} +template void i<const A>(const A); // expected-note {{requested here}} + +namespace NS { + class ADL {}; + int *begin(ADL); // expected-note {{no known conversion from 'NS::NoADL' to 'NS::ADL'}} + int *end(ADL); + + class NoADL {}; +} +int *begin(NS::NoADL); +int *end(NS::NoADL); + +struct VoidBeginADL {}; +void begin(VoidBeginADL); // expected-note {{selected 'begin' function with iterator type 'void'}} +void end(VoidBeginADL); + +void j() { + for (auto u : NS::ADL()) { + } + for (auto u : NS::NoADL()) { // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type}} + } + for (auto a : VoidBeginADL()) { // expected-error {{cannot use type 'void' as an iterator}} + } +} + +void example() { + int array[5] = { 1, 2, 3, 4, 5 }; + for (int &x : array) + x *= 2; +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp index a0b17adad6a..25338e3bae6 100644 --- a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp @@ -205,6 +205,8 @@ struct TestUnexpandedDecls : T{ Types t; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} for (Types *t = 0; ; ) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} for (; Types *t = 0; ) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + T a[] = { T(), T(), T() }; + for (Types t : a) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} switch(Types *t = 0) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} while(Types *t = 0) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} if (Types *t = 0) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} @@ -341,6 +343,8 @@ void test_unexpanded_exprs(Types ...values) { // SizeOfPackExpr is uninteresting // FIXME: Objective-C expressions will need to go elsewhere + + for (auto t : values) { } // expected-error{{expression contains unexpanded parameter pack 'values'}} } // Test unexpanded parameter packs in partial specializations. diff --git a/clang/test/CodeGenCXX/for-range-temporaries.cpp b/clang/test/CodeGenCXX/for-range-temporaries.cpp new file mode 100644 index 00000000000..285862f51f6 --- /dev/null +++ b/clang/test/CodeGenCXX/for-range-temporaries.cpp @@ -0,0 +1,131 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++0x -emit-llvm -o - -UDESUGAR %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++0x -emit-llvm -o - -DDESUGAR %s | FileCheck %s + +struct A { + A(); + A(const A &); + ~A(); +}; + +struct B { + B(); + B(const B &); + ~B(); +}; + +struct C { + C(const B &); + C(const C &); + ~C(); +}; + +struct E; +struct D { + D(const C &); + D(const D &); + ~D(); +}; +E begin(D); +E end(D); + +struct F; +struct G; +struct H; +struct E { + E(const E &); + ~E(); + F operator*(); + G operator++(); + H operator!=(const E &o); +}; + +struct I; +struct F { + F(const F &); + ~F(); + operator I(); +}; + +struct G { + G(const G &); + ~G(); + operator bool(); +}; + +struct H { + H(const H &); + ~H(); + operator bool(); +}; + +struct I { + I(const I &); + ~I(); +}; + +void body(const I &); + +void for_temps() { + A a; +#ifdef DESUGAR + { + auto && __range = D(B()); + for (auto __begin = begin(__range), __end = end(__range); + __begin != __end; ++__begin) { + I i = *__begin; + body(i); + } + } +#else + for (I i : D(B())) { + body(i); + } +#endif +} + +// CHECK: define void @_Z9for_tempsv() +// CHECK: call void @_ZN1AC1Ev( +// CHECK: call void @_ZN1BC1Ev( +// CHECK: call void @_ZN1CC1ERK1B( +// CHECK: call void @_ZN1DC1ERK1C( +// CHECK: call void @_ZN1CD1Ev( +// CHECK: call void @_ZN1BD1Ev( +// CHECK: call void @_ZN1DC1ERKS_( +// CHECK: call void @_Z5begin1D( +// CHECK: call void @_ZN1DD1Ev( +// CHECK: call void @_ZN1DC1ERKS_( +// CHECK: call void @_Z3end1D( +// CHECK: call void @_ZN1DD1Ev( +// CHECK: br label %[[COND:.*]] + +// CHECK: [[COND]]: +// CHECK: call void @_ZN1EneERKS_( +// CHECK: %[[CMP:.*]] = call zeroext i1 @_ZN1HcvbEv( +// CHECK: call void @_ZN1HD1Ev( +// CHECK: br i1 %[[CMP]], label %[[BODY:.*]], label %[[CLEANUP:.*]] + +// CHECK: [[CLEANUP]]: +// CHECK: call void @_ZN1ED1Ev( +// CHECK: call void @_ZN1ED1Ev( +// In for-range: +// call void @_ZN1DD1Ev( +// CHECK: br label %[[END:.*]] + +// CHECK: [[BODY]]: +// CHECK: call void @_ZN1EdeEv( +// CHECK: call void @_ZN1Fcv1IEv( +// CHECK: call void @_ZN1FD1Ev( +// CHECK: call void @_Z4bodyRK1I( +// CHECK: call void @_ZN1ID1Ev( +// CHECK: br label %[[INC:.*]] + +// CHECK: [[INC]]: +// CHECK: call void @_ZN1EppEv( +// CHECK: call void @_ZN1GD1Ev( +// CHECK: br label %[[COND]] + +// CHECK: [[END]]: +// In desugared version: +// call void @_ZN1DD1Ev( +// CHECK: call void @_ZN1AD1Ev( +// CHECK: ret void diff --git a/clang/test/CodeGenCXX/for-range.cpp b/clang/test/CodeGenCXX/for-range.cpp new file mode 100644 index 00000000000..94b614f726b --- /dev/null +++ b/clang/test/CodeGenCXX/for-range.cpp @@ -0,0 +1,128 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -std=c++0x -emit-llvm -o - %s | FileCheck %s + +struct A { + A(); + A(const A&); + ~A(); +}; + +struct B { + B(); + B(const B&); + ~B(); +}; + +struct C { + C(); + C(const C&); + ~C(); +}; + +struct D { + D(); + D(const D&); + ~D(); + + B *begin(); + B *end(); +}; + +namespace std { + B *begin(C&); + B *end(C&); +} + +extern B array[5]; + +// CHECK: define void @_Z9for_arrayv( +void for_array() { + // CHECK: call void @_ZN1AC1Ev(%struct.A* [[A:.*]]) + A a; + for (B b : array) { + // CHECK-NOT: 5begin + // CHECK-NOT: 3end + // CHECK: getelementptr {{.*}}, i32 0 + // CHECK: getelementptr {{.*}}, i64 5 + // CHECK: br label %[[COND:.*]] + + // CHECK: [[COND]]: + // CHECK: %[[CMP:.*]] = icmp ne + // CHECK: br i1 %[[CMP]], label %[[BODY:.*]], label %[[END:.*]] + + // CHECK: [[BODY]]: + // CHECK: call void @_ZN1BC1ERKS_( + // CHECK: call void @_ZN1BD1Ev( + // CHECK: br label %[[INC:.*]] + + // CHECK: [[INC]]: + // CHECK: getelementptr {{.*}} i32 1 + // CHECK: br label %[[COND]] + } + // CHECK: [[END]]: + // CHECK: call void @_ZN1AD1Ev(%struct.A* [[A]]) + // CHECK: ret void +} + +// CHECK: define void @_Z9for_rangev( +void for_range() { + // CHECK: call void @_ZN1AC1Ev(%struct.A* [[A:.*]]) + A a; + for (B b : C()) { + // CHECK: call void @_ZN1CC1Ev( + // CHECK: = call %struct.A* @_ZSt5beginR1C( + // CHECK: = call %struct.A* @_ZSt3endR1C( + // CHECK: br label %[[COND:.*]] + + // CHECK: [[COND]]: + // CHECK: %[[CMP:.*]] = icmp ne + // CHECK: br i1 %[[CMP]], label %[[BODY:.*]], label %[[CLEANUP:.*]] + + // CHECK: [[CLEANUP]]: + // CHECK: call void @_ZN1CD1Ev( + // CHECK: br label %[[END:.*]] + + // CHECK: [[BODY]]: + // CHECK: call void @_ZN1BC1ERKS_( + // CHECK: call void @_ZN1BD1Ev( + // CHECK: br label %[[INC:.*]] + + // CHECK: [[INC]]: + // CHECK: getelementptr {{.*}} i32 1 + // CHECK: br label %[[COND]] + } + // CHECK: [[END]]: + // CHECK: call void @_ZN1AD1Ev(%struct.A* [[A]]) + // CHECK: ret void +} + +// CHECK: define void @_Z16for_member_rangev( +void for_member_range() { + // CHECK: call void @_ZN1AC1Ev(%struct.A* [[A:.*]]) + A a; + for (B b : D()) { + // CHECK: call void @_ZN1DC1Ev( + // CHECK: = call %struct.A* @_ZN1D5beginEv( + // CHECK: = call %struct.A* @_ZN1D3endEv( + // CHECK: br label %[[COND:.*]] + + // CHECK: [[COND]]: + // CHECK: %[[CMP:.*]] = icmp ne + // CHECK: br i1 %[[CMP]], label %[[BODY:.*]], label %[[CLEANUP:.*]] + + // CHECK: [[CLEANUP]]: + // CHECK: call void @_ZN1DD1Ev( + // CHECK: br label %[[END:.*]] + + // CHECK: [[BODY]]: + // CHECK: call void @_ZN1BC1ERKS_( + // CHECK: call void @_ZN1BD1Ev( + // CHECK: br label %[[INC:.*]] + + // CHECK: [[INC]]: + // CHECK: getelementptr {{.*}} i32 1 + // CHECK: br label %[[COND]] + } + // CHECK: [[END]]: + // CHECK: call void @_ZN1AD1Ev(%struct.A* [[A]]) + // CHECK: ret void +} diff --git a/clang/test/PCH/cxx-for-range.cpp b/clang/test/PCH/cxx-for-range.cpp new file mode 100644 index 00000000000..5854917da5c --- /dev/null +++ b/clang/test/PCH/cxx-for-range.cpp @@ -0,0 +1,19 @@ +// Test this without pch. +// RUN: %clang_cc1 -std=c++0x -include %S/cxx-for-range.h -fsyntax-only -emit-llvm -o - %s + +// Test with pch. +// RUN: %clang_cc1 -std=c++0x -emit-pch -o %t %S/cxx-for-range.h +// RUN: %clang_cc1 -std=c++0x -include-pch %t -fsyntax-only -emit-llvm -o - %s + +void h() { + f(); + + g<int>(); + + char a[3] = { 0, 1, 2 }; + for (auto w : a) + for (auto x : S()) + for (auto y : T()) + for (auto z : U()) + ; +} diff --git a/clang/test/PCH/cxx-for-range.h b/clang/test/PCH/cxx-for-range.h new file mode 100644 index 00000000000..f15c7e73df3 --- /dev/null +++ b/clang/test/PCH/cxx-for-range.h @@ -0,0 +1,35 @@ +// Header for PCH test cxx-for-range.cpp + +struct S { + int *begin(); + int *end(); +}; + +struct T { }; +char *begin(T); +char *end(T); + +struct U { }; +namespace std { + char *begin(U); + char *end(U); +} + +void f() { + char a[3] = { 0, 1, 2 }; + for (auto w : a) + for (auto x : S()) + for (auto y : T()) + for (auto z : U()) + ; +} + +template<typename A> +void g() { + A a[3] = { 0, 1, 2 }; + for (auto &v : a) + for (auto x : S()) + for (auto y : T()) + for (auto z : U()) + ; +} diff --git a/clang/test/SemaCXX/for-range-examples.cpp b/clang/test/SemaCXX/for-range-examples.cpp new file mode 100644 index 00000000000..810f1de441a --- /dev/null +++ b/clang/test/SemaCXX/for-range-examples.cpp @@ -0,0 +1,150 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x + +namespace value_range_detail { + template<typename T> + class value_range_iter { + T t; + public: + value_range_iter(const T &t) : t(t) {} + T operator*() const { return t; } + bool operator!=(const value_range_iter &o) const { return t != o.t; } + value_range_iter &operator++() { ++t; return *this; } + }; + + template<typename T> + struct value_range { + value_range(const T &a, const T &b) : begin_(a), end_(b) {} + value_range_iter<T> begin_, end_; + }; + + template<typename T> + value_range_iter<T> begin(const value_range<T> &r) { return r.begin_; } + template<typename T> + value_range_iter<T> end(const value_range<T> &r) { return r.end_; } + + + struct end_t {}; + + template<typename T> + class value_range_step_iter { + T it, step; + public: + value_range_step_iter(const T &it, const T &step) : it(it), step(step) {} + T operator*() const { return it; } + bool operator!=(value_range_step_iter end) const { return it != end.it; } + value_range_step_iter &operator++() { it += step; return *this; } + }; + + template<typename T> + class value_range_step { + T it, step, end_; + public: + value_range_step(const T &it, const T &end, const T &step) : + it(it), end_(end), step(step) {} + typedef value_range_step_iter<T> iterator; + iterator begin() const { return iterator(it, step); } + iterator end() const { return iterator(end_, step); } + }; +} + +template<typename T> +value_range_detail::value_range<T> range(const T &a, const T &b) { return value_range_detail::value_range<T>(a, b); } + +template<typename T> +value_range_detail::value_range_step<T> range(const T &a, const T &b, const T &step) { return value_range_detail::value_range_step<T>(a, b, step); } + + +namespace map_range { + template<typename T> + class vector { + T storage[100]; + decltype(sizeof(char)) size; + public: + vector() : size() {} + void push_back(T t) { storage[size++] = t; } + T *begin() { return storage; } + T *end() { return storage + size; } + }; + + template<typename T> struct tuple_elem { + T t; + tuple_elem() {} + tuple_elem(T t) : t(t) {} + }; + template<typename... A> + struct tuple : tuple_elem<A>... { + tuple() : tuple_elem<A>()... {} + tuple(A... a) : tuple_elem<A>(a)... {} + template<typename B> B &get() { return tuple_elem<B>::t; } + }; + + template<typename F, typename I> + class map_iter { + F f; + I i; + public: + map_iter(F f, I i) : f(f), i(i) {} + auto operator*() const -> decltype(f(*i)) { return f(*i); } + bool operator!=(const map_iter &o) const { return i != o.i; } + map_iter &operator++() { ++i; return *this; } + }; + + template<typename T> + struct iter_pair { + T begin_, end_; + iter_pair(T begin, T end) : begin_(begin), end_(end) {} + }; + template<typename T> T begin(iter_pair<T> p) { return p.begin_; } + template<typename T> T end(iter_pair<T> p) { return p.end_; } + + template<typename...> class mem_fun_impl; + template<typename R, typename T, typename... A> + class mem_fun_impl<R (T::*)(A...)> { + typedef R (T::*F)(A...); + F f; + public: + mem_fun_impl(F f) : f(f) {} + R operator()(T &t, A &&...a) const { return (t.*f)(static_cast<A&&>(a)...); } + }; + template<typename F> mem_fun_impl<F> mem_fun(F f) { return mem_fun_impl<F>(f); } + + template<typename F, typename T> + auto map(const F &f, T &t) -> iter_pair<map_iter<F, decltype(t.begin())>> { + typedef map_iter<F, decltype(t.begin())> iter; + return iter_pair<iter>(iter(f, t.begin()), iter(f, t.end())); + } +} + +#define assert(b) if (!b) { return 1; } +int main() { + int total = 0; + + for (auto n : range(1, 5)) { + total += n; + } + assert(total == 10); + + for (auto n : range(10, 100, 10)) { + total += n; + } + assert(total == 460); + + map_range::vector<char> chars; + chars.push_back('a'); + chars.push_back('b'); + chars.push_back('c'); + for (char c : chars) { + ++total; + } + assert(total == 463); + + typedef map_range::tuple<int, double> T; + map_range::vector<T> pairs; + pairs.push_back(T(42, 12.9)); + pairs.push_back(T(6, 4.2)); + pairs.push_back(T(9, 1.1)); + for (auto a : map(map_range::mem_fun(&T::get<int>), pairs)) { + total += a; + } + assert(total == 500); +} diff --git a/clang/test/SemaCXX/for-range-no-std.cpp b/clang/test/SemaCXX/for-range-no-std.cpp new file mode 100644 index 00000000000..8cc71e5111a --- /dev/null +++ b/clang/test/SemaCXX/for-range-no-std.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x + +struct S { + int *begin(); + int *end(); +}; + +struct T { +}; + +struct Range {}; +int begin(Range); // expected-note {{not viable}} +int end(Range); + +namespace NS { + struct ADL {}; + struct iter { + int operator*(); + bool operator!=(iter); + void operator++(); + }; + iter begin(ADL); // expected-note {{not viable}} + iter end(ADL); + + struct NoADL {}; +} +NS::iter begin(NS::NoADL); // expected-note {{not viable}} +NS::iter end(NS::NoADL); + +void f() { + int a[] = {1, 2, 3}; + for (auto b : S()) {} // ok + for (auto b : T()) {} // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type}} + for (auto b : a) {} // ok + for (int b : NS::ADL()) {} // ok + for (int b : NS::NoADL()) {} // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type}} +} |