diff options
Diffstat (limited to 'test/CXX')
135 files changed, 5449 insertions, 131 deletions
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp index df3429e..1e5a823 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp @@ -44,7 +44,7 @@ namespace Test { // PR6716 namespace test1 { template <class T> class A { - template <class U> friend void foo(A &, U); // expected-note {{not viable: 1st argument ('A<int> const') would lose const qualifier}} + template <class U> friend void foo(A &, U); // expected-note {{not viable: 1st argument ('const A<int>') would lose const qualifier}} }; void test() { diff --git a/test/CXX/basic/basic.scope/basic.scope.hiding/p2.cpp b/test/CXX/basic/basic.scope/basic.scope.hiding/p2.cpp new file mode 100644 index 0000000..911df98 --- /dev/null +++ b/test/CXX/basic/basic.scope/basic.scope.hiding/p2.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// rdar4641403 +namespace N { + struct X { // expected-note{{candidate found by name lookup}} + float b; + }; +} + +using namespace N; + +typedef struct { + int a; +} X; // expected-note{{candidate found by name lookup}} + + +struct Y { }; +void Y(int) { } + +void f() { + X *x; // expected-error{{reference to 'X' is ambiguous}} + Y(1); // okay +} + diff --git a/test/CXX/basic/basic.start/basic.start.main/p2h.cpp b/test/CXX/basic/basic.start/basic.start.main/p2h.cpp new file mode 100644 index 0000000..abf8faa --- /dev/null +++ b/test/CXX/basic/basic.start/basic.start.main/p2h.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +int main() { } // expected-error{{'main' cannot be a template}} + diff --git a/test/CXX/class.access/class.friend/p1.cpp b/test/CXX/class.access/class.friend/p1.cpp index 277b70b..1668155 100644 --- a/test/CXX/class.access/class.friend/p1.cpp +++ b/test/CXX/class.access/class.friend/p1.cpp @@ -258,13 +258,12 @@ namespace test7 { namespace test8 { class A { typedef int I; // expected-note 4 {{declared private here}} - static const I x = 0; + static const I x = 0; // expected-note {{implicitly declared private here}} friend I f(I i); template<typename T> friend I g(I i); }; - // FIXME: This should be on line 264. - const A::I A::x; // expected-note {{declared private here}} + const A::I A::x; A::I f(A::I i = A::x) {} template<typename T> A::I g(A::I i) { T t; @@ -306,3 +305,39 @@ namespace test10 { NS::bar->foo(); // expected-error {{private member}} } } + +// PR8705 +namespace test11 { + class A { + void test0(int); + void test1(int); + void test2(int); + void test3(int); + }; + + class B { + typedef int private_type; // expected-note 2 {{implicitly declared private here}} + friend void A::test0(int); + friend void A::test1(int); + }; + + void A::test0(B::private_type x) {} + void A::test1(int x = B::private_type()) {} + void A::test2(B::private_type x) {} // expected-error {{'private_type' is a private member of 'test11::B'}} + void A::test3(int x = B::private_type()) {} // expected-error {{'private_type' is a private member of 'test11::B'}} +} + + +// PR9221 +namespace test12 { + struct A { + void foo(); + }; + class B : private A { + friend void A::foo(); + void *mem; + }; + void A::foo() { + void *var = static_cast<B*>(this)->mem; + } +} diff --git a/test/CXX/class.access/class.friend/p11.cpp b/test/CXX/class.access/class.friend/p11.cpp new file mode 100644 index 0000000..a05b2d2 --- /dev/null +++ b/test/CXX/class.access/class.friend/p11.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// rdar://problem/8540720 +namespace test0 { + void foo() { + void bar(); + class A { + friend void bar(); + }; + } +} + +namespace test1 { + void foo() { + class A { + friend void bar(); // expected-error {{no matching function found in local scope}} + }; + } +} diff --git a/test/CXX/class.access/p4.cpp b/test/CXX/class.access/p4.cpp index 115a22a..84b7b19 100644 --- a/test/CXX/class.access/p4.cpp +++ b/test/CXX/class.access/p4.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fexceptions -fsyntax-only -verify %s // C++0x [class.access]p4: @@ -201,7 +201,7 @@ namespace test4 { // Implicit copy assignment operator uses. namespace test5 { class A { - void operator=(const A &); // expected-note 2 {{declared private here}} + void operator=(const A &); // expected-note 2 {{implicitly declared private here}} }; class Test1 { A a; }; // expected-error {{private member}} @@ -450,3 +450,61 @@ namespace test18 { A<int> member; }; } + +// PR8325 +namespace test19 { + class A { ~A(); }; + // The destructor is not implicitly referenced here. Contrast to test16, + // testing PR7281, earlier in this file. + void b(A* x) { throw x; } +} + +// PR7930 +namespace test20 { + class Foo { + Foo(); // expected-note {{implicitly declared private here}} + }; + Foo::Foo() {} + + void test() { + Foo a; // expected-error {{calling a private constructor}} + } +} + +namespace test21 { + template <class T> class A { + void foo(); + void bar(); + class Inner; // expected-note {{implicitly declared private here}} + public: + void baz(); + }; + template <class T> class A<T>::Inner {}; + class B { + template <class T> class A<T>::Inner; + }; + + void test() { + A<int>::Inner i; // expected-error {{'Inner' is a private member}} + } +} + +namespace rdar8876150 { + struct A { operator bool(); }; + struct B : private A { using A::operator bool; }; + + bool f() { + B b; + return !b; + } +} + +namespace test23 { + template <typename T> class A { + A(); + static A instance; + }; + + template <typename T> A<T> A<T>::instance; + template class A<int>; +} diff --git a/test/CXX/class.access/p6.cpp b/test/CXX/class.access/p6.cpp index 8795708..fe3304a 100644 --- a/test/CXX/class.access/p6.cpp +++ b/test/CXX/class.access/p6.cpp @@ -139,3 +139,32 @@ namespace test5 { template <A::Enum en> class bar {}; // expected-error {{'Enum' is a private member of 'test5::A'}} }; } + +namespace test6 { + class A { + public: class public_inner {}; + protected: class protected_inner {}; + private: class private_inner {}; // expected-note {{declared private here}} + }; + + class B : A { + public_inner a; + protected_inner b; + private_inner c; // expected-error {{ 'private_inner' is a private member of 'test6::A'}} + }; +} + +// PR9229 +namespace test7 { + void foo(int arg[1]); + class A { + void check(); + }; + class B { + friend class A; + A ins; + }; + void A::check() { + void foo(int arg[__builtin_offsetof(B, ins)]); + } +} diff --git a/test/CXX/class.derived/class.abstract/p4.cpp b/test/CXX/class.derived/class.abstract/p4.cpp index ca99bf7..b04de21 100644 --- a/test/CXX/class.derived/class.abstract/p4.cpp +++ b/test/CXX/class.derived/class.abstract/p4.cpp @@ -24,7 +24,7 @@ namespace PR6631 { // subobject but not pure in another subobject. namespace PartlyPure { struct A { - virtual void f() = 0; // expected-note{{pure virtual function}} + virtual void f() = 0; // expected-note{{unimplemented pure virtual method}} }; struct B : A { @@ -36,7 +36,7 @@ namespace PartlyPure { struct D : B, C { }; void f() { - (void) new D; // expected-error{{abstract type}} + (void) new D; // expected-error{{abstract class}} } } diff --git a/test/CXX/class.derived/class.abstract/p5.cpp b/test/CXX/class.derived/class.abstract/p5.cpp index 207519d..cdff931 100644 --- a/test/CXX/class.derived/class.abstract/p5.cpp +++ b/test/CXX/class.derived/class.abstract/p5.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s struct A { - virtual void f() = 0; // expected-note{{pure virtual function}} + virtual void f() = 0; // expected-note{{unimplemented pure virtual method}} }; struct B : A { @@ -9,15 +9,15 @@ struct B : A { }; struct C : B { - virtual void f() = 0; // expected-note 2{{pure virtual function}} + virtual void f() = 0; // expected-note 2{{unimplemented pure virtual method}} }; struct D : C { }; void test() { - (void)new A; // expected-error{{object of abstract type}} + (void)new A; // expected-error{{abstract class}} (void)new B; - (void)new C; // expected-error{{object of abstract type}} - (void)new D; // expected-error{{object of abstract type}} + (void)new C; // expected-error{{abstract class}} + (void)new D; // expected-error{{abstract class}} } diff --git a/test/CXX/class.derived/class.member.lookup/p9.cpp b/test/CXX/class.derived/class.member.lookup/p9.cpp new file mode 100644 index 0000000..ba7bd21 --- /dev/null +++ b/test/CXX/class.derived/class.member.lookup/p9.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace rdar8436162 { + class ClsA { + public: + static void f(); + void g(); + }; + + class ClsB : virtual private ClsA { + public: + using ClsA::f; + using ClsA::g; // expected-note{{member found by ambiguous name lookup}} + }; + + class ClsF : virtual private ClsA { + public: + using ClsA::f; + using ClsA::g; // expected-note{{member found by ambiguous name lookup}} + }; + + class ClsE : public ClsB, public ClsF { + void test() { + f(); + g(); // expected-error{{member 'g' found in multiple base classes of different types}} + } + }; +} diff --git a/test/CXX/class.derived/class.virtual/p3-0x.cpp b/test/CXX/class.derived/class.virtual/p3-0x.cpp new file mode 100644 index 0000000..4bd9efd --- /dev/null +++ b/test/CXX/class.derived/class.virtual/p3-0x.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s + +namespace Test1 { + +struct B { + virtual void f(int); +}; + +struct D : B { + virtual void f(long) override; // expected-error {{'f' marked 'override' but does not override any member functions}} + void f(int) override; +}; +} + +namespace Test2 { + +struct A { + virtual void f(int, char, int); +}; + +template<typename T> +struct B : A { + virtual void f(T) override; +}; + +} + +namespace Test3 { + +struct A { + virtual void f(int, char, int); +}; + +template<typename... Args> +struct B : A { + virtual void f(Args...) override; // expected-error {{'f' marked 'override' but does not override any member functions}} +}; + +template struct B<int, char, int>; +template struct B<int>; // expected-note {{in instantiation of template class 'Test3::B<int>' requested here}} + +} + +namespace Test4 { +struct B { + virtual void f() const final; // expected-note {{overridden virtual function is here}} +}; + +struct D : B { + void f() const; // expected-error {{declaration of 'f' overrides a 'final' function}} +}; + +} diff --git a/test/CXX/class.derived/p8-0x.cpp b/test/CXX/class.derived/p8-0x.cpp new file mode 100644 index 0000000..6a667f7 --- /dev/null +++ b/test/CXX/class.derived/p8-0x.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++0x + +namespace Test1 { + +struct A { + virtual void f(); // expected-note {{overridden virtual function is here}} +}; + +struct B explicit : A { + virtual void f(); // expected-error {{overrides function without being marked 'override'}} +}; + +struct C { + virtual ~C(); +}; + +struct D explicit : C { + virtual ~D(); +}; + +} + diff --git a/test/CXX/class/class.friend/p1.cpp b/test/CXX/class/class.friend/p1.cpp index 3ad4a5f..bb1af10 100644 --- a/test/CXX/class/class.friend/p1.cpp +++ b/test/CXX/class/class.friend/p1.cpp @@ -57,7 +57,8 @@ class A { friend A operator|(const A& l, const A& r); // okay friend A operator|(const A& r); // expected-error {{ overloaded 'operator|' must be a binary operator (has 1 parameter) }} - friend operator bool() const; // expected-error {{ must use a qualified name when declaring a conversion operator as a friend }} + friend operator bool() const; // expected-error {{ must use a qualified name when declaring a conversion operator as a friend }} \ + // expected-error{{type qualifier is not allowed on this function}} typedef void ftypedef(); friend ftypedef typedeffed_function; // okay (because it's not declared as a member) diff --git a/test/CXX/class/class.mem/p1.cpp b/test/CXX/class/class.mem/p1.cpp index 55507d4..a41f1db 100644 --- a/test/CXX/class/class.mem/p1.cpp +++ b/test/CXX/class/class.mem/p1.cpp @@ -62,3 +62,30 @@ struct S5 }; + +namespace PR8245 { + class X { + public: + template<class C> + class Inner { + public: + void foo(bool bar = true); + int bam; + }; + + Inner<int> _foo; + }; + + void f() { + X::Inner<int> c2i; + X::Inner<float> c2f; + c2i.foo(); + c2f.foo(); + } + + class Y { + class Inner { + void foo(int = sizeof(Y)); + }; + }; +} diff --git a/test/CXX/class/class.mem/p13.cpp b/test/CXX/class/class.mem/p13.cpp new file mode 100644 index 0000000..7cded23 --- /dev/null +++ b/test/CXX/class/class.mem/p13.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// If T is the name of a class, then each of the following shall have +// a name different from T: + +// - every static data member of class T; +struct X0 { + static int X0; // expected-error{{member 'X0' has the same name as its class}} +}; + +// - every member function of class T +// (Cannot be tested) + +// - every member of class T that is itself a type; +struct X1 { // expected-note{{previous use is here}} + enum X1 { }; // expected-error{{use of 'X1' with tag type that does not match previous declaration}} +}; + +struct X2 { + typedef int X2; // expected-error{{member 'X2' has the same name as its class)}} +}; + +// - every enumerator of every member of class T that is an enumerated type; and +struct X3 { + enum E { + X3 // expected-error{{member 'X3' has the same name as its class}} + }; +}; + +// - every member of every anonymous union that is a member of class T. +struct X4 { + union { + int X; + union { + float Y; + unsigned X4; // expected-error{{member 'X4' has the same name as its class}} + }; + }; +}; + diff --git a/test/CXX/class/class.mem/p14.cpp b/test/CXX/class/class.mem/p14.cpp new file mode 100644 index 0000000..72b232e --- /dev/null +++ b/test/CXX/class/class.mem/p14.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// In addition, if class T has a user-declared constructor (12.1), +// every non-static data member of class T shall have a name different +// from T. + +struct X0 { + int X0; // okay +}; + +struct X1 { + int X1; + X1(); // expected-error{{declarator requires an identifier}} +}; + +struct X2 { + X2(); + float X2; // expected-error{{member 'X2' has the same name as its class}} +}; diff --git a/test/CXX/class/class.mem/p1b.cpp b/test/CXX/class/class.mem/p1b.cpp new file mode 100644 index 0000000..d3493f6 --- /dev/null +++ b/test/CXX/class/class.mem/p1b.cpp @@ -0,0 +1,46 @@ +// The first run checks that the correct errors are generated, +// implicitly checking the order of default argument parsing: +// RUN: %clang_cc1 -fsyntax-only -verify %s +// The second run checks the order of inline method definitions: +// RUN: not %clang_cc1 -fsyntax-only %s 2> %t +// RUN: FileCheck %s < %t + +class A { +public: + void a1() { + B b = B(); + } + + class B; + void a2(B b = B()); // expected-error{{use of default argument to function 'B' that is declared later in class 'B'}} + + void a3(int a = 42); + + // CHEKC: error: use of undeclared identifier 'first' + void a4(int a = first); // expected-error{{use of undeclared identifier 'first'}} + + class B { + public: + B(int b = 42) { // expected-note{{default argument declared here}} + A a; + a.a3(); + a.a6(); + } + + void b1(A a = A()); // expected-error{{use of default argument to function 'A' that is declared later in class 'A'}} + + // CHECK: error: use of undeclared identifier 'second' + void b2(int a = second); // expected-error{{use of undeclared identifier 'second'}} + }; + + void a5() { + B b = B(); + } + + void a6(B b = B()); + + A(int a = 42); // expected-note{{default argument declared here}} + + // CHECK: error: use of undeclared identifier 'third' + void a7(int a = third); // expected-error{{use of undeclared identifier 'third'}} +}; diff --git a/test/CXX/class/class.mem/p8-0x-pedantic.cpp b/test/CXX/class/class.mem/p8-0x-pedantic.cpp new file mode 100644 index 0000000..a4b775c --- /dev/null +++ b/test/CXX/class/class.mem/p8-0x-pedantic.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++0x -pedantic -verify %s + +namespace inline_extension { + struct Base1 { + virtual void f() {} + }; + + struct B : Base1 { + virtual void f() override {} // expected-warning {{'override' keyword only allowed in declarations, allowed as an extension}} + virtual void g() final {} // expected-warning {{'final' keyword only allowed in declarations, allowed as an extension}} + virtual void h() new {} // expected-warning {{'new' keyword only allowed in declarations, allowed as an extension}} + }; +} + diff --git a/test/CXX/class/class.mem/p8-0x.cpp b/test/CXX/class/class.mem/p8-0x.cpp new file mode 100644 index 0000000..bf1b4c1 --- /dev/null +++ b/test/CXX/class/class.mem/p8-0x.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s + +struct Base1 { + virtual void g(); +}; + +struct A : Base1 { + virtual void f() new new; // expected-error {{class member already marked 'new'}} + virtual void g() override override; // expected-error {{class member already marked 'override'}} + virtual void h() final final; // expected-error {{class member already marked 'final'}} +}; + +struct Base2 { + virtual void e1(), e2(); + virtual void f(); +}; + +struct B : Base2 { + virtual void e1() override, e2(int); // No error. + virtual void f() override; + void g() override; // expected-error {{only virtual member functions can be marked 'override'}} + int h override; // expected-error {{only virtual member functions can be marked 'override'}} +}; + +struct C { + virtual void f() final; + void g() final; // expected-error {{only virtual member functions can be marked 'final'}} + int h final; // expected-error {{only virtual member functions can be marked 'final'}} +}; + +namespace inline_extension { + struct Base1 { + virtual void g() {} + }; + + struct A : Base1 { + virtual void f() new new {} // expected-error {{class member already marked 'new'}} + virtual void g() override override {} // expected-error {{class member already marked 'override'}} + virtual void h() final final {} // expected-error {{class member already marked 'final'}} + }; + + struct Base2 { + virtual void f(); + }; + + struct B : Base2 { + virtual void f() override {} + void g() override {} // expected-error {{only virtual member functions can be marked 'override'}} + }; + + struct C { + virtual void f() final {} + void g() final {} // expected-error {{only virtual member functions can be marked 'final'}} + }; +} diff --git a/test/CXX/class/class.nest/p1-cxx0x.cpp b/test/CXX/class/class.nest/p1-cxx0x.cpp new file mode 100644 index 0000000..f8b06ac --- /dev/null +++ b/test/CXX/class/class.nest/p1-cxx0x.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s + +class Outer { + int x; + static int sx; + int f(); + + // The first case is invalid in the C++03 mode but valid in C++0x (see 5.1.1.10). + class Inner { + static char a[sizeof(x)]; // okay + static char b[sizeof(sx)]; // okay + static char c[sizeof(f)]; // expected-error {{ call to non-static member function without an object argument }} + }; +}; diff --git a/test/CXX/class/class.nest/p1.cpp b/test/CXX/class/class.nest/p1.cpp index f1f5496..350cc81 100644 --- a/test/CXX/class/class.nest/p1.cpp +++ b/test/CXX/class/class.nest/p1.cpp @@ -3,12 +3,12 @@ class Outer { int x; static int sx; + int f(); - // C++0x will likely relax this rule in this specific case, but - // we'll still need to enforce it in C++03 mode. See N2253 (or - // successor). + // C++0x does relax this rule (see 5.1.1.10) in the first case, but we need to enforce it in C++03 mode. class Inner { static char a[sizeof(x)]; // expected-error {{ invalid use of nonstatic data member 'x' }} static char b[sizeof(sx)]; // okay + static char c[sizeof(f)]; // expected-error {{ call to non-static member function without an object argument }} }; }; diff --git a/test/CXX/class/class.union/p1.cpp b/test/CXX/class/class.union/p1.cpp index e974d82..b5dd4df 100644 --- a/test/CXX/class/class.union/p1.cpp +++ b/test/CXX/class/class.union/p1.cpp @@ -90,6 +90,14 @@ union U3 { } m7; }; +union U4 { + static int i1; // expected-error {{static data member 'i1' not allowed in union}} +}; + +union U5 { + int& i1; // expected-error {{union member 'i1' has reference type 'int &'}} +}; + template <class A, class B> struct Either { bool tag; union { diff --git a/test/CXX/class/p1-0x.cpp b/test/CXX/class/p1-0x.cpp new file mode 100644 index 0000000..5851de6 --- /dev/null +++ b/test/CXX/class/p1-0x.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +namespace Test1 { + +class A final { }; +class B explicit { }; +class C final explicit { }; +class D final final { }; // expected-error {{class already marked 'final'}} +class E explicit explicit { }; // expected-error {{class already marked 'explicit'}} + +} diff --git a/test/CXX/class/p2-0x.cpp b/test/CXX/class/p2-0x.cpp new file mode 100644 index 0000000..630aa7e --- /dev/null +++ b/test/CXX/class/p2-0x.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +namespace Test1 { + +class A final { }; // expected-note {{'A' declared here}} +class B : A { }; // expected-error {{base 'A' is marked 'final'}} + +} + +namespace Test2 { + +template<typename T> struct A final { }; // expected-note 2 {{'A' declared here}} +struct B : A<int> { }; // expected-error {{base 'A' is marked 'final'}} + +template<typename T> struct C : A<T> { }; // expected-error {{base 'A' is marked 'final'}} +struct D : C<int> { }; // expected-note {{in instantiation of template class 'Test2::C<int>' requested here}} + +} + +namespace Test3 { + +template<typename T> struct A { }; +template<> struct A<int> final { }; // expected-note {{'A' declared here}} + +struct B : A<bool> { }; +struct C : A<int> { }; // expected-error {{base 'A' is marked 'final'}} + +} + diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp index ddcbe78..069ca0a 100644 --- a/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only %s +// RUN: %clang_cc1 -fsyntax-only %s -verify // C++'0x [namespace.memdef] p3: // Every name first declared in a namespace is a member of that namespace. If @@ -66,3 +66,28 @@ namespace N3 { } // FIXME: Woefully inadequate for testing + +// Friends declared as template-ids aren't subject to the restriction +// on innermost namespaces. +// rdar://problem/8552377 +namespace test5 { + template <class T> void f(T); + namespace ns { + class A { + friend void f<int>(int); + static void foo(); // expected-note 2 {{declared private here}} + }; + + // Note that this happens without instantiation. + template <class T> void f(T) { + A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}} + } + } + + template <class T> void f(T) { + ns::A::foo(); // expected-error {{'foo' is a private member of 'test5::ns::A'}} + } + + template void f<int>(int); + template void f<long>(long); //expected-note {{instantiation}} +} diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/p2.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p2.cpp new file mode 100644 index 0000000..411c16c --- /dev/null +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p2.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR8430 +namespace N { + class A { }; +} + +namespace M { } + +using namespace M; + +namespace N { + namespace M { + } +} + +namespace M { + namespace N { + } +} + +namespace N { + A *getA(); +} diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp index bb1d67f..634369d 100644 --- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp @@ -89,6 +89,7 @@ namespace test2 { namespace test3 { class A { + public: ~A(); }; diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp index 082a32d..24780c6 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp @@ -1,6 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x void f() { auto a = a; // expected-error{{variable 'a' declared with 'auto' type cannot appear in its own initializer}} + auto *b = b; // expected-error{{variable 'b' declared with 'auto' type cannot appear in its own initializer}} + const auto c = c; // expected-error{{variable 'c' declared with 'auto' type cannot appear in its own initializer}} } void g() { @@ -8,3 +10,32 @@ void g() { auto *b; // expected-error{{declaration of variable 'b' with type 'auto *' requires an initializer}} } + +auto n(1,2,3); // expected-error{{initializer for variable 'n' with type 'auto' contains multiple expressions}} + +namespace N +{ + auto a = "const char [16]", *p = &a; +} + +void h() { + auto b = 42ULL; + + for (auto c = 0; c < 100; ++c) { + } +} + +template<typename T, typename U> struct same; +template<typename T> struct same<T, T> {}; + +void p3example() { + auto x = 5; + const auto *v = &x, u = 6; + static auto y = 0.0; + auto int r; // expected-error{{cannot combine with previous}} expected-error{{requires an initializer}} + + same<decltype(x), int> xHasTypeInt; + same<decltype(v), const int*> vHasTypeConstIntPtr; + same<decltype(u), const int> uHasTypeConstInt; + same<decltype(y), double> yHasTypeDouble; +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp new file mode 100644 index 0000000..34a1784 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x + +template<typename T> +struct only { + only(T); + template<typename U> only(U) = delete; +}; + +void f() { + if (auto a = true) { + } + + switch (auto a = 0) { + } + + while (auto a = false) { + } + + for (; auto a = false; ) { + } + + new const auto (0); + new (auto) (0.0); + +#if 0 + // When clang supports for-range: + for (auto i : {1,2,3}) { + } + + // When clang supports inline initialization of members. + class X { + static const auto &n = 'x'; + }; +#endif +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp index e739254..836ccda 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp @@ -1,13 +1,72 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x -void f() { - auto a = a; // expected-error{{variable 'a' declared with 'auto' type cannot appear in its own initializer}} +// RUN: %clang_cc1 -fexceptions -fsyntax-only -verify %s -std=c++0x + +struct S { + virtual ~S(); + + auto a; // expected-error{{'auto' not allowed in struct member}} + auto *b; // expected-error{{'auto' not allowed in struct member}} + const auto c; // expected-error{{'auto' not allowed in struct member}} + + void f() throw (auto); // expected-error{{'auto' not allowed here}} + + friend auto; // expected-error{{'auto' not allowed in struct member}} + + operator auto(); // expected-error{{'auto' not allowed here}} +}; + +void g(auto a) { // expected-error{{'auto' not allowed in function prototype}} + try { } + catch (auto &a) { } // expected-error{{'auto' not allowed in exception declaration}} + catch (const auto a) { } // expected-error{{'auto' not allowed in exception declaration}} + try { } catch (auto a) { } // expected-error{{'auto' not allowed in exception declaration}} +} + +void h(auto a[10]) { // expected-error{{'auto' not allowed in function prototype}} } -struct S { auto a; }; // expected-error{{'auto' not allowed in struct member}} +void i(const auto a) { // expected-error{{'auto' not allowed in function prototype}} +} -void f(auto a) // expected-error{{'auto' not allowed in function prototype}} -{ - try { } catch (auto a) { } // expected-error{{'auto' not allowed in exception declaration}} +namespace std { + class type_info; +} + +template<typename T> struct U {}; + +void j() { + (void)typeid(auto); // expected-error{{'auto' not allowed here}} + (void)sizeof(auto); // expected-error{{'auto' not allowed here}} + (void)__alignof(auto); // expected-error{{'auto' not allowed here}} + + // FIXME: don't issue the second diagnostic for this error. + U<auto> v; // expected-error{{'auto' not allowed in template argument}} unexpected-error{{C++ requires a type specifier}} + + int n; + (void)dynamic_cast<auto&>(S()); // expected-error{{'auto' not allowed here}} + (void)static_cast<auto*>(&n); // expected-error{{'auto' not allowed here}} + (void)reinterpret_cast<auto*>(&n); // expected-error{{'auto' not allowed here}} + (void)const_cast<auto>(n); // expected-error{{'auto' not allowed here}} + (void)*(auto*)(&n); // expected-error{{'auto' not allowed here}} + (void)auto(n); // expected-error{{expected expression}} + (void)auto{n}; // expected-error{{expected expression}} } template <auto a = 10> class C { }; // expected-error{{'auto' not allowed in template parameter}} +int ints[] = {1, 2, 3}; +template <const auto (*a)[3] = &ints> class D { }; // expected-error{{'auto' not allowed in template parameter}} +enum E : auto {}; // expected-error{{'auto' not allowed here}} +struct F : auto {}; // expected-error{{expected class name}} +template<typename T = auto> struct G { }; // expected-error{{'auto' not allowed here}} + +using A = auto; // expected-error{{expected ';'}} expected-error{{requires a qualified name}} + +// Whether this is illegal depends on the interpretation of [decl.spec.auto]p2 and p3, +// and in particular the "Otherwise, ..." at the start of p3. +namespace TrailingReturnType { + // FIXME: don't issue the second diagnostic for this error. + auto f() -> auto; // expected-error{{'auto' not allowed here}} unexpected-error{{without trailing return type}} + int g(); + auto (*h)() -> auto = &g; // expected-error{{'auto' not allowed here}} + auto (*i)() = &g; // ok; auto deduced as int. + auto (*j)() -> int = i; // ok; no deduction. +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp new file mode 100644 index 0000000..06aeaa6 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x + +template<typename T> +struct only { + only(T); + template<typename U> only(U) = delete; +}; + +namespace N +{ + auto a = "const char [16]", *p = &a; + + only<const char [16]> testA = a; + only<const char **> testP = p; +} + +void h() { + auto b = 42ULL; + only<unsigned long long> testB = b; + + for (auto c = 0; c < 100; ++c) { + only<int> testC = c; + } +} + +void p3example() { + auto x = 5; + const auto *v = &x, u = 6; + static auto y = 0.0; + + only<int> testX = x; + only<const int*> testV = v; + only<const int> testU = u; + only<double> testY = y; +} + +void f() { + if (auto a = true) { + only<bool> testA = a; + } + + switch (auto a = 0) { + case 0: + only<int> testA = a; + } + + while (auto a = false) { + only<bool> testA = a; + } + + for (; auto a = "test"; ) { + only<const char[5]> testA = a; + } + + auto *fail1 = 0; // expected-error {{variable 'fail1' with type 'auto *' has incompatible initializer of type 'int'}} + int **p; + // FIXME: due to PR9233, we get the wrong diagnostic here. + const auto **fail2(p); // desired-error {{variable 'fail2' with type 'auto const **' has incompatible initializer of type 'int **'}} expected-error {{cannot initialize}} +} + +struct S { + void f(); + char g(int); + float g(double); + int m; + + void test() { + auto p1 = &S::f; + auto S::*p2 = &S::f; + auto (S::*p3)() = &S::f; + auto p4 = &S::g; // expected-error {{incompatible initializer of type '<overloaded function type>'}} + auto S::*p5 = &S::g; // expected-error {{incompatible initializer of type '<overloaded function type>'}} + auto (S::*p6)(int) = &S::g; + auto p7 = &S::m; + auto S::*p8 = &S::m; + + only<void (S::*)()> test1 = p1; + only<void (S::*)()> test2 = p2; + only<void (S::*)()> test3 = p3; + only<char (S::*)(int)> test6 = p6; + only<int (S::*)> test7 = p7; + only<int (S::*)> test8 = p8; + } +}; + +// TODO: if the initializer is a braced-init-list, deduce auto as std::initializer_list<T>. diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp new file mode 100644 index 0000000..de87a93 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x +void f() { + auto a = 0, b = 0, c = 0; + auto d = 0, e = 0.0; // expected-error {{'int' in declaration of 'd' and deduced as 'double' in declaration of 'e'}} + + auto v1 = 0, *p1 = &v1; + auto *p2 = 0, v2 = *p2; // expected-error {{incompatible initializer}} + + const int k = 0; + auto &f = k, &g = a; // expected-error {{'const int' in declaration of 'f' and deduced as 'int' in declaration of 'g'}} + + typedef int I; + I x; + auto xa = x, xb = 0; + + auto &&ra1 = a, rb1 = b; // expected-error {{'int &' in declaration of 'ra1' and deduced as 'int' in declaration of 'rb1'}} + auto &&ra2 = +a, rb2 = b; +} + +void g() { + auto a = 0, (*b)() -> void, c = 0; + auto d = 0, (*e)() -> void, f = 0.0; // expected-error {{'auto' deduced as 'int' in declaration of 'd' and deduced as 'double' in declaration of 'f'}} +} diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp new file mode 100644 index 0000000..7b0fb9c --- /dev/null +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp @@ -0,0 +1,164 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify -pedantic %s + +// Test the C++0x-specific reference initialization rules, e.g., the +// rules for rvalue references. +template<typename T> T prvalue(); +template<typename T> T&& xvalue(); +template<typename T> T& lvalue(); + +struct Base { }; +struct Derived : Base { }; + +struct HasArray { + int array[5]; +}; + +int f(int); + +template<typename T> +struct ConvertsTo { + operator T(); // expected-note 4{{candidate function}} +}; + +void test_rvalue_refs() { + // If the initializer expression... + // - is an xvalue, class prvalue, array prvalue or function lvalue + // and "cv1 T1" is reference-compatible with "cv2 T2", or + + // xvalue case + Base&& base0 = xvalue<Base>(); + Base&& base1 = xvalue<Derived>(); + int&& int0 = xvalue<int>(); + + // class prvalue case + Base&& base2 = prvalue<Base>(); + Base&& base3 = prvalue<Derived>(); + + // array prvalue case + int (&&array0)[5] = HasArray().array; + + // function lvalue case + int (&&function0)(int) = f; + + // - has a class type (i.e., T2 is a class type), where T1 is not + // reference-related to T2, and can be implicitly converted to + // an xvalue, class prvalue, or function lvalue of type "cv3 + // T3", where "cv1 T1" is reference-compatible with "cv3 T3", + + // xvalue + Base&& base4 = ConvertsTo<Base&&>(); + Base&& base5 = ConvertsTo<Derived&&>(); + int && int1 = ConvertsTo<int&&>(); + + // class prvalue + Base&& base6 = ConvertsTo<Base>(); + Base&& base7 = ConvertsTo<Derived>(); + + // function lvalue + int (&&function1)(int) = ConvertsTo<int(&)(int)>(); + + // In the second case, if the reference is an rvalue reference and + // the second standard conversion sequence of the user-defined + // conversion sequence includes an lvalue-to-rvalue conversion, the + // program is ill-formed. + int &&int2 = ConvertsTo<int&>(); // expected-error{{no viable conversion from 'ConvertsTo<int &>' to 'int'}} + int &&int3 = ConvertsTo<float&>(); // expected-error{{no viable conversion from 'ConvertsTo<float &>' to 'int'}} +} + +class NonCopyable { + NonCopyable(const NonCopyable&); +}; + +class NonCopyableDerived : public NonCopyable { + NonCopyableDerived(const NonCopyableDerived&); +}; + +// Make sure we get direct bindings with no copies. +void test_direct_binding() { + NonCopyable &&nc0 = prvalue<NonCopyable>(); + NonCopyable &&nc1 = prvalue<NonCopyableDerived>(); + NonCopyable &&nc2 = xvalue<NonCopyable>(); + NonCopyable &&nc3 = xvalue<NonCopyableDerived>(); + const NonCopyable &nc4 = prvalue<NonCopyable>(); + const NonCopyable &nc5 = prvalue<NonCopyableDerived>(); + const NonCopyable &nc6 = xvalue<NonCopyable>(); + const NonCopyable &nc7 = xvalue<NonCopyableDerived>(); + NonCopyable &&nc8 = ConvertsTo<NonCopyable&&>(); + NonCopyable &&nc9 = ConvertsTo<NonCopyableDerived&&>(); + const NonCopyable &nc10 = ConvertsTo<NonCopyable&&>(); + const NonCopyable &nc11 = ConvertsTo<NonCopyableDerived&&>(); +} + +namespace std_example_1 { + double d = 2.0; + double& rd = d; + const double& rcd = d; + struct A { }; + struct B : A { + operator int&(); + } b; + A& ra = b; + const A& rca = b; + int& ir = B(); +} + +namespace std_example_2 { + double& rd2 = 2.0; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a temporary of type 'double'}} + int i = 2; + double& rd3 = i; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a value of unrelated type 'int'}} + struct A { }; + struct B : A { } b; + extern B f(); + const A& rca = f(); + A&& rra = f(); + struct X { + operator B(); // expected-note{{candidate function}} + operator int&(); // expected-note{{candidate function}} + } x; + const A& r = x; + int&& rri = static_cast<int&&>(i); + B&& rrb = x; + int&& rri2 = X(); // expected-error{{no viable conversion from 'std_example_2::X' to 'int'}} + + const double& rcd2 = 2; + double&& rrd = 2; + const volatile int cvi = 1; + const int& r2 = cvi; // expected-error{{binding of reference to type 'const int' to a value of type 'const volatile int' drops qualifiers}} + + double d; + double&& rrd2 = d; // expected-error{{rvalue reference to type 'double' cannot bind to lvalue of type 'double'}} + double&& rrd3 = i; +} + +namespace argument_passing { + void base_rvalue_ref(Base&&); + void int_rvalue_ref(int&&); // expected-note 2{{passing argument to parameter here}} + void array_rvalue_ref(int (&&)[5]); + void function_rvalue_ref(int (&&)(int)); + + void test() { + base_rvalue_ref(xvalue<Base>()); + base_rvalue_ref(xvalue<Derived>()); + int_rvalue_ref(xvalue<int>()); + + base_rvalue_ref(prvalue<Base>()); + base_rvalue_ref(prvalue<Derived>()); + + array_rvalue_ref(HasArray().array); + + function_rvalue_ref(f); + + base_rvalue_ref(ConvertsTo<Base&&>()); + base_rvalue_ref(ConvertsTo<Derived&&>()); + int_rvalue_ref(ConvertsTo<int&&>()); + + base_rvalue_ref(ConvertsTo<Base>()); + base_rvalue_ref(ConvertsTo<Derived>()); + + function_rvalue_ref(ConvertsTo<int(&)(int)>()); + + int_rvalue_ref(ConvertsTo<int&>()); // expected-error{{no viable conversion from 'ConvertsTo<int &>' to 'int'}} + int_rvalue_ref(ConvertsTo<float&>()); // expected-error{{no viable conversion from 'ConvertsTo<float &>' to 'int'}} + } + +} diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp index ae59598..8c65411 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp @@ -53,7 +53,7 @@ void g4(const X4<int>&); void g5(const X5&); void test() { - g1(X1()); // expected-warning{{no viable constructor copying parameter of type 'X1'; C++98 requires a copy constructor when binding a reference to a temporary [-Wbind-to-temporary-copy]}} + g1(X1()); g2(X2()); // expected-warning{{C++98 requires an accessible copy constructor for class 'X2' when binding a reference to a temporary; was private [-Wbind-to-temporary-copy]}} g3(X3()); // expected-warning{{no viable constructor copying parameter of type 'X3'}} g4(X4<int>()); diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp index 9b39259..08d9639 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp @@ -6,8 +6,8 @@ void example0() { // CHECK: double &rd = // CHECK-NEXT: DeclRefExpr double &rd = d; - // CHECK: double const &rcd = - // CHECK-NEXT: ImplicitCastExpr{{.*}}'double const' <NoOp> + // CHECK: const double &rcd = + // CHECK-NEXT: ImplicitCastExpr{{.*}}'const double' lvalue <NoOp> const double &rcd = d; } @@ -17,11 +17,11 @@ struct B : A { } b; // CHECK: example1 void example1() { // CHECK: A &ra = - // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)> lvalue + // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue <DerivedToBase (A)> A &ra = b; - // CHECK: A const &rca = - // CHECK: ImplicitCastExpr{{.*}}'struct A const' <NoOp> - // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)> + // CHECK: const A &rca = + // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <NoOp> + // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue <DerivedToBase (A)> const A& rca = b; } @@ -33,13 +33,13 @@ struct X { // CHECK: example2 void example2() { - // CHECK: A const &rca = - // CHECK: ImplicitCastExpr{{.*}}'struct A const' <NoOp> + // CHECK: const A &rca = + // CHECK: ImplicitCastExpr{{.*}}'const struct A' <NoOp> // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)> // CHECK: CallExpr{{.*}}B const A &rca = f(); - // CHECK: A const &r = - // CHECK: ImplicitCastExpr{{.*}}'struct A const' <NoOp> + // CHECK: const A &r = + // CHECK: ImplicitCastExpr{{.*}}'const struct A' <NoOp> // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)> // CHECK: CXXMemberCallExpr{{.*}}'struct B' const A& r = x; @@ -47,7 +47,7 @@ void example2() { // CHECK: example3 void example3() { - // CHECK: double const &rcd2 = - // CHECK: ImplicitCastExpr{{.*}}<IntegralToFloating> + // CHECK: const double &rcd2 = + // CHECK: ImplicitCastExpr{{.*}} <IntegralToFloating> const double& rcd2 = 2; } diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp index 6a039b9..fee5f96 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -struct Base { }; // expected-note{{candidate is the implicit copy constructor}} +struct Base { }; struct Derived : Base { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}} struct Unrelated { }; struct Derived2 : Base { }; @@ -64,10 +64,10 @@ void bind_lvalue_quals(volatile Base b, volatile Derived d, volatile const int ivc) { volatile Base &bvr1 = b; volatile Base &bvr2 = d; - volatile Base &bvr3 = bvc; // expected-error{{binding of reference to type 'Base volatile' to a value of type 'Base const volatile' drops qualifiers}} - volatile Base &bvr4 = dvc; // expected-error{{binding of reference to type 'Base volatile' to a value of type 'Derived const volatile' drops qualifiers}} + volatile Base &bvr3 = bvc; // expected-error{{binding of reference to type 'volatile Base' to a value of type 'const volatile Base' drops qualifiers}} + volatile Base &bvr4 = dvc; // expected-error{{binding of reference to type 'volatile Base' to a value of type 'const volatile Derived' drops qualifiers}} - volatile int &ir = ivc; // expected-error{{binding of reference to type 'int volatile' to a value of type 'int const volatile' drops qualifiers}} + volatile int &ir = ivc; // expected-error{{binding of reference to type 'volatile int' to a value of type 'const volatile int' drops qualifiers}} const volatile Base &bcvr1 = b; const volatile Base &bcvr2 = d; @@ -76,15 +76,15 @@ void bind_lvalue_quals(volatile Base b, volatile Derived d, void bind_lvalue_to_rvalue() { Base &br1 = Base(); // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a temporary of type 'Base'}} Base &br2 = Derived(); // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a temporary of type 'Derived'}} - const volatile Base &br3 = Base(); // expected-error{{volatile lvalue reference to type 'Base const volatile' cannot bind to a temporary of type 'Base'}} - const volatile Base &br4 = Derived(); // expected-error{{volatile lvalue reference to type 'Base const volatile' cannot bind to a temporary of type 'Derived'}} + const volatile Base &br3 = Base(); // expected-error{{volatile lvalue reference to type 'const volatile Base' cannot bind to a temporary of type 'Base'}} + const volatile Base &br4 = Derived(); // expected-error{{volatile lvalue reference to type 'const volatile Base' cannot bind to a temporary of type 'Derived'}} int &ir = 17; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}} } void bind_lvalue_to_unrelated(Unrelated ur) { Base &br1 = ur; // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a value of unrelated type 'Unrelated'}} - const volatile Base &br2 = ur; // expected-error{{volatile lvalue reference to type 'Base const volatile' cannot bind to a value of unrelated type 'Unrelated'}} + const volatile Base &br2 = ur; // expected-error{{volatile lvalue reference to type 'const volatile Base' cannot bind to a value of unrelated type 'Unrelated'}} } void bind_lvalue_to_conv_lvalue() { @@ -118,8 +118,8 @@ void bind_const_lvalue_to_rvalue() { const Base &br3 = create<const Base>(); const Base &br4 = create<const Derived>(); - const Base &br5 = create<const volatile Base>(); // expected-error{{binding of reference to type 'Base const' to a value of type 'Base const volatile' drops qualifiers}} - const Base &br6 = create<const volatile Derived>(); // expected-error{{binding of reference to type 'Base const' to a value of type 'Derived const volatile' drops qualifiers}} + const Base &br5 = create<const volatile Base>(); // expected-error{{binding of reference to type 'const Base' to a value of type 'const volatile Base' drops qualifiers}} + const Base &br6 = create<const volatile Derived>(); // expected-error{{binding of reference to type 'const Base' to a value of type 'const volatile Derived' drops qualifiers}} const int &ir = create<int>(); } @@ -131,5 +131,5 @@ void bind_const_lvalue_to_class_conv_temporary() { } void bind_lvalue_to_conv_rvalue_ambig(ConvertibleToBothDerived both) { const Derived &dr1 = both; - const Base &br1 = both; // expected-error{{reference initialization of type 'Base const &' with initializer of type 'ConvertibleToBothDerived' is ambiguous}} + const Base &br1 = both; // expected-error{{reference initialization of type 'const Base &' with initializer of type 'ConvertibleToBothDerived' is ambiguous}} } diff --git a/test/CXX/dcl.decl/dcl.init/p6.cpp b/test/CXX/dcl.decl/dcl.init/p6.cpp index c542dac..da6f5b5 100644 --- a/test/CXX/dcl.decl/dcl.init/p6.cpp +++ b/test/CXX/dcl.decl/dcl.init/p6.cpp @@ -10,7 +10,7 @@ struct NoUserDefault : public MakeNonPOD { }; struct HasUserDefault { HasUserDefault(); }; void test_const_default_init() { - const NoUserDefault x1; // expected-error{{default initialization of an object of const type 'NoUserDefault const' requires a user-provided default constructor}} + const NoUserDefault x1; // expected-error{{default initialization of an object of const type 'const NoUserDefault' requires a user-provided default constructor}} const HasUserDefault x2; - const int x3; // expected-error{{default initialization of an object of const type 'int const'}} + const int x3; // expected-error{{default initialization of an object of const type 'const int'}} } diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1-cxx0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1-cxx0x.cpp index 00e59e0..b0575b8 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1-cxx0x.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1-cxx0x.cpp @@ -3,4 +3,5 @@ void f() { int b[5]; auto a[5] = b; // expected-error{{'a' declared as array of 'auto'}} + auto *c[5] = b; // expected-error{{'c' declared as array of 'auto *'}} } diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp index ac0ec85..bb4a48e 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp @@ -5,7 +5,7 @@ int ar1[10]; // Element type cannot be: // - (cv) void -volatile void ar2[10]; // expected-error {{incomplete element type 'void volatile'}} +volatile void ar2[10]; // expected-error {{incomplete element type 'volatile void'}} // - a reference int& ar3[10]; // expected-error {{array of references}} // - a function type @@ -16,7 +16,7 @@ struct Abstract { virtual void fn() = 0; }; // expected-note {{pure virtual}} Abstract ar5[10]; // expected-error {{abstract class}} // If we have a size, it must be greater than zero. -int ar6[-1]; // expected-error {{array size is negative}} +int ar6[-1]; // expected-error {{array with a negative size}} int ar7[0u]; // expected-warning {{zero size arrays are an extension}} // An array with unknown bound is incomplete. @@ -42,3 +42,13 @@ template <typename T> struct S { typename T::type x; // expected-error {{has no members}} }; S<int> ar10[10]; // expected-note {{requested here}} + +// Ensure that negative array size errors include the name of the declared +// array as this is often used to simulate static_assert with template +// instantiations, placing the 'error message' in the declarator name. +int +user_error_message +[-1]; // expected-error {{user_error_message}} +typedef int +another_user_error_message +[-1]; // expected-error {{another_user_error_message}} diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp new file mode 100644 index 0000000..5fb35ba --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -fexceptions -verify %s + +// When it is part of a parameter-declaration-clause, the parameter +// pack is a function parameter pack. +template<typename ...Types> +void f0(Types ...args); + +template<typename ...Types> +void f1(const Types &...args); + +// [ Note: Otherwise, the parameter-declaration is part of a +// template-parameter-list and the parameter pack is a template +// parameter pack; see 14.1. -- end note ] +template<int ...N> +struct X0 { }; + +template<typename ...Types> +struct X1 { + template<Types ...Values> struct Inner; +}; + +// A declarator-id or abstract-declarator containing an ellipsis shall +// only be used in a parameter-declaration. +int (...f2)(int); // expected-error{{only function and template parameters can be parameter packs}} + +void f3() { + int ...x; // expected-error{{only function and template parameters can be parameter packs}} + if (int ...y = 17) { } // expected-error{{only function and template parameters can be parameter packs}} + + for (int ...z = 0; z < 10; ++z) { } // expected-error{{only function and template parameters can be parameter packs}} + + try { + } catch (int ...e) { // expected-error{{only function and template parameters can be parameter packs}} + } +} + +template<typename ...Types> +struct X2 { + Types ...members; // expected-error{{only function and template parameters can be parameter packs}} \ + // expected-error{{data member type contains unexpanded parameter pack}} +}; + +// The type T of the declarator-id of the function parameter pack +// shall contain a template parameter pack; each template parameter +// pack in T is expanded by the function parameter pack. +template<typename T> +void f4(T ...args); // expected-error{{type 'T' of function parameter pack does not contain any unexpanded parameter packs}} + diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp new file mode 100644 index 0000000..1293a06 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template<typename T> struct identity; +template<typename ...Types> struct tuple; + +template<typename T, typename U> struct is_same { + static const bool value = false; +}; + +template<typename T> struct is_same<T, T> { + static const bool value = true; +}; + +// There is a syntactic ambiguity when an ellipsis occurs at the end +// of a parameter-declaration-clause without a preceding comma. In +// this case, the ellipsis is parsed as part of the +// abstract-declarator if the type of the parameter names a template +// parameter pack that has not been expanded; otherwise, it is parsed +// as part of the parameter-declaration-clause. + +template<typename T, typename ...Types> +struct X0 { + typedef identity<T(Types...)> function_pack_1; + typedef identity<T(Types......)> variadic_function_pack_1; + typedef identity<T(T...)> variadic_1; + typedef tuple<T(Types, ...)...> template_arg_expansion_1; +}; + + + +// FIXME: Once function parameter packs are implemented, we can test all of the disambiguation diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp new file mode 100644 index 0000000..4dc393d --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +auto a() -> int; // ok +const auto b() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not 'auto const'}} +auto *c() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not 'auto *'}} diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp new file mode 100644 index 0000000..c81c844 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +void f0() &; // expected-error{{ref-qualifier '&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}} +void f1() &&; // expected-error{{ref-qualifier '&&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}} + +struct X { + void f0() &; + void f1() &&; + static void f2() &; // expected-error{{ref-qualifier '&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}} + static void f3() &&; // expected-error{{ref-qualifier '&&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}} +}; + +typedef void func_type_lvalue() &; +typedef void func_type_rvalue() &&; + +func_type_lvalue f2; // expected-error{{nonmember function cannot have a ref-qualifier '&'}} +func_type_rvalue f3; // expected-error{{nonmember function cannot have a ref-qualifier '&&'}} + +struct Y { + func_type_lvalue f0; + func_type_rvalue f1; +}; + +void (X::*mpf1)() & = &X::f0; +void (X::*mpf2)() && = &X::f1; + + +void (f() &&); // expected-error{{ref-qualifier '&&' is only allowed on non-static member functions, member function pointers, and typedefs of function types}} diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp new file mode 100644 index 0000000..4873c09 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f() const; // expected-error{{type qualifier is not allowed on this function}} + +struct X { + void f() const; + friend void g() const; // expected-error{{type qualifier is not allowed on this function}} + static void h() const; // expected-error{{type qualifier is not allowed on this function}} +}; + +struct Y { + friend void X::f() const; + friend void ::f() const; // expected-error{{type qualifier is not allowed on this function}} +}; diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp new file mode 100644 index 0000000..34a8c85 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A { }; +A::A (enum { e1 }) {} // expected-error{{can not be defined in a parameter}} \ +// expected-error{{out-of-line definition}} +void A::f(enum { e2 }) {} // expected-error{{can not be defined in a parameter}} \ +// expected-error{{out-of-line definition}} + +enum { e3 } A::g() { } // expected-error{{can not be defined in the result type}} \ +// expected-error{{out-of-line definition}} diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp new file mode 100644 index 0000000..789cde7 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; +#define JOIN2(X,Y) X##Y +#define JOIN(X,Y) JOIN2(X,Y) +#define CHECK_EQUAL_TYPES(T1, T2) \ + int JOIN(array,__LINE__)[is_same<T1, T2>::value? 1 : -1] + +int i; +typedef int& LRI; +typedef int&& RRI; + +typedef LRI& r1; CHECK_EQUAL_TYPES(r1, int&); +typedef const LRI& r2; CHECK_EQUAL_TYPES(r2, int&); +typedef const LRI&& r3; CHECK_EQUAL_TYPES(r3, int&); + +typedef RRI& r4; CHECK_EQUAL_TYPES(r4, int&); +typedef RRI&& r5; CHECK_EQUAL_TYPES(r5, int&&); diff --git a/test/CXX/dcl.decl/p4-0x.cpp b/test/CXX/dcl.decl/p4-0x.cpp new file mode 100644 index 0000000..9fa2ea1 --- /dev/null +++ b/test/CXX/dcl.decl/p4-0x.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct X { + void f() &; + void g() &&; +}; + +void (X::*pmf)() & = &X::f; diff --git a/test/CXX/except/except.handle/p16.cpp b/test/CXX/except/except.handle/p16.cpp index 4950a2f..24f0db0 100644 --- a/test/CXX/except/except.handle/p16.cpp +++ b/test/CXX/except/except.handle/p16.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fexceptions -fsyntax-only -verify %s // The object declared in an exception-declaration or, if the // exception-declaration does not specify a name, a temporary (12.2) diff --git a/test/CXX/except/except.spec/p14-ir.cpp b/test/CXX/except/except.spec/p14-ir.cpp index 4d8d1f7..c681727 100644 --- a/test/CXX/except/except.spec/p14-ir.cpp +++ b/test/CXX/except/except.spec/p14-ir.cpp @@ -26,17 +26,17 @@ struct X4 { struct X5 : X0, X4 { }; void test(X2 x2, X3 x3, X5 x5) { - // CHECK: define linkonce_odr void @_ZN2X2C1ERKS_ + // CHECK: define linkonce_odr void @_ZN2X2C1ERKS_(%struct.X0* %this, %struct.X0*) unnamed_addr // CHECK: call void @_ZN2X2C2ERKS_({{.*}}) nounwind // CHECK-NEXT: ret void // CHECK-NEXT: } X2 x2a(x2); - // CHECK: define linkonce_odr void @_ZN2X3C1ERKS_ + // CHECK: define linkonce_odr void @_ZN2X3C1ERKS_(%struct.X0* %this, %struct.X0*) unnamed_addr // CHECK: call void @_ZN2X3C2ERKS_({{.*}}) nounwind // CHECK-NEXT: ret void // CHECK-NEXT: } X3 x3a(x3); - // CHECK: define linkonce_odr void @_ZN2X5C1ERS_ + // CHECK: define linkonce_odr void @_ZN2X5C1ERS_({{.*}}) unnamed_addr // CHECK-NOT: call void @__cxa_call_unexpected // CHECK: ret void X5 x5a(x5); @@ -55,24 +55,24 @@ struct X8 : X6 { }; struct X9 : X6, X7 { }; void test() { - // CHECK: define linkonce_odr void @_ZN2X8C1Ev + // CHECK: define linkonce_odr void @_ZN2X8C1Ev(%struct.X0* %this) unnamed_addr // CHECK: call void @_ZN2X8C2Ev({{.*}}) nounwind // CHECK-NEXT: ret void X8(); - // CHECK: define linkonce_odr void @_ZN2X9C1Ev + // CHECK: define linkonce_odr void @_ZN2X9C1Ev(%struct.X0* %this) unnamed_addr // FIXME: check that this is the end of the line here: // CHECK: call void @_ZN2X9C2Ev({{.*}}) // CHECK-NEXT: ret void X9(); - // CHECK: define linkonce_odr void @_ZN2X9C2Ev + // CHECK: define linkonce_odr void @_ZN2X9C2Ev(%struct.X0* %this) unnamed_addr // CHECK: call void @_ZN2X6C2Ev({{.*}}) nounwind // FIXME: and here: // CHECK-NEXT: call void @_ZN2X7C2Ev({{.*}}) // CHECK: ret void - // CHECK: define linkonce_odr void @_ZN2X8C2Ev + // CHECK: define linkonce_odr void @_ZN2X8C2Ev(%struct.X0* %this) unnamed_addr // CHECK: call void @_ZN2X6C2Ev({{.*}}) nounwind // CHECK-NEXT: ret void } diff --git a/test/CXX/expr/expr.cast/p4-0x.cpp b/test/CXX/expr/expr.cast/p4-0x.cpp new file mode 100644 index 0000000..5824cd2 --- /dev/null +++ b/test/CXX/expr/expr.cast/p4-0x.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct X { }; +struct Y : X { }; + +void test_lvalue_to_rvalue_drop_cvquals(const X &x, const Y &y, const int &i) { + (void)(X&&)x; + (void)(int&&)i; + (void)(X&&)y; + (void)(Y&&)x; +} diff --git a/test/CXX/expr/expr.cast/p4.cpp b/test/CXX/expr/expr.cast/p4.cpp new file mode 100644 index 0000000..907e008 --- /dev/null +++ b/test/CXX/expr/expr.cast/p4.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -ast-dump %s | FileCheck %s + +struct A { int x; }; +struct B { int y; }; +struct C : A, B { }; + +// CHECK: casting_away_constness +void casting_away_constness(const B &b, const C &c, const B *bp, const C *cp) { + // CHECK: DerivedToBase (B) + // CHECK: DeclRefExpr {{.*}} ParmVar {{.*}} 'c' + (void)(B&)c; + // CHECK: BaseToDerived (B) + // CHECK: DeclRefExpr {{.*}} ParmVar {{.*}} 'b' + (void)(C&)b; + // CHECK: DerivedToBase (B) + // CHECK: DeclRefExpr {{.*}} ParmVar {{.*}} 'cp' + (void)(B*)cp; + // CHECK: BaseToDerived (B) + // CHECK: DeclRefExpr {{.*}} ParmVar {{.*}} 'bp' + (void)(C*)bp; + // CHECK: ReturnStmt + return; +} diff --git a/test/CXX/expr/expr.mptr.oper/p5.cpp b/test/CXX/expr/expr.mptr.oper/p5.cpp new file mode 100644 index 0000000..7380b5d --- /dev/null +++ b/test/CXX/expr/expr.mptr.oper/p5.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct X0 { + void f0(); + void f1() const; + void f2() volatile; + void f3() const volatile; +}; + +void test_object_cvquals(void (X0::*pm)(), + void (X0::*pmc)() const, + void (X0::*pmv)() volatile, + void (X0::*pmcv)() const volatile, + X0 *p, + const X0 *pc, + volatile X0 *pv, + const volatile X0 *pcv, + X0 &o, + const X0 &oc, + volatile X0 &ov, + const volatile X0 &ocv) { + (p->*pm)(); + (p->*pmc)(); + (p->*pmv)(); + (p->*pmcv)(); + + (pc->*pm)(); // expected-error{{call to pointer to member function of type 'void ()' drops 'const' qualifier}} + (pc->*pmc)(); + (pc->*pmv)(); // expected-error{{call to pointer to member function of type 'void () volatile' drops 'const' qualifier}} + (pc->*pmcv)(); + + (pv->*pm)(); // expected-error{{call to pointer to member function of type 'void ()' drops 'volatile' qualifier}} + (pv->*pmc)(); // expected-error{{call to pointer to member function of type 'void () const' drops 'volatile' qualifier}} + (pv->*pmv)(); + (pv->*pmcv)(); + + (pcv->*pm)(); // expected-error{{call to pointer to member function of type 'void ()' drops 'const volatile' qualifiers}} + (pcv->*pmc)(); // expected-error{{call to pointer to member function of type 'void () const' drops 'volatile' qualifier}} + (pcv->*pmv)(); // expected-error{{call to pointer to member function of type 'void () volatile' drops 'const' qualifier}} + (pcv->*pmcv)(); + + (o.*pm)(); + (o.*pmc)(); + (o.*pmv)(); + (o.*pmcv)(); + + (oc.*pm)(); // expected-error{{call to pointer to member function of type 'void ()' drops 'const' qualifier}} + (oc.*pmc)(); + (oc.*pmv)(); // expected-error{{call to pointer to member function of type 'void () volatile' drops 'const' qualifier}} + (oc.*pmcv)(); + + (ov.*pm)(); // expected-error{{call to pointer to member function of type 'void ()' drops 'volatile' qualifier}} + (ov.*pmc)(); // expected-error{{call to pointer to member function of type 'void () const' drops 'volatile' qualifier}} + (ov.*pmv)(); + (ov.*pmcv)(); + + (ocv.*pm)(); // expected-error{{call to pointer to member function of type 'void ()' drops 'const volatile' qualifiers}} + (ocv.*pmc)(); // expected-error{{call to pointer to member function of type 'void () const' drops 'volatile' qualifier}} + (ocv.*pmv)(); // expected-error{{call to pointer to member function of type 'void () volatile' drops 'const' qualifier}} + (ocv.*pmcv)(); +} diff --git a/test/CXX/expr/expr.mptr.oper/p6-0x.cpp b/test/CXX/expr/expr.mptr.oper/p6-0x.cpp new file mode 100644 index 0000000..d5dc7d2 --- /dev/null +++ b/test/CXX/expr/expr.mptr.oper/p6-0x.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct X { }; + +template<typename T> T& lvalue(); +template<typename T> T&& xvalue(); +template<typename T> T prvalue(); + +// In a .* expression whose object expression is an rvalue, the +// program is ill-formed if the second operand is a pointer to member +// function with ref-qualifier &. In a ->* expression or in a .* +// expression whose object expression is an lvalue, the program is +// ill-formed if the second operand is a pointer to member function +// with ref-qualifier &&. +void test(X *xp, int (X::*pmf)(int), int (X::*l_pmf)(int) &, + int (X::*r_pmf)(int) &&) { + // No ref-qualifier. + (lvalue<X>().*pmf)(17); + (xvalue<X>().*pmf)(17); + (prvalue<X>().*pmf)(17); + (xp->*pmf)(17); + + // Lvalue ref-qualifier. + (lvalue<X>().*l_pmf)(17); + (xvalue<X>().*l_pmf)(17); // expected-error{{pointer-to-member function type 'int (X::*)(int) &' can only be called on an lvalue}} + (prvalue<X>().*l_pmf)(17); // expected-error{{pointer-to-member function type 'int (X::*)(int) &' can only be called on an lvalue}} + (xp->*l_pmf)(17); + + // Rvalue ref-qualifier. + (lvalue<X>().*r_pmf)(17); // expected-error{{pointer-to-member function type 'int (X::*)(int) &&' can only be called on an rvalue}} + (xvalue<X>().*r_pmf)(17); + (prvalue<X>().*r_pmf)(17); + (xp->*r_pmf)(17); // expected-error{{pointer-to-member function type 'int (X::*)(int) &&' can only be called on an rvalue}} +} diff --git a/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp b/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp new file mode 100644 index 0000000..d464881 --- /dev/null +++ b/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// The result of the expression const_cast<T>(v) is of type T. If T is +// an lvalue reference to object type, the result is an lvalue; if T +// is an rvalue reference to object type, the result is an xvalue;. + +unsigned int f(int); + +template<typename T> T& lvalue(); +template<typename T> T&& xvalue(); +template<typename T> T prvalue(); + +void test_classification(const int *ptr) { + int *ptr0 = const_cast<int *&&>(ptr); + int *ptr1 = const_cast<int *&&>(xvalue<const int*>()); + int *ptr2 = const_cast<int *&&>(prvalue<const int*>()); +} diff --git a/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp b/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp new file mode 100644 index 0000000..3b448a8 --- /dev/null +++ b/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct X { virtual ~X(); }; +struct Y : public X { }; +struct Z; // expected-note{{forward declaration of 'Z'}} + +void test(X &x, Y &y, Z &z) { + // If T is an rvalue reference type, v shall be an expression having + // a complete class type, and the result is an xvalue of the type + // referred to by T. + Y &&yr0 = dynamic_cast<Y&&>(x); + Y &&yr1 = dynamic_cast<Y&&>(static_cast<X&&>(x)); + Y &&yr2 = dynamic_cast<Y&&>(z); // expected-error{{'Z' is an incomplete type}} +} diff --git a/test/CXX/expr/expr.post/expr.reinterpret.cast/p1-0x.cpp b/test/CXX/expr/expr.post/expr.reinterpret.cast/p1-0x.cpp new file mode 100644 index 0000000..e80082a --- /dev/null +++ b/test/CXX/expr/expr.post/expr.reinterpret.cast/p1-0x.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// If T is an lvalue reference type or an rvalue reference to function +// type, the result is an lvalue; if T is an rvalue reference to +// object type, the result is an xvalue; + +unsigned int f(int); + +template<typename T> T&& xvalue(); +void test_classification(char *ptr) { + int (&fr0)(int) = reinterpret_cast<int (&&)(int)>(f); + int &&ir0 = reinterpret_cast<int &&>(*ptr); + int &&ir1 = reinterpret_cast<int &&>(0); + int &&ir2 = reinterpret_cast<int &&>('a'); + int &&ir3 = reinterpret_cast<int &&>(xvalue<char>()); +} diff --git a/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp b/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp new file mode 100644 index 0000000..c103351 --- /dev/null +++ b/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to +// cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1" (8.5.3). +struct A { }; +struct B : A { }; + +template<typename T> T& lvalue(); +template<typename T> T&& xvalue(); + +void test(A &a, B &b) { + A &&ar0 = static_cast<A&&>(a); + A &&ar1 = static_cast<A&&>(b); + A &&ar2 = static_cast<A&&>(lvalue<A>()); + A &&ar3 = static_cast<A&&>(lvalue<B>()); + A &&ar4 = static_cast<A&&>(xvalue<A>()); + A &&ar5 = static_cast<A&&>(xvalue<B>()); + const A &&ar6 = static_cast<const A&&>(a); + const A &&ar7 = static_cast<const A&&>(b); + const A &&ar8 = static_cast<const A&&>(lvalue<A>()); + const A &&ar9 = static_cast<const A&&>(lvalue<B>()); + const A &&ar10 = static_cast<const A&&>(xvalue<A>()); + const A &&ar11 = static_cast<const A&&>(xvalue<B>()); +} diff --git a/test/CXX/expr/expr.post/expr.static.cast/p9-0x.cpp b/test/CXX/expr/expr.post/expr.static.cast/p9-0x.cpp new file mode 100644 index 0000000..4acafb8 --- /dev/null +++ b/test/CXX/expr/expr.post/expr.static.cast/p9-0x.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +enum class EC { ec1 }; + +void test0(EC ec) { + (void)static_cast<bool>(ec); + (void)static_cast<bool>(EC::ec1); + (void)static_cast<char>(ec); + (void)static_cast<char>(EC::ec1); + (void)static_cast<int>(ec); + (void)static_cast<int>(EC::ec1); + (void)static_cast<unsigned long>(ec); + (void)static_cast<unsigned long>(EC::ec1); + (void)static_cast<float>(ec); + (void)static_cast<float>(EC::ec1); + (void)static_cast<double>(ec); + (void)static_cast<double>(EC::ec1); +} + +namespace PR9107 { + enum E {}; + template <class _Tp> inline _Tp* addressof(_Tp& __x) { + return (_Tp*)&(char&)__x; + } + void test() { + E a; + addressof(a); + } +} diff --git a/test/CXX/expr/expr.unary/expr.delete/p5.cpp b/test/CXX/expr/expr.unary/expr.delete/p5.cpp index 2fa30e5..ecb2918 100644 --- a/test/CXX/expr/expr.unary/expr.delete/p5.cpp +++ b/test/CXX/expr/expr.unary/expr.delete/p5.cpp @@ -24,11 +24,23 @@ void f0(T2_A *a) { T2_C x; x.f0(a); } class T2_A { }; // An alternate version of the same. -// -// FIXME: Revisit this case when we have access control. class T3_A; template<typename T> -struct T3_B { void f0(T *a) { delete a; } }; -struct T3_C { T3_B<T3_A> x; void f0(T3_A *a) { x.f0(a); } }; +struct T3_B { + void f0(T *a) { + delete a; // expected-error{{calling a private destructor of class 'T3_A'}} + } +}; + +struct T3_C { + T3_B<T3_A> x; + void f0(T3_A *a) { + x.f0(a); // expected-note{{in instantiation of member function 'T3_B<T3_A>::f0' requested here}} + } +}; + void f0(T3_A *a) { T3_C x; x.f0(a); } -class T3_A { private: ~T3_A(); }; +class T3_A { +private: + ~T3_A(); // expected-note{{declared private here}} +}; diff --git a/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp b/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp new file mode 100644 index 0000000..c9a8887 --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x + +template<typename T> +struct only { + only(T); + template<typename U> only(U) = delete; +}; + +void f() { + only<const int*> p = new const auto (0); + only<double*> q = new (auto) (0.0); + + new auto; // expected-error{{new expression for type 'auto' requires a constructor argument}} + new (const auto)(); // expected-error{{new expression for type 'auto const' requires a constructor argument}} + new (auto) (1,2,3); // expected-error{{new expression for type 'auto' contains multiple constructor arguments}} +} + +void p2example() { + only<int*> r = new auto(1); + auto x = new auto('a'); + + only<char*> testX = x; +} diff --git a/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp b/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp new file mode 100644 index 0000000..3824615 --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Test parsing + semantic analysis +template<typename ...Types> struct count_types { + static const unsigned value = sizeof...(Types); +}; + +template<int ...Values> struct count_ints { + static const unsigned value = sizeof...(Values); +}; + +// Test instantiation +int check_types[count_types<short, int, long>::value == 3? 1 : -1]; +int check_ints[count_ints<1, 2, 3, 4, 5>::value == 5? 1 : -1]; + +// Test instantiation involving function parameter packs. +struct any { + template<typename T> any(T); +}; + +template<typename ...Inits> +void init_me(Inits ...inits) { + any array[sizeof...(inits)] = { inits... }; +} + +template void init_me<int, float, double*>(int, float, double*); + +// Test parser and semantic recovery. +template<int Value> struct count_ints_2 { + static const unsigned value = sizeof...(Value); // expected-error{{'Value' does not refer to the name of a parameter pack}} +}; + +template<typename ...Types> // expected-note{{parameter pack 'Types' declared here}} +struct count_types_2 { + static const unsigned value = sizeof... Type; // expected-error{{missing parentheses around the size of parameter pack 'Type'}} \ + // expected-error{{Type' does not refer to the name of a parameter pack; did you mean 'Types'?}} +}; + diff --git a/test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp b/test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp new file mode 100644 index 0000000..6aec3a2 --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fexceptions -triple x86_64-apple-darwin10 -S -emit-llvm -std=c++0x -include %S/ser.h %s -o - | FileCheck %s +// RUN: %clang_cc1 -fexceptions -triple x86_64-apple-darwin10 -emit-pch -o %t-ser.pch -std=c++0x -x c++ %S/ser.h +// RUN: %clang_cc1 -fexceptions -triple x86_64-apple-darwin10 -S -emit-llvm -std=c++0x -include-pch %t-ser.pch %s -o - | FileCheck %s + +struct D { + ~D() throw(); +}; +struct E { + ~E() throw(); +}; + +void test() { + bool b; + // CHECK: store i8 1 + b = noexcept(0); + // CHECK: store i8 0 + b = noexcept(throw 0); + b = f1(); + b = f2(); + + // CHECK-NOT: call void @_ZN1ED1Ev + // CHECK: call void @_ZN1DD1Ev + D(), noexcept(E()); +} +// CHECK: ret i1 true +// CHECK: ret i1 false diff --git a/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp b/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp new file mode 100644 index 0000000..98c6f4e --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp @@ -0,0 +1,172 @@ +// RUN: %clang_cc1 -fexceptions -fsyntax-only -verify -std=c++0x -fms-extensions %s + +#define P(e) static_assert(noexcept(e), "expected nothrow") +#define N(e) static_assert(!noexcept(e), "expected throw") +#define B(b, e) static_assert(b == noexcept(e), "expectation failed") + +void simple() { + P(0); + P(0 + 0); + int i; + P(i); + P(sizeof(0)); + P(static_cast<int>(0)); + N(throw 0); + N((throw 0, 0)); +} + +void nospec(); +void allspec() throw(...); +void intspec() throw(int); +void emptyspec() throw(); +void nothrowattr() __attribute__((nothrow)); + +void call() { + N(nospec()); + N(allspec()); + N(intspec()); + P(emptyspec()); + P(nothrowattr()); +} + +void (*pnospec)(); +void (*pallspec)() throw(...); +void (*pintspec)() throw(int); +void (*pemptyspec)() throw(); + +void callptr() { + N(pnospec()); + N((*pnospec)()); + N(pallspec()); + N((*pallspec)()); + N(pintspec()); + N((*pintspec)()); + P(pemptyspec()); + P((*pemptyspec)()); +} + +struct S1 { + void nospec(); + void allspec() throw(...); + void intspec() throw(int); + void emptyspec() throw(); +}; + +void callmem() { + S1 s; + N(s.nospec()); + N(s.allspec()); + N(s.intspec()); + P(s.emptyspec()); +} + +void (S1::*mpnospec)(); +void (S1::*mpallspec)() throw(...); +void (S1::*mpintspec)() throw(int); +void (S1::*mpemptyspec)() throw(); + +void callmemptr() { + S1 s; + N((s.*mpnospec)()); + N((s.*mpallspec)()); + N((s.*mpintspec)()); + P((s.*mpemptyspec)()); +} + +struct S2 { + S2(); + S2(int, int) throw(); + void operator +(); + void operator -() throw(); + void operator +(int); + void operator -(int) throw(); + operator int(); + operator float() throw(); +}; + +void *operator new(__typeof__(sizeof(int)) sz, int) throw(); + +struct Bad1 { + ~Bad1() throw(int); +}; +struct Bad2 { + void operator delete(void*) throw(int); +}; + +void implicits() { + N(new int); + P(new (0) int); + P(delete (int*)0); + N(delete (Bad1*)0); + N(delete (Bad2*)0); + N(S2()); + P(S2(0, 0)); + S2 s; + N(+s); + P(-s); + N(s + 0); + P(s - 0); + N(static_cast<int>(s)); + P(static_cast<float>(s)); + N(Bad1()); +} + +struct V { + virtual ~V() throw(); +}; +struct D : V {}; + +void dyncast() { + V *pv = 0; + D *pd = 0; + P(dynamic_cast<V&>(*pd)); + P(dynamic_cast<V*>(pd)); + N(dynamic_cast<D&>(*pv)); + P(dynamic_cast<D*>(pv)); +} + +namespace std { + struct type_info {}; +} + +void idtype() { + P(typeid(V)); + P(typeid((V*)0)); + P(typeid(*(S1*)0)); + N(typeid(*(V*)0)); +} + +void uneval() { + P(sizeof(typeid(*(V*)0))); + P(typeid(typeid(*(V*)0))); +} + +struct G1 {}; +struct G2 { int i; }; +struct G3 { S2 s; }; + +void gencon() { + P(G1()); + P(G2()); + N(G3()); +} + +template <typename T, bool b> +void late() { + B(b, typeid(*(T*)0)); + B(b, T(1)); + B(b, static_cast<T>(S2(0, 0))); + B(b, S1() + T()); +} +struct S3 { + virtual ~S3() throw(); + S3() throw(); + explicit S3(int); + S3(const S2&); +}; +void operator +(const S1&, float) throw(); +void operator +(const S1&, const S3&); +void tlate() { + late<float, true>(); + late<S3, false>(); +} diff --git a/test/CXX/expr/expr.unary/expr.unary.noexcept/ser.h b/test/CXX/expr/expr.unary/expr.unary.noexcept/ser.h new file mode 100644 index 0000000..e6e7b79 --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.unary.noexcept/ser.h @@ -0,0 +1,8 @@ +// Serialization testing helper for noexcept, included by cg.cpp. + +inline bool f1() { + return noexcept(0); +} +inline bool f2() { + return noexcept(throw 0); +} diff --git a/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp b/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp index 170c734..06cc610 100644 --- a/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp +++ b/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp @@ -7,8 +7,7 @@ namespace test0 { template<typename T> void g(T); void test() { - // FIXME: this diagnostic is terrible - foo(&g<int>); // expected-error {{cannot initialize a parameter of type 'void (test0::A::*)(int)' with an rvalue of type '<overloaded function type>'}} + foo(&g<int>); // expected-error {{can't form member pointer of type 'void (test0::A::*)(int)' without '&' and class name}} } }; } @@ -39,7 +38,6 @@ namespace test2 { }; void A::test() { - // FIXME: This diagnostic is terrible. - int (A::*ptr)(int) = &(A::foo); // expected-error {{cannot initialize a variable of type 'int (test2::A::*)(int)' with an rvalue of type '<overloaded function type>'}} + int (A::*ptr)(int) = &(A::foo); // expected-error {{can't form member pointer of type 'int (test2::A::*)(int)' without '&' and class name}} } } diff --git a/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp b/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp new file mode 100644 index 0000000..543a86d --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// -- prvalue of arithmetic + +bool b = !0; + +bool b2 = !1.2; + +bool b3 = !4; + +// -- unscoped enumeration +enum { E, F }; + +bool b4 = !E; +bool b5 = !F; + +// -- pointer, +bool b6 = !&b4; +void f(); +bool b61 = !&f; + +// -- or pointer to member type can be converted to a prvalue of type bool. +struct S { void f() { } }; + +bool b7 = !&S::f; + + +bool b8 = !S(); //expected-error {{invalid argument type 'S'}} + +namespace PR8181 +{ + void f() { } + void f(char) { } + bool b = !&f; //expected-error {{cannot resolve overloaded function from context}} + +} diff --git a/test/CXX/over/over.built/p1.cpp b/test/CXX/over/over.built/p1.cpp new file mode 100644 index 0000000..6000f5b --- /dev/null +++ b/test/CXX/over/over.built/p1.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +enum E1 { one }; +enum E2 { two }; + +bool operator >= (E1, E1) { + return false; +} + +bool operator >= (E1, const E2) { + return false; +} + +bool test(E1 a, E1 b, E2 c) { + return a >= b || a >= c; +} diff --git a/test/CXX/over/over.built/p25.cpp b/test/CXX/over/over.built/p25.cpp new file mode 100644 index 0000000..c185fb4 --- /dev/null +++ b/test/CXX/over/over.built/p25.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +enum class Color { Red, Green, Blue }; + +struct ConvertsToColorA { + operator Color(); +}; + +struct ConvertsToColorB { + operator Color(); +}; + +Color foo(bool cond, ConvertsToColorA ca, ConvertsToColorB cb) { + return cond? ca : cb; +} diff --git a/test/CXX/over/over.load/p2-0x.cpp b/test/CXX/over/over.load/p2-0x.cpp new file mode 100644 index 0000000..f0ace90 --- /dev/null +++ b/test/CXX/over/over.load/p2-0x.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Member function declarations with the same name and the same +// parameter-type-list as well as mem- ber function template +// declarations with the same name, the same parameter-type-list, and +// the same template parameter lists cannot be overloaded if any of +// them, but not all, have a ref-qualifier (8.3.5). + +class Y { + void h() &; + void h() const &; + void h() &&; + void i() &; // expected-note{{previous declaration}} + void i() const; // expected-error{{cannot overload a member function without a ref-qualifier with a member function with ref-qualifier '&'}} + + template<typename T> void f(T*) &; + template<typename T> void f(T*) &&; + + template<typename T> void g(T*) &; // expected-note{{previous declaration}} + template<typename T> void g(T*); // expected-error{{cannot overload a member function without a ref-qualifier with a member function with ref-qualifier '&'}} + + void k(); // expected-note{{previous declaration}} + void k() &&; // expected-error{{cannot overload a member function with ref-qualifier '&&' with a member function without a ref-qualifier}} +}; diff --git a/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp b/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp new file mode 100644 index 0000000..ab171bc --- /dev/null +++ b/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +namespace std_example { + int i; + int f1(); + int&& f2(); + int &g(const int &); + float &g(const int &&); + int &j = g(i); + float &k = g(f1()); + float &l = g(f2()); + + int &g2(const int &); + float &g2(int &&); + int &j2 = g2(i); + float &k2 = g2(f1()); + float &l2 = g2(f2()); + + // FIXME: We don't support ref-qualifiers yet. +#if 0 + struct A { + A& operator<<(int); + void p() &; + void p() &&; + }; + + A& operator<<(A&&, char); + A() << 1; + A() << 'c'; + A a; + a << 1; + a << 'c'; + A().p(); + a.p(); +#endif +} + +template<typename T> +struct remove_reference { + typedef T type; +}; + +template<typename T> +struct remove_reference<T&> { + typedef T type; +}; + +template<typename T> +struct remove_reference<T&&> { + typedef T type; +}; + +namespace FunctionReferencesOverloading { + template<typename T> int &f(typename remove_reference<T>::type&); + template<typename T> float &f(typename remove_reference<T>::type&&); + + void test_f(int (&func_ref)(int)) { + int &ir = f<int (&)(int)>(func_ref); + } +} diff --git a/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp b/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp new file mode 100644 index 0000000..8ccc5b6 --- /dev/null +++ b/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template<typename T> T &lvalue(); +template<typename T> T &&xvalue(); +template<typename T> T prvalue(); + +struct X0 { + int &f() &; + float &f() &&; + + template<typename T> int &ft(T) &; + template<typename T> float &ft(T) &&; + + typedef int &(*func_int_ref)(); + typedef float &(*func_float_ref)(); + + operator func_int_ref() &; + operator func_float_ref() &&; + + void g(); + + int &operator+(const X0&) &; + float &operator+(const X0&) &&; + + template<typename T> int &operator+(const T&) &; + template<typename T> float &operator+(const T&) &&; + + int &h() const&; + float &h() &&; + int &h2() const&; + float &h2() const&&; +}; + +void X0::g() { + int &ir1 = f(); + int &ir2 = X0::f(); +} + +void test_ref_qualifier_binding() { + int &ir1 = lvalue<X0>().f(); + float &fr1 = xvalue<X0>().f(); + float &fr2 = prvalue<X0>().f(); + int &ir2 = lvalue<X0>().ft(1); + float &fr3 = xvalue<X0>().ft(2); + float &fr4 = prvalue<X0>().ft(3); +} + +void test_ref_qualifier_binding_with_surrogates() { + int &ir1 = lvalue<X0>()(); + float &fr1 = xvalue<X0>()(); + float &fr2 = prvalue<X0>()(); +} + +void test_ref_qualifier_binding_operators() { + int &ir1 = lvalue<X0>() + prvalue<X0>(); + float &fr1 = xvalue<X0>() + prvalue<X0>(); + float &fr2 = prvalue<X0>() + prvalue<X0>(); + int &ir2 = lvalue<X0>() + 1; + float &fr3 = xvalue<X0>() + 2; + float &fr4 = prvalue<X0>() + 3; +} + +void test_ref_qualifier_overloading() { + int &ir1 = lvalue<X0>().h(); + float &fr1 = xvalue<X0>().h(); + float &fr2 = prvalue<X0>().h(); + int &ir2 = lvalue<X0>().h2(); + float &fr3 = xvalue<X0>().h2(); + float &fr4 = prvalue<X0>().h2(); +} diff --git a/test/CXX/over/over.over/p2-resolve-single-template-id.cpp b/test/CXX/over/over.over/p2-resolve-single-template-id.cpp new file mode 100644 index 0000000..f38a74e --- /dev/null +++ b/test/CXX/over/over.over/p2-resolve-single-template-id.cpp @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +typedef __typeof__(((int*)0)-((int*)0)) ptrdiff_t; + +namespace DontResolveTooEarly_WaitForOverloadResolution +{ + template <class T> T* f(int); // #1 + template <class T, class U> T& f(U); // #2 + + void g() { + int *ip = f<int>(1); // calls #1 + } + + template <class T> + T* f2(int); + template <class T, class U> + T& f2(U); + + void g2() { + int*ip = (f2<int>)(1); // ok + } + +} // End namespace + + template<typename T> + void twoT() { } + template<typename T, typename U> + void twoT(T) { } + + + void two() { }; //expected-note 5{{candidate}} + void two(int) { }; //expected-note 5{{candidate}} + + + + void one() { } + template<class T> + void oneT() { } + + template<class T> + void cant_resolve() { } //expected-note 3{{candidate}} + + template<class T> void cant_resolve(T) { }//expected-note 3{{candidate}} + + +int main() +{ + { static_cast<void>(one); } + { (void)(one); } + { static_cast<void>(oneT<int>); } + { (void)(oneT<int>); } + + { static_cast<void>(two); } // expected-error {{address of overloaded}} + { (void)(two); } // expected-error {{address of overloaded}} + { static_cast<void>(twoT<int>); } + { (void)(twoT<int>); } + + + { ptrdiff_t x = reinterpret_cast<ptrdiff_t>(oneT<int>); } + { (void) reinterpret_cast<int (*)(char, double)>(oneT<int>); } + { (void) reinterpret_cast<ptrdiff_t>(one); } + { (void) reinterpret_cast<int (*)(char, double)>(one); } + + { ptrdiff_t x = reinterpret_cast<ptrdiff_t>(twoT<int>); } + { (void) reinterpret_cast<int (*)(char, double)>(twoT<int>); } + { (void) reinterpret_cast<void (*)(int)>(two); } //expected-error {{reinterpret_cast}} + { (void) static_cast<void (*)(int)>(two); } //ok + + { (void) reinterpret_cast<int>(two); } //expected-error {{reinterpret_cast}} + { (void) reinterpret_cast<int (*)(char, double)>(two); } //expected-error {{reinterpret_cast}} + + { bool b = (twoT<int>); } // ok + { bool b = (twoT<int, int>); } //ok + + { bool b = &twoT<int>; //&foo<int>; } + b = &(twoT<int>); } + + { ptrdiff_t x = (ptrdiff_t) &twoT<int>; + x = (ptrdiff_t) &twoT<int>; } + + { ptrdiff_t x = (ptrdiff_t) twoT<int>; + x = (ptrdiff_t) twoT<int>; } + + + { ptrdiff_t x = (ptrdiff_t) &twoT<int,int>; + x = (ptrdiff_t) &twoT<int>; } + + { oneT<int>; &oneT<int>; } //expected-warning 2{{ expression result unused }} + { static_cast<void>(cant_resolve<int>); } // expected-error {{address of overload}} + { bool b = cant_resolve<int>; } // expected-error {{address of overload}} + { (void) cant_resolve<int>; } // expected-error {{address of overload}} + +} + + diff --git a/test/CXX/over/over.over/p2.cpp b/test/CXX/over/over.over/p2.cpp index e8840d2..3e8d0f1 100644 --- a/test/CXX/over/over.over/p2.cpp +++ b/test/CXX/over/over.over/p2.cpp @@ -1,10 +1,9 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -template<typename T> T f0(T, T); +template<typename T> T f0(T, T); //expected-note{{candidate}} void test_f0() { int (*f0a)(int, int) = f0; int (*f0b)(int, int) = &f0; - int (*f0c)(int, float) = f0; // expected-error{{cannot initialize}} - // FIXME: poor error message above! + int (*f0c)(int, float) = f0; // expected-error{{address of overloaded function 'f0' does not match required type 'int (int, float)'}} } diff --git a/test/CXX/over/over.over/p4.cpp b/test/CXX/over/over.over/p4.cpp index 4189218..27d070e 100644 --- a/test/CXX/over/over.over/p4.cpp +++ b/test/CXX/over/over.over/p4.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -template<typename T> T f0(T); +template<typename T> T f0(T); // expected-note{{candidate function}} int f0(int); // expected-note{{candidate function}} void test_f0() { @@ -13,11 +13,8 @@ namespace N { int f0(int); // expected-note{{candidate function}} } -int f0(int); - void test_f0_2() { using namespace N; - int (*fp0)(int) = f0; // expected-error{{ambiguous}} \ - // expected-error{{cannot initialize}} + int (*fp0)(int) = f0; // expected-error{{address of overloaded function 'f0' is ambiguous}} float (*fp1)(float) = f0; } diff --git a/test/CXX/special/class.copy/p33-0x.cpp b/test/CXX/special/class.copy/p33-0x.cpp new file mode 100644 index 0000000..262809e --- /dev/null +++ b/test/CXX/special/class.copy/p33-0x.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fexceptions -std=c++0x -fsyntax-only -verify %s +class X { + X(const X&); + +public: + X(); + X(X&&); +}; + +X return_by_move(int i, X x) { + X x2; + if (i == 0) + return x; + else if (i == 1) + return x2; + else + return x; +} + +void throw_move_only(X x) { + X x2; + throw x; + throw x2; +} + diff --git a/test/CXX/special/class.copy/p9.cpp b/test/CXX/special/class.copy/p9.cpp index d037944..77ab19e 100644 --- a/test/CXX/special/class.copy/p9.cpp +++ b/test/CXX/special/class.copy/p9.cpp @@ -15,30 +15,30 @@ struct VirtualInheritsNonConstCopy : virtual NonConstCopy { VirtualInheritsNonConstCopy(const VirtualInheritsNonConstCopy&); }; -struct ImplicitNonConstCopy1 : NonConstCopy { - ImplicitNonConstCopy1(); +struct ImplicitNonConstCopy1 : NonConstCopy { // expected-note {{candidate constructor}} + ImplicitNonConstCopy1(); // expected-note {{candidate constructor}} }; -struct ImplicitNonConstCopy2 { - ImplicitNonConstCopy2(); +struct ImplicitNonConstCopy2 { // expected-note {{candidate constructor}} + ImplicitNonConstCopy2(); // expected-note {{candidate constructor}} NonConstCopy ncc; }; -struct ImplicitNonConstCopy3 { - ImplicitNonConstCopy3(); +struct ImplicitNonConstCopy3 { // expected-note {{candidate constructor}} + ImplicitNonConstCopy3(); // expected-note {{candidate constructor}} NonConstCopy ncc_array[2][3]; }; -struct ImplicitNonConstCopy4 : VirtualInheritsNonConstCopy { - ImplicitNonConstCopy4(); +struct ImplicitNonConstCopy4 : VirtualInheritsNonConstCopy { // expected-note {{candidate constructor}} + ImplicitNonConstCopy4(); // expected-note {{candidate constructor}} }; void test_non_const_copy(const ImplicitNonConstCopy1 &cincc1, const ImplicitNonConstCopy2 &cincc2, const ImplicitNonConstCopy3 &cincc3, const ImplicitNonConstCopy4 &cincc4) { - (void)sizeof(ImplicitNonConstCopy1(cincc1)); // expected-error{{functional-style cast from 'ImplicitNonConstCopy1 const' to 'ImplicitNonConstCopy1' is not allowed}} - (void)sizeof(ImplicitNonConstCopy2(cincc2)); // expected-error{{functional-style cast from 'ImplicitNonConstCopy2 const' to 'ImplicitNonConstCopy2' is not allowed}} - (void)sizeof(ImplicitNonConstCopy3(cincc3)); // expected-error{{functional-style cast from 'ImplicitNonConstCopy3 const' to 'ImplicitNonConstCopy3' is not allowed}} - (void)sizeof(ImplicitNonConstCopy4(cincc4)); // expected-error{{functional-style cast from 'ImplicitNonConstCopy4 const' to 'ImplicitNonConstCopy4' is not allowed}} + (void)sizeof(ImplicitNonConstCopy1(cincc1)); // expected-error{{no matching conversion for functional-style cast from 'const ImplicitNonConstCopy1' to 'ImplicitNonConstCopy1'}} + (void)sizeof(ImplicitNonConstCopy2(cincc2)); // expected-error{{no matching conversion for functional-style cast from 'const ImplicitNonConstCopy2' to 'ImplicitNonConstCopy2'}} + (void)sizeof(ImplicitNonConstCopy3(cincc3)); // expected-error{{no matching conversion for functional-style cast from 'const ImplicitNonConstCopy3' to 'ImplicitNonConstCopy3'}} + (void)sizeof(ImplicitNonConstCopy4(cincc4)); // expected-error{{no matching conversion for functional-style cast from 'const ImplicitNonConstCopy4' to 'ImplicitNonConstCopy4'}} } diff --git a/test/CXX/special/class.ctor/p4-0x.cpp b/test/CXX/special/class.ctor/p4-0x.cpp new file mode 100644 index 0000000..e3508e2 --- /dev/null +++ b/test/CXX/special/class.ctor/p4-0x.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// A constructor shall not be declared with a ref-qualifier. +struct X { + X() &; // expected-error{{ref-qualifier '&' is not allowed on a constructor}} + X(int) &&; // expected-error{{ref-qualifier '&&' is not allowed on a constructor}} +}; diff --git a/test/CXX/special/class.dtor/p2-0x.cpp b/test/CXX/special/class.dtor/p2-0x.cpp new file mode 100644 index 0000000..53a2e03 --- /dev/null +++ b/test/CXX/special/class.dtor/p2-0x.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// A destructor shall not be declared with a ref-qualifier. +struct X { + ~X() &; // expected-error{{ref-qualifier '&' is not allowed on a destructor}} +}; + +struct Y { + ~Y() &&; // expected-error{{ref-qualifier '&&' is not allowed on a destructor}} +}; diff --git a/test/CXX/special/class.inhctor/elsewhere.cpp b/test/CXX/special/class.inhctor/elsewhere.cpp new file mode 100644 index 0000000..82944d6 --- /dev/null +++ b/test/CXX/special/class.inhctor/elsewhere.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Tests related to constructor inheriting, but not specified in [class.inhctor] + +// [namespace.udecl]p8: +// A using-declaration for a class member shall be a member-declaration. + +struct B1 { + B1(int); +}; + +using B1::B1; // expected-error {{using declaration can not refer to class member}} + +// C++0x [namespace.udecl]p10: +// A using-declaration is a declaration and can therefore be used repeatedly +// where (and only where) multiple declarations are allowed. + +struct I1 : B1 { + using B1::B1; // expected-note {{previous using declaration}} + using B1::B1; // expected-error {{redeclaration of using decl}} +}; + +// C++0x [namespace.udecl]p3: +// In a using declaration used as a member-declaration, the nested-name- +// specifier shall name a base class of the class being defined. +// If such a using-declaration names a constructor, the nested-name-specifier +// shall name a direct base class of the class being defined. + +struct D1 : I1 { + using B1::B1; // expected-error {{'B1' is not a direct base of 'D1', can not inherit constructors}} +}; diff --git a/test/CXX/special/class.inhctor/p3.cpp b/test/CXX/special/class.inhctor/p3.cpp new file mode 100644 index 0000000..021f701 --- /dev/null +++ b/test/CXX/special/class.inhctor/p3.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct B1 { + B1(int); + B1(int, int); +}; +struct D1 : B1 { + using B1::B1; +}; +D1 d1a(1), d1b(1, 1); + +D1 fd1() { return 1; } + +struct B2 { + explicit B2(int, int = 0, int = 0); +}; +struct D2 : B2 { // expected-note {{candidate constructor}} + using B2::B2; +}; +D2 d2a(1), d2b(1, 1), d2c(1, 1, 1); + +D2 fd2() { return 1; } // expected-error {{no viable conversion}} + +struct B3 { + B3(void*); // expected-note {{inherited from here}} +}; +struct D3 : B3 { // expected-note {{candidate constructor}} + using B3::B3; // expected-note {{candidate constructor (inherited)}} +}; +D3 fd3() { return 1; } // expected-error {{no viable conversion}} diff --git a/test/CXX/special/class.inhctor/p7.cpp b/test/CXX/special/class.inhctor/p7.cpp new file mode 100644 index 0000000..3ad761f --- /dev/null +++ b/test/CXX/special/class.inhctor/p7.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Straight from the standard +struct B1 { + B1(int); // expected-note {{previous constructor}} +}; +struct B2 { + B2(int); // expected-note {{conflicting constructor}} +}; +struct D1 : B1, B2 { + using B1::B1; // expected-note {{inherited here}} + using B2::B2; // expected-error {{already inherited constructor with the same signature}} +}; +struct D2 : B1, B2 { + using B1::B1; + using B2::B2; + D2(int); +}; diff --git a/test/CXX/stmt.stmt/stmt.label/p1.cpp b/test/CXX/stmt.stmt/stmt.label/p1.cpp new file mode 100644 index 0000000..90367f8 --- /dev/null +++ b/test/CXX/stmt.stmt/stmt.label/p1.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f() +{ + int x = 0; + goto label1; + +label1: // expected-note{{previous definition is here}} + x = 1; + goto label2; // expected-error{{use of undeclared label 'label2'}} + +label1: // expected-error{{redefinition of label 'label1'}} + x = 2; +} + +void h() +{ + int x = 0; + switch (x) + { + case 1:; + default:; // expected-error{{multiple default labels in one switch}} + default:; // expected-note{{previous case defined here}} + } +} diff --git a/test/CXX/stmt.stmt/stmt.select/p3.cpp b/test/CXX/stmt.stmt/stmt.select/p3.cpp index 31de685..35e5c91 100644 --- a/test/CXX/stmt.stmt/stmt.select/p3.cpp +++ b/test/CXX/stmt.stmt/stmt.select/p3.cpp @@ -16,4 +16,4 @@ void h() { int x; // expected-error{{redefinition of 'x'}} else int x; // expected-error{{redefinition of 'x'}} -}
\ No newline at end of file +} diff --git a/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp b/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp index b0f1c46..9b9b532 100644 --- a/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp +++ b/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp @@ -53,7 +53,7 @@ namespace pointer_to_object_parameters { A2<X_ptr> *a12; // expected-error{{must have its address taken}} A2<array_of_Xs> *a13; A2<&an_X> *a13_2; - A2<(&an_X)> *a13_3; // expected-error{{non-type template argument cannot be surrounded by parentheses}} + A2<(&an_X)> *a13_3; // expected-warning{{address non-type template argument cannot be surrounded by parentheses}} // PR6244 struct X1 {} X1v; @@ -88,19 +88,19 @@ namespace reference_parameters { extern const volatile int cvi; void test() { S0<i> s0; - S0<ci> s0c; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'int const' ignores qualifiers}} - S0<vi> s0v; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'int volatile' ignores qualifiers}} - S0<cvi> s0cv; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'int const volatile' ignores qualifiers}} + S0<ci> s0c; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'const int' ignores qualifiers}} + S0<vi> s0v; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'volatile int' ignores qualifiers}} + S0<cvi> s0cv; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type 'const volatile int' ignores qualifiers}} S1<i> s1; S1<ci> s1c; - S1<vi> s1v; // expected-error{{reference binding of non-type template parameter of type 'int const &' to template argument of type 'int volatile' ignores qualifiers}} - S1<cvi> s1cv; // expected-error{{reference binding of non-type template parameter of type 'int const &' to template argument of type 'int const volatile' ignores qualifiers}} + S1<vi> s1v; // expected-error{{reference binding of non-type template parameter of type 'const int &' to template argument of type 'volatile int' ignores qualifiers}} + S1<cvi> s1cv; // expected-error{{reference binding of non-type template parameter of type 'const int &' to template argument of type 'const volatile int' ignores qualifiers}} S2<i> s2; - S2<ci> s2c; // expected-error{{reference binding of non-type template parameter of type 'int volatile &' to template argument of type 'int const' ignores qualifiers}} + S2<ci> s2c; // expected-error{{reference binding of non-type template parameter of type 'volatile int &' to template argument of type 'const int' ignores qualifiers}} S2<vi> s2v; - S2<cvi> s2cv; // expected-error{{reference binding of non-type template parameter of type 'int volatile &' to template argument of type 'int const volatile' ignores qualifiers}} + S2<cvi> s2cv; // expected-error{{reference binding of non-type template parameter of type 'volatile int &' to template argument of type 'const volatile int' ignores qualifiers}} S3<i> s3; S3<ci> s3c; diff --git a/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp b/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp new file mode 100644 index 0000000..794a050 --- /dev/null +++ b/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template <class T> struct eval; // expected-note 3{{template is declared here}} + +template <template <class, class...> class TT, class T1, class... Rest> +struct eval<TT<T1, Rest...>> { }; + +template <class T1> struct A; +template <class T1, class T2> struct B; +template <int N> struct C; +template <class T1, int N> struct D; +template <class T1, class T2, int N = 17> struct E; + +eval<A<int>> eA; +eval<B<int, float>> eB; +eval<C<17>> eC; // expected-error{{implicit instantiation of undefined template 'eval<C<17> >'}} +eval<D<int, 17>> eD; // expected-error{{implicit instantiation of undefined template 'eval<D<int, 17> >'}} +eval<E<int, float>> eE; // expected-error{{implicit instantiation of undefined template 'eval<E<int, float, 17> >}} + +template<template <int ...N> class TT> struct X0 { }; // expected-note{{previous non-type template parameter with type 'int' is here}} +template<int I, int J, int ...Rest> struct X0a; +template<int ...Rest> struct X0b; +template<int I, long J> struct X0c; // expected-note{{template non-type parameter has a different type 'long' in template argument}} + +X0<X0a> inst_x0a; +X0<X0b> inst_x0b; +X0<X0c> inst_x0c; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} + +template<typename T, + template <T ...N> class TT> // expected-note{{previous non-type template parameter with type 'short' is here}} +struct X1 { }; +template<int I, int J, int ...Rest> struct X1a; +template<long I, long ...Rest> struct X1b; +template<short I, short J> struct X1c; +template<short I, long J> struct X1d; // expected-note{{template non-type parameter has a different type 'long' in template argument}} + +X1<int, X1a> inst_x1a; +X1<long, X1b> inst_x1b; +X1<short, X1c> inst_x1c; +X1<short, X1d> inst_x1d; // expected-error{{template template argument has different template parameters than its corresponding template template paramete}} diff --git a/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp b/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp new file mode 100644 index 0000000..0fd9a7e --- /dev/null +++ b/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T> struct A { + static T t; // expected-error{{static data member instantiated with function type 'int ()'}} +}; +typedef int function(); +A<function> a; // expected-note{{instantiation of}} + +template<typename T> struct B { + B() { T t; } // expected-error{{variable instantiated with function type 'int ()'}} +}; +B<function> b; // expected-note{{instantiation of}} + +template <typename T> int f0(void *, const T&); // expected-note{{candidate template ignored: substitution failure}} +enum {e}; // expected-note{{unnamed type used in template argument was declared here}} + +void test_f0(int n) { + int i = f0(0, e); // expected-warning{{template argument uses unnamed type}} + int vla[n]; + f0(0, vla); // expected-error{{no matching function for call to 'f0'}} +} + +namespace N0 { + template <typename R, typename A1> void f0(R (*)(A1)); + template <typename T> int f1(T); + template <typename T, typename U> int f1(T, U); + enum {e1}; // expected-note 2{{unnamed type used in template argument was declared here}} + enum {e2}; // expected-note 2{{unnamed type used in template argument was declared here}} + enum {e3}; // expected-note{{unnamed type used in template argument was declared here}} + + template<typename T> struct X; + template<typename T> struct X<T*> { }; + + void f() { + f0( // expected-warning{{template argument uses unnamed type}} + &f1<__typeof__(e1)>); // expected-warning{{template argument uses unnamed type}} + int (*fp1)(int, __typeof__(e2)) = f1; // expected-warning{{template argument uses unnamed type}} + f1(e2); // expected-warning{{template argument uses unnamed type}} + f1(e2); + + X<__typeof__(e3)*> x; // expected-warning{{template argument uses unnamed type}} + } +} diff --git a/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp b/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp index a93249e..d0fc797 100644 --- a/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp +++ b/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp @@ -53,3 +53,24 @@ struct X0<float>::Inner0<Z*> { int array3[X0<float>::Inner0<int>::value == 0? 1 : -1]; int array4[X0<float>::Inner0<int*>::value == 3? 1 : -1]; int array5[X0<float>::Inner0<const int*>::value == 2? 1 : -1]; + +namespace rdar8651930 { + template<typename OuterT> + struct Outer { + template<typename T, typename U> + struct Inner; + + template<typename T> + struct Inner<T, T> { + static const bool value = true; + }; + + template<typename T, typename U> + struct Inner { + static const bool value = false; + }; + }; + + int array0[Outer<int>::Inner<int, int>::value? 1 : -1]; + int array1[Outer<int>::Inner<int, float>::value? -1 : 1]; +} diff --git a/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp b/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp new file mode 100644 index 0000000..14152cf --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template<int ...Values> struct X1; + +template<int ...Values> +struct X1<0, Values+1 ...>; // expected-error{{non-type template argument depends on a template parameter of the partial specialization}} + + diff --git a/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp b/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp new file mode 100644 index 0000000..d8e07b8 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// -- The argument list of the specialization shall not be identical +// to the implicit argument list of the primary template. + +template<typename T, typename ...Types> +struct X1; + +template<typename T, typename ...Types> +struct X1<T, Types...> // expected-error{{class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}} +{ }; + + diff --git a/test/CXX/temp/temp.decls/temp.class.spec/p9.cpp b/test/CXX/temp/temp.decls/temp.class.spec/p9.cpp new file mode 100644 index 0000000..2a3e914 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.class.spec/p9.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR8905 +template<char C1, char C2> +struct X { + static const bool value = 0; +}; + +template<int C1> +struct X<C1, C1> { + static const bool value = 1; +}; + +int check0[X<1, 2>::value == 0? 1 : -1]; +int check1[X<1, 1>::value == 1? 1 : -1]; + +template<int, int, int> struct int_values { + static const unsigned value = 0; +}; + +template<unsigned char C1, unsigned char C3> +struct int_values<C1, 12, C3> { + static const unsigned value = 1; +}; + +int check2[int_values<256, 12, 3>::value == 0? 1 : -1]; diff --git a/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3-0x.cpp b/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3-0x.cpp new file mode 100644 index 0000000..11ec289 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3-0x.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +// Core DR 532. +namespace PR8130 { + struct A { }; + + template<class T> struct B { + template<class R> int &operator*(R&); + }; + + template<class T, class R> float &operator*(T&, R&); + void test() { + A a; + B<A> b; + int &ir = b * a; + } +} diff --git a/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3.cpp b/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3.cpp new file mode 100644 index 0000000..2ffdd95 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace DeduceVsMember { + template<typename T> + struct X { + template<typename U> + int &operator==(const U& other) const; + }; + + template<typename T, typename U> + float &operator==(const T&, const X<U>&); + + void test(X<int> xi, X<float> xf) { + float& ir = (xi == xf); + } +} diff --git a/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/test/CXX/temp/temp.decls/temp.friend/p1.cpp index 073b2a1..578de29 100644 --- a/test/CXX/temp/temp.decls/temp.friend/p1.cpp +++ b/test/CXX/temp/temp.decls/temp.friend/p1.cpp @@ -293,3 +293,42 @@ namespace test13 { template class Foo<0>; } + +namespace test14 { + template <class T> class B; + template <class T> class A { + friend void B<T>::foo(); + static void foo(); // expected-note {{declared private here}} + }; + + template <class T> class B { + void foo() { return A<long>::foo(); } // expected-error {{'foo' is a private member of 'test14::A<long>'}} + }; + + template class B<int>; // expected-note {{in instantiation}} +} + +namespace test15 { + template <class T> class B; + template <class T> class A { + friend void B<T>::foo(); + + // This shouldn't be misrecognized as a templated-scoped reference. + template <class U> friend void B<T>::bar(U); + + static void foo(); // expected-note {{declared private here}} + }; + + template <class T> class B { + void foo() { return A<long>::foo(); } // expected-error {{'foo' is a private member of 'test15::A<long>'}} + }; + + template <> class B<float> { + void foo() { return A<float>::foo(); } + template <class U> void bar(U u) { + (void) A<float>::foo(); + } + }; + + template class B<int>; // expected-note {{in instantiation}} +} diff --git a/test/CXX/temp/temp.decls/temp.friend/p5.cpp b/test/CXX/temp/temp.decls/temp.friend/p5.cpp index f23611b..63fd3df 100644 --- a/test/CXX/temp/temp.decls/temp.friend/p5.cpp +++ b/test/CXX/temp/temp.decls/temp.friend/p5.cpp @@ -1,13 +1,103 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -template <class T> class A { - class Member { +namespace test0 { + template <class T> class A { + class Member {}; }; -}; -class B { - template <class T> friend class A<T>::Member; -}; + class B { + template <class T> friend class A<T>::Member; + }; + + A<int> a; + B b; +} + +// rdar://problem/8204127 +namespace test1 { + template <class T> struct A; + + class C { + static void foo(); + template <class T> friend void A<T>::f(); + }; + + template <class T> struct A { + void f() { C::foo(); } + }; + + template <class T> struct A<T*> { + void f() { C::foo(); } + }; + + template <> struct A<char> { + void f() { C::foo(); } + }; +} + +// FIXME: these should fail! +namespace test2 { + template <class T> struct A; + + class C { + static void foo(); + template <class T> friend void A<T>::g(); + }; + + template <class T> struct A { + void f() { C::foo(); } + }; + + template <class T> struct A<T*> { + void f() { C::foo(); } + }; + + template <> struct A<char> { + void f() { C::foo(); } + }; +} + +// Tests 3, 4 and 5 were all noted in <rdar://problem/8540527>. +namespace test3 { + template <class T> struct A { + struct Inner { + static int foo(); + }; + }; + + template <class U> class C { + int i; + template <class T> friend struct A<T>::Inner; + }; + + template <class T> int A<T>::Inner::foo() { + C<int> c; + c.i = 0; + return 0; + } + + int test = A<int>::Inner::foo(); +} + +namespace test4 { + template <class T> struct X { + template <class U> void operator+=(U); + + template <class V> + template <class U> + friend void X<V>::operator+=(U); + }; + + void test() { + X<int>() += 1.0; + } +} + +namespace test5 { + template<template <class> class T> struct A { + template<template <class> class T> friend void A<T>::foo(); + }; -A<int> a; -B b; + template <class> struct B {}; + template class A<B>; +} diff --git a/test/CXX/temp/temp.decls/temp.friend/p8.cpp b/test/CXX/temp/temp.decls/temp.friend/p8.cpp new file mode 100644 index 0000000..d0221a3 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.friend/p8.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T> class A { }; + +class X { + template<class T> friend class A<T*>; // expected-error{{partial specialization cannot be declared as a friend}} +}; diff --git a/test/CXX/temp/temp.decls/temp.mem/p3.cpp b/test/CXX/temp/temp.decls/temp.mem/p3.cpp new file mode 100644 index 0000000..0eb747b --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.mem/p3.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <class T> struct AA { + template <class C> virtual void g(C); // expected-error{{'virtual' can not be specified on member function templates}} + virtual void f(); +}; diff --git a/test/CXX/temp/temp.decls/temp.mem/p5.cpp b/test/CXX/temp/temp.decls/temp.mem/p5.cpp index b0078d4..a188f05 100644 --- a/test/CXX/temp/temp.decls/temp.mem/p5.cpp +++ b/test/CXX/temp/temp.decls/temp.mem/p5.cpp @@ -63,12 +63,12 @@ struct X0 { template<typename T> operator const T*() const { T x = T(); - return x; // expected-error{{cannot initialize return object of type 'char const *' with an lvalue of type 'char'}} + return x; // expected-error{{cannot initialize return object of type 'const char *' with an lvalue of type 'char'}} } }; -template X0::operator const char*() const; // expected-note{{'X0::operator char const *<char>' requested here}} -template X0::operator const int*(); // expected-note{{'X0::operator int const *<int const>' requested here}} +template X0::operator const char*() const; // expected-note{{'X0::operator const char *<char>' requested here}} +template X0::operator const int*(); // expected-note{{'X0::operator const int *<const int>' requested here}} template X0::operator float*() const; // expected-error{{explicit instantiation of undefined function template}} void test_X0(X0 x0, const X0 &x0c) { diff --git a/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp b/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp new file mode 100644 index 0000000..383e268 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +namespace DeductionForInstantiation { + template<unsigned I, typename ...Types> + struct X { }; + + template<typename ...Types> + void f0(X<sizeof...(Types), Types&...>) { } + + // No explicitly-specified arguments + template void f0(X<0>); + template void f0(X<1, int&>); + template void f0(X<2, int&, short&>); + + // One explicitly-specified argument + template void f0<float>(X<1, float&>); + template void f0<double>(X<1, double&>); + + // Two explicitly-specialized arguments + template void f0<char, unsigned char>(X<2, char&, unsigned char&>); + template void f0<signed char, char>(X<2, signed char&, char&>); + + // FIXME: Extension of explicitly-specified arguments + // template void f0<short, int>(X<3, short&, int&, long&>); +} + +namespace DeductionWithConversion { + template<char...> struct char_values { + static const unsigned value = 0; + }; + + template<int C1, char C3> + struct char_values<C1, 12, C3> { + static const unsigned value = 1; + }; + + int check0[char_values<1, 12, 3>::value == 1? 1 : -1]; + + template<int...> struct int_values { + static const unsigned value = 0; + }; + + template<unsigned char C1, unsigned char C3> + struct int_values<C1, 12, C3> { + static const unsigned value = 1; + }; + + int check1[int_values<256, 12, 3>::value == 0? 1 : -1]; + int check2[int_values<3, 12, 3>::value == 1? 1 : -1]; +} diff --git a/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp b/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp new file mode 100644 index 0000000..83db171 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp @@ -0,0 +1,352 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Example bind implementation from the variadic templates proposal, +// ISO C++ committee document number N2080. + +// Helper type traits +template<typename T> +struct add_reference { + typedef T &type; +}; + +template<typename T> +struct add_reference<T&> { + typedef T &type; +}; + +template<typename T> +struct add_const_reference { + typedef T const &type; +}; + +template<typename T> +struct add_const_reference<T&> { + typedef T &type; +}; + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +template<typename T> +class reference_wrapper { + T *ptr; + +public: + reference_wrapper(T& t) : ptr(&t) { } + operator T&() const { return *ptr; } +}; + +template<typename T> reference_wrapper<T> ref(T& t) { + return reference_wrapper<T>(t); +} +template<typename T> reference_wrapper<const T> cref(const T& t) { + return reference_wrapper<const T>(t); +} + +template<typename... Values> class tuple; + +// Basis case: zero-length tuple +template<> class tuple<> { }; + +template<typename Head, typename... Tail> +class tuple<Head, Tail...> : private tuple<Tail...> { + typedef tuple<Tail...> inherited; + +public: + tuple() { } + // implicit copy-constructor is okay + + // Construct tuple from separate arguments. + tuple(typename add_const_reference<Head>::type v, + typename add_const_reference<Tail>::type... vtail) + : m_head(v), inherited(vtail...) { } + + // Construct tuple from another tuple. + template<typename... VValues> tuple(const tuple<VValues...>& other) + : m_head(other.head()), inherited(other.tail()) { } + + template<typename... VValues> tuple& + operator=(const tuple<VValues...>& other) { + m_head = other.head(); + tail() = other.tail(); + return *this; + } + + typename add_reference<Head>::type head() { return m_head; } + typename add_reference<const Head>::type head() const { return m_head; } + inherited& tail() { return *this; } + const inherited& tail() const { return *this; } + +protected: + Head m_head; +}; + +// Creation functions +template<typename T> +struct make_tuple_result { + typedef T type; +}; + +template<typename T> +struct make_tuple_result<reference_wrapper<T> > { + typedef T& type; +}; + +template<typename... Values> +tuple<typename make_tuple_result<Values>::type...> +make_tuple(const Values&... values) { + return tuple<typename make_tuple_result<Values>::type...>(values...); +} + +template<typename... Values> +tuple<Values&...> tie(Values&... values) { + return tuple<Values&...>(values...); +} + +// Helper classes +template<typename Tuple> struct tuple_size; + +template<typename... Values> struct tuple_size<tuple<Values...> > { + static const int value = sizeof...(Values); +}; + +template<int I, typename Tuple> struct tuple_element; + +template<int I, typename Head, typename... Tail> +struct tuple_element<I, tuple<Head, Tail...> > { + typedef typename tuple_element<I-1, tuple<Tail...> >::type type; +}; + +template<typename Head, typename... Tail> +struct tuple_element<0, tuple<Head, Tail...> > { + typedef Head type; +}; + +// Element access +template<int I, typename Tuple> class get_impl; +template<int I, typename Head, typename... Values> +class get_impl<I, tuple<Head, Values...> > { + typedef typename tuple_element<I-1, tuple<Values...> >::type Element; + typedef typename add_reference<Element>::type RJ; + typedef typename add_const_reference<Element>::type PJ; + typedef get_impl<I-1, tuple<Values...> > Next; +public: + static RJ get(tuple<Head, Values...>& t) { return Next::get(t.tail()); } + static PJ get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); } +}; + +template<typename Head, typename... Values> +class get_impl<0, tuple<Head, Values...> > { + typedef typename add_reference<Head>::type RJ; + typedef typename add_const_reference<Head>::type PJ; +public: + static RJ get(tuple<Head, Values...>& t) { return t.head(); } + static PJ get(const tuple<Head, Values...>& t) { return t.head(); } +}; + +template<int I, typename... Values> typename add_reference< +typename tuple_element<I, tuple<Values...> >::type >::type +get(tuple<Values...>& t) { + return get_impl<I, tuple<Values...> >::get(t); +} + +template<int I, typename... Values> typename add_const_reference< +typename tuple_element<I, tuple<Values...> >::type >::type +get(const tuple<Values...>& t) { + return get_impl<I, tuple<Values...> >::get(t); +} + +// Relational operators +inline bool operator==(const tuple<>&, const tuple<>&) { return true; } + +template<typename T, typename... TTail, typename U, typename... UTail> +bool operator==(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { + return t.head() == u.head() && t.tail() == u.tail(); +} + +template<typename... TValues, typename... UValues> +bool operator!=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(t == u); +} + +inline bool operator<(const tuple<>&, const tuple<>&) { return false; } + +template<typename T, typename... TTail, typename U, typename... UTail> +bool operator<(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { + return (t.head() < u.head() || (!(t.head() < u.head()) && t.tail() < u.tail())); +} + +template<typename... TValues, typename... UValues> +bool operator>(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return u < t; +} + +template<typename... TValues, typename... UValues> +bool operator<=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(u < t); +} + +template<typename... TValues, typename... UValues> +bool operator>=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(t < u); +} + +// make_indices helper +template<int...> struct int_tuple {}; +// make_indexes impl is a helper for make_indexes +template<int I, typename IntTuple, typename... Types> struct make_indexes_impl; + +template<int I, int... Indexes, typename T, typename... Types> +struct make_indexes_impl<I, int_tuple<Indexes...>, T, Types...> { + typedef typename make_indexes_impl<I+1, int_tuple<Indexes..., I>, Types...>::type type; +}; + +template<int I, int... Indexes> +struct make_indexes_impl<I, int_tuple<Indexes...> > { + typedef int_tuple<Indexes...> type; +}; + +template<typename... Types> +struct make_indexes : make_indexes_impl<0, int_tuple<>, Types...> { +}; + +// Bind +template<typename T> struct is_bind_expression { + static const bool value = false; +}; + +template<typename T> struct is_placeholder { + static const int value = 0; +}; + + +template<typename F, typename... BoundArgs> class bound_functor { + typedef typename make_indexes<BoundArgs...>::type indexes; +public: + typedef typename F::result_type result_type; + explicit bound_functor(const F& f, const BoundArgs&... bound_args) + : f(f), bound_args(bound_args...) { } template<typename... Args> + typename F::result_type operator()(Args&... args); +private: F f; + tuple<BoundArgs...> bound_args; +}; + +template<typename F, typename... BoundArgs> +inline bound_functor<F, BoundArgs...> bind(const F& f, const BoundArgs&... bound_args) { + return bound_functor<F, BoundArgs...>(f, bound_args...); +} + +template<typename F, typename ...BoundArgs> +struct is_bind_expression<bound_functor<F, BoundArgs...> > { + static const bool value = true; +}; + +// enable_if helper +template<bool Cond, typename T = void> +struct enable_if; + +template<typename T> +struct enable_if<true, T> { + typedef T type; +}; + +template<typename T> +struct enable_if<false, T> { }; + +// safe_tuple_element helper +template<int I, typename Tuple, typename = void> +struct safe_tuple_element { }; + +template<int I, typename... Values> +struct safe_tuple_element<I, tuple<Values...>, + typename enable_if<(I >= 0 && I < tuple_size<tuple<Values...> >::value)>::type> { + typedef typename tuple_element<I, tuple<Values...> >::type type; +}; + +// mu +template<typename Bound, typename... Args> +inline typename safe_tuple_element<is_placeholder<Bound>::value -1, + tuple<Args...> >::type +mu(Bound& bound_arg, const tuple<Args&...>& args) { + return get<is_placeholder<Bound>::value-1>(args); +} + +template<typename T, typename... Args> +inline T& mu(reference_wrapper<T>& bound_arg, const tuple<Args&...>&) { + return bound_arg.get(); +} + +template<typename F, int... Indexes, typename... Args> +inline typename F::result_type +unwrap_and_forward(F& f, int_tuple<Indexes...>, const tuple<Args&...>& args) { + return f(get<Indexes>(args)...); +} + +template<typename Bound, typename... Args> +inline typename enable_if<is_bind_expression<Bound>::value, + typename Bound::result_type>::type +mu(Bound& bound_arg, const tuple<Args&...>& args) { + typedef typename make_indexes<Args...>::type Indexes; + return unwrap_and_forward(bound_arg, Indexes(), args); +} + +template<typename T> +struct is_reference_wrapper { + static const bool value = false; +}; + +template<typename T> +struct is_reference_wrapper<reference_wrapper<T>> { + static const bool value = true; +}; + +template<typename Bound, typename... Args> +inline typename enable_if<(!is_bind_expression<Bound>::value + && !is_placeholder<Bound>::value + && !is_reference_wrapper<Bound>::value), + Bound&>::type +mu(Bound& bound_arg, const tuple<Args&...>&) { + return bound_arg; +} + +template<typename F, typename... BoundArgs, int... Indexes, typename... Args> +typename F::result_type apply_functor(F& f, tuple<BoundArgs...>& bound_args, + int_tuple<Indexes...>, + const tuple<Args&...>& args) { + return f(mu(get<Indexes>(bound_args), args)...); +} + +template<typename F, typename... BoundArgs> +template<typename... Args> +typename F::result_type bound_functor<F, BoundArgs...>::operator()(Args&... args) { + return apply_functor(f, bound_args, indexes(), tie(args...)); +} + +template<int N> struct placeholder { }; +template<int N> +struct is_placeholder<placeholder<N>> { + static const int value = N; +}; + +template<typename T> +struct plus { + typedef T result_type; + + T operator()(T x, T y) { return x + y; } +}; + +placeholder<1> _1; + +// Test bind +void test_bind() { + int x = 17; + int y = 25; + bind(plus<int>(), x, _1)(y); +} diff --git a/test/CXX/temp/temp.decls/temp.variadic/example-function.cpp b/test/CXX/temp/temp.decls/temp.variadic/example-function.cpp new file mode 100644 index 0000000..b3d010c --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/example-function.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Example function implementation from the variadic templates proposal, +// ISO C++ committee document number N2080. + +template<typename Signature> class function; + +template<typename R, typename... Args> class invoker_base { +public: + virtual ~invoker_base() { } + virtual R invoke(Args...) = 0; + virtual invoker_base* clone() = 0; +}; + +template<typename F, typename R, typename... Args> +class functor_invoker : public invoker_base<R, Args...> { +public: + explicit functor_invoker(const F& f) : f(f) { } + R invoke(Args... args) { return f(args...); } + functor_invoker* clone() { return new functor_invoker(f); } + +private: + F f; +}; + +template<typename R, typename... Args> +class function<R (Args...)> { +public: + typedef R result_type; + function() : invoker (0) { } + function(const function& other) : invoker(0) { + if (other.invoker) + invoker = other.invoker->clone(); + } + + template<typename F> function(const F& f) : invoker(0) { + invoker = new functor_invoker<F, R, Args...>(f); + } + + ~function() { + if (invoker) + delete invoker; + } + + function& operator=(const function& other) { + function(other).swap(*this); + return *this; + } + + template<typename F> + function& operator=(const F& f) { + function(f).swap(*this); + return *this; + } + + void swap(function& other) { + invoker_base<R, Args...>* tmp = invoker; + invoker = other.invoker; + other.invoker = tmp; + } + + result_type operator()(Args... args) const { + return invoker->invoke(args...); + } + +private: + invoker_base<R, Args...>* invoker; +}; + +template<typename T> +struct add { + T operator()(T x, T y) { return x + y; } +}; + +int add_ints(int x, int y) { return x + y; } + +void test_function() { + function<int(int, int)> f2a; + function<int(int, int)> f2b = add<int>(); + function<int(int, int)> f2c = add<float>(); + function<int(int, int)> f2d(f2b); + function<int(int, int)> f2e = &add_ints; + f2c = f2d; + f2d = &add_ints; + f2c(1.0, 3); +} diff --git a/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp b/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp new file mode 100644 index 0000000..3b4bd77 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp @@ -0,0 +1,260 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Example tuple implementation from the variadic templates proposal, +// ISO C++ committee document number N2080. + +// Helper type traits +template<typename T> +struct add_reference { + typedef T &type; +}; + +template<typename T> +struct add_reference<T&> { + typedef T &type; +}; + +template<typename T> +struct add_const_reference { + typedef T const &type; +}; + +template<typename T> +struct add_const_reference<T&> { + typedef T &type; +}; + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +template<typename T> +class reference_wrapper { + T *ptr; + +public: + reference_wrapper(T& t) : ptr(&t) { } + operator T&() const { return *ptr; } +}; + +template<typename T> reference_wrapper<T> ref(T& t) { + return reference_wrapper<T>(t); +} +template<typename T> reference_wrapper<const T> cref(const T& t) { + return reference_wrapper<const T>(t); +} + +template<typename... Values> class tuple; + +// Basis case: zero-length tuple +template<> class tuple<> { }; + +template<typename Head, typename... Tail> +class tuple<Head, Tail...> : private tuple<Tail...> { + typedef tuple<Tail...> inherited; + +public: + tuple() { } + // implicit copy-constructor is okay + + // Construct tuple from separate arguments. + tuple(typename add_const_reference<Head>::type v, + typename add_const_reference<Tail>::type... vtail) + : m_head(v), inherited(vtail...) { } + + // Construct tuple from another tuple. + template<typename... VValues> tuple(const tuple<VValues...>& other) + : m_head(other.head()), inherited(other.tail()) { } + + template<typename... VValues> tuple& + operator=(const tuple<VValues...>& other) { + m_head = other.head(); + tail() = other.tail(); + return *this; + } + + typename add_reference<Head>::type head() { return m_head; } + typename add_reference<const Head>::type head() const { return m_head; } + inherited& tail() { return *this; } + const inherited& tail() const { return *this; } + +protected: + Head m_head; +}; + +void test_tuple() { + tuple<> t0a; + tuple<> t0b(t0a); + t0a = t0b; + + tuple<int> t1a; + tuple<int> t1b(17); + tuple<int> t1c(t1b); + t1a = t1b; + + tuple<float> t1d(3.14159); + tuple<float> t1e(t1d); + t1d = t1e; + + int i; + float f; + double d; + tuple<int*, float*, double*> t3a(&i, &f, &d); +} + +// Creation functions +template<typename T> +struct make_tuple_result { + typedef T type; +}; + +template<typename T> +struct make_tuple_result<reference_wrapper<T> > { + typedef T& type; +}; + +template<typename... Values> +tuple<typename make_tuple_result<Values>::type...> +make_tuple(const Values&... values) { + return tuple<typename make_tuple_result<Values>::type...>(values...); +} + +template<typename... Values> +tuple<Values&...> tie(Values&... values) { + return tuple<Values&...>(values...); +} + +template<typename T> const T *addr(const T& ref) { return &ref; } +void test_creation_functions() { + int i; + float f; + double d; + const tuple<int, float&, const double&> *t3p = addr(make_tuple(i, ref(f), cref(d))); + const tuple<int&, float&, double&> *t3q = addr(tie(i, f, d)); +} + +// Helper classes +template<typename Tuple> struct tuple_size; + +template<typename... Values> struct tuple_size<tuple<Values...> > { + static const int value = sizeof...(Values); +}; + +int check_tuple_size_0[tuple_size<tuple<> >::value == 0? 1 : -1]; +int check_tuple_size_1[tuple_size<tuple<int>>::value == 1? 1 : -1]; +int check_tuple_size_2[tuple_size<tuple<float, double>>::value == 2? 1 : -1]; +int check_tuple_size_3[tuple_size<tuple<char, unsigned char, signed char>>::value == 3? 1 : -1]; + +template<int I, typename Tuple> struct tuple_element; + +template<int I, typename Head, typename... Tail> +struct tuple_element<I, tuple<Head, Tail...> > { + typedef typename tuple_element<I-1, tuple<Tail...> >::type type; +}; + +template<typename Head, typename... Tail> +struct tuple_element<0, tuple<Head, Tail...> > { + typedef Head type; +}; + +int check_tuple_element_0[is_same<tuple_element<0, tuple<int&, float, double>>::type, + int&>::value? 1 : -1]; + +int check_tuple_element_1[is_same<tuple_element<1, tuple<int&, float, double>>::type, + float>::value? 1 : -1]; + +int check_tuple_element_2[is_same<tuple_element<2, tuple<int&, float, double>>::type, + double>::value? 1 : -1]; + +// Element access +template<int I, typename Tuple> class get_impl; +template<int I, typename Head, typename... Values> +class get_impl<I, tuple<Head, Values...> > { + typedef typename tuple_element<I-1, tuple<Values...> >::type Element; + typedef typename add_reference<Element>::type RJ; + typedef typename add_const_reference<Element>::type PJ; + typedef get_impl<I-1, tuple<Values...> > Next; +public: + static RJ get(tuple<Head, Values...>& t) { return Next::get(t.tail()); } + static PJ get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); } +}; + +template<typename Head, typename... Values> +class get_impl<0, tuple<Head, Values...> > { + typedef typename add_reference<Head>::type RJ; + typedef typename add_const_reference<Head>::type PJ; +public: + static RJ get(tuple<Head, Values...>& t) { return t.head(); } + static PJ get(const tuple<Head, Values...>& t) { return t.head(); } +}; + +template<int I, typename... Values> typename add_reference< +typename tuple_element<I, tuple<Values...> >::type >::type +get(tuple<Values...>& t) { + return get_impl<I, tuple<Values...> >::get(t); +} + +template<int I, typename... Values> typename add_const_reference< +typename tuple_element<I, tuple<Values...> >::type >::type +get(const tuple<Values...>& t) { + return get_impl<I, tuple<Values...> >::get(t); +} + +void test_element_access(tuple<int*, float*, double*&> t3) { + int i; + float f; + double d; + get<0>(t3) = &i; + get<1>(t3) = &f; + get<2>(t3) = &d; +} + +// Relational operators +inline bool operator==(const tuple<>&, const tuple<>&) { return true; } + +template<typename T, typename... TTail, typename U, typename... UTail> +bool operator==(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { + return t.head() == u.head() && t.tail() == u.tail(); +} + +template<typename... TValues, typename... UValues> +bool operator!=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(t == u); +} + +inline bool operator<(const tuple<>&, const tuple<>&) { return false; } + +template<typename T, typename... TTail, typename U, typename... UTail> +bool operator<(const tuple<T, TTail...>& t, const tuple<U, UTail...>& u) { + return (t.head() < u.head() || (!(t.head() < u.head()) && t.tail() < u.tail())); +} + +template<typename... TValues, typename... UValues> +bool operator>(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return u < t; +} + +template<typename... TValues, typename... UValues> +bool operator<=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(u < t); +} + +template<typename... TValues, typename... UValues> +bool operator>=(const tuple<TValues...>& t, const tuple<UValues...>& u) { + return !(t < u); +} + +void test_relational_operators(tuple<int*, float*, double*> t3) { + (void)(t3 == t3); + (void)(t3 != t3); + (void)(t3 < t3); + (void)(t3 <= t3); + (void)(t3 >= t3); + (void)(t3 > t3); +}; diff --git a/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp b/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp new file mode 100644 index 0000000..62cf429 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -std=c++0x -fblocks -fsyntax-only -verify %s + +// Tests the use of blocks with variadic templates. +template<typename ...Args> +int f0(Args ...args) { + return ^ { + return sizeof...(Args); + }() + ^ { + return sizeof...(args); + }(); +} + +template<typename ...Args> +int f1(Args ...args) { + return ^ { + return f0(args...); + }(); +} + +template int f0(int, float, double); +template int f1(const char*, int, float, double); + +template<typename ...Args> +int f2(Args ...args) { + return ^(Args ...block_args) { + return f1(block_args...); + }(args + 0 ...); +} + +template int f2(const char*, int, float, double); + +template<typename ...Args> +int f3(Args ...args) { + return ^(Args *...block_args) { + return f1(block_args...); + }(&args...); +} + +template int f3(const char*, int, float, double); diff --git a/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp b/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp new file mode 100644 index 0000000..a76ef80 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Check for declaration matching with out-of-line declarations and +// variadic templates, which involves proper computation of the +// injected-class-name. +template<typename T, typename ...Types> +struct X0 { + typedef T type; + + void f0(T); + type f1(T); +}; + +template<typename T, typename ...Types> +void X0<T, Types...>::f0(T) { } + +template<typename T, typename ...Types> +typename X0<T, Types...>::type X0<T, Types...>::f1(T) { } + +template<typename T, typename ...Types> +struct X0<T, T, Types...> { + typedef T* result; + result f3(); + + template<typename... InnerTypes> + struct Inner; +}; + +template<typename T, typename ...Types> +typename X0<T, T, Types...>::result X0<T, T, Types...>::f3() { return 0; } + +template<typename T, typename ...Types> +template<typename ...InnerTypes> +struct X0<T, T, Types...>::Inner { + template<typename ...ReallyInner> void f4(); +}; + +template<typename T, typename ...Types> +template<typename ...InnerTypes> +template<typename ...ReallyInner> +void X0<T, T, Types...>::Inner<InnerTypes...>::f4() { } + +namespace rdar8848837 { + // Out-of-line definitions that cause rebuilding in the current + // instantiation. + template<typename F> struct X; + + template<typename R, typename ...ArgTypes> + struct X<R(ArgTypes...)> { + X<R(ArgTypes...)> f(); + }; + + template<typename R, typename ...ArgTypes> + X<R(ArgTypes...)> X<R(ArgTypes...)>::f() { return *this; } + + + X<int(float, double)> xif; + + template<unsigned> struct unsigned_c { }; + template<typename ...ArgTypes> int g(ArgTypes...); + + template<typename F> struct X1; + + template<typename R, typename ...ArgTypes> + struct X1<R(ArgTypes...)> { + unsigned_c<sizeof(1 + g(ArgTypes()...))> f(); + }; + + template<typename R, typename ...ArgTypes> + unsigned_c<sizeof(1 + g(ArgTypes()...))> X1<R(ArgTypes...)>::f() { + return unsigned_c<sizeof(int)>(); + } + + X1<int(float, double)> xif2; +} diff --git a/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp b/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp new file mode 100644 index 0000000..d80182c --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp @@ -0,0 +1,274 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// This is a collection of various template metafunctions involving +// variadic templates, which are meant to exercise common use cases. +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +template<typename...> struct tuple { }; +template<int ...> struct int_tuple { }; +template<typename T, typename U> struct pair { }; + +namespace Count { + template<typename Head, typename ...Tail> + struct count { + static const unsigned value = 1 + count<Tail...>::value; + }; + + template<typename T> + struct count<T> { + static const unsigned value = 1; + }; + + int check1[count<int>::value == 1? 1 : -1]; + int check2[count<float, double>::value == 2? 1 : -1]; + int check3[count<char, signed char, unsigned char>::value == 3? 1 : -1]; +} + +namespace CountWithPackExpansion { + template<typename ...> struct count; + + template<typename Head, typename ...Tail> + struct count<Head, Tail...> { + static const unsigned value = 1 + count<Tail...>::value; + }; + + template<> + struct count<> { + static const unsigned value = 0; + }; + + int check0[count<>::value == 0? 1 : -1]; + int check1[count<int>::value == 1? 1 : -1]; + int check2[count<float, double>::value == 2? 1 : -1]; + int check3[count<char, signed char, unsigned char>::value == 3? 1 : -1]; +} + +namespace Replace { + // Simple metafunction that replaces the template arguments of + // template template parameters with 'int'. + template<typename T> + struct EverythingToInt; + + template<template<typename ...> class TT, typename T1, typename T2> + struct EverythingToInt<TT<T1, T2> > { + typedef TT<int, int> type; + }; + + int check0[is_same<EverythingToInt<tuple<double, float>>::type, + tuple<int, int>>::value? 1 : -1]; +} + +namespace Math { + template<int ...Values> + struct double_values { + typedef int_tuple<Values*2 ...> type; + }; + + int check0[is_same<double_values<1, 2, -3>::type, + int_tuple<2, 4, -6>>::value? 1 : -1]; + + template<int ...Values> + struct square { + typedef int_tuple<(Values*Values)...> type; + }; + + int check1[is_same<square<1, 2, -3>::type, + int_tuple<1, 4, 9>>::value? 1 : -1]; + + template<typename IntTuple> struct square_tuple; + + template<int ...Values> + struct square_tuple<int_tuple<Values...>> { + typedef int_tuple<(Values*Values)...> type; + }; + + int check2[is_same<square_tuple<int_tuple<1, 2, -3> >::type, + int_tuple<1, 4, 9>>::value? 1 : -1]; + + template<int ...Values> struct sum; + + template<int First, int ...Rest> + struct sum<First, Rest...> { + static const int value = First + sum<Rest...>::value; + }; + + template<> + struct sum<> { + static const int value = 0; + }; + + int check3[sum<1, 2, 3, 4, 5>::value == 15? 1 : -1]; + + template<int ... Values> + struct lazy_sum { + int operator()() { + return sum<Values...>::value; + } + }; + + void f() { + lazy_sum<1, 2, 3, 4, 5>()(); + } +} + +namespace ListMath { + template<typename T, T ... V> struct add; + + template<typename T, T i, T ... V> + struct add<T, i, V...> { + static const T value = i + add<T, V...>::value; + }; + + template<typename T> + struct add<T> { + static const T value = T(); + }; + + template<typename T, T ... V> + struct List { + struct sum { + static const T value = add<T, V...>::value; + }; + }; + + template<int ... V> + struct ListI : public List<int, V...> { + }; + + int check0[ListI<1, 2, 3>::sum::value == 6? 1 : -1]; +} + +namespace Indices { + template<unsigned I, unsigned N, typename IntTuple> + struct build_indices_impl; + + template<unsigned I, unsigned N, int ...Indices> + struct build_indices_impl<I, N, int_tuple<Indices...> > + : build_indices_impl<I+1, N, int_tuple<Indices..., I> > { + }; + + template<unsigned N, int ...Indices> + struct build_indices_impl<N, N, int_tuple<Indices...> > { + typedef int_tuple<Indices...> type; + }; + + template<unsigned N> + struct build_indices : build_indices_impl<0, N, int_tuple<> > { }; + + int check0[is_same<build_indices<5>::type, + int_tuple<0, 1, 2, 3, 4>>::value? 1 : -1]; +} + +namespace TemplateTemplateApply { + template<typename T, template<class> class ...Meta> + struct apply_each { + typedef tuple<typename Meta<T>::type...> type; + }; + + template<typename T> + struct add_reference { + typedef T& type; + }; + + template<typename T> + struct add_pointer { + typedef T* type; + }; + + template<typename T> + struct add_const { + typedef const T type; + }; + + int check0[is_same<apply_each<int, + add_reference, add_pointer, add_const>::type, + tuple<int&, int*, int const>>::value? 1 : -1]; + + template<typename T, template<class> class ...Meta> + struct apply_each_indirect { + typedef typename apply_each<T, Meta...>::type type; + }; + + int check1[is_same<apply_each_indirect<int, add_reference, add_pointer, + add_const>::type, + tuple<int&, int*, int const>>::value? 1 : -1]; + + template<typename T, typename ...Meta> + struct apply_each_nested { + typedef typename apply_each<T, Meta::template apply...>::type type; + }; + + struct add_reference_meta { + template<typename T> + struct apply { + typedef T& type; + }; + }; + + struct add_pointer_meta { + template<typename T> + struct apply { + typedef T* type; + }; + }; + + struct add_const_meta { + template<typename T> + struct apply { + typedef const T type; + }; + }; + + int check2[is_same<apply_each_nested<int, add_reference_meta, + add_pointer_meta, add_const_meta>::type, + tuple<int&, int*, int const>>::value? 1 : -1]; + +} + +namespace FunctionTypes { + template<typename FunctionType> + struct Arity; + + template<typename R, typename ...Types> + struct Arity<R(Types...)> { + static const unsigned value = sizeof...(Types); + }; + + template<typename R, typename ...Types> + struct Arity<R(Types......)> { + static const unsigned value = sizeof...(Types); + }; + + template<typename R, typename T1, typename T2, typename T3, typename T4> + struct Arity<R(T1, T2, T3, T4)>; // expected-note{{template is declared here}} + + int check0[Arity<int()>::value == 0? 1 : -1]; + int check1[Arity<int(float, double)>::value == 2? 1 : -1]; + int check2[Arity<int(float...)>::value == 1? 1 : -1]; + int check3[Arity<int(float, double, long double...)>::value == 3? 1 : -1]; + Arity<int(float, double, long double, char)> check4; // expected-error{{implicit instantiation of undefined template 'FunctionTypes::Arity<int (float, double, long double, char)>'}} +} + +namespace SuperReplace { + template<typename T> + struct replace_with_int { + typedef int type; + }; + + template<template<typename ...> class TT, typename ...Types> + struct replace_with_int<TT<Types...>> { + typedef TT<typename replace_with_int<Types>::type...> type; + }; + + int check0[is_same<replace_with_int<pair<tuple<float, double, short>, + pair<char, unsigned char>>>::type, + pair<tuple<int, int, int>, pair<int, int>>>::value? 1 : -1]; +} diff --git a/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp b/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp new file mode 100644 index 0000000..2df6d33 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp @@ -0,0 +1,218 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template<typename T, T ...Values> struct value_tuple {}; +template<typename...> struct tuple { }; +template<typename T, typename U> struct pair { }; + +template<typename T, T Value> struct value_c; + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +template<typename T> +struct X0 { + template<T ...Values> + void f(value_tuple<T, Values...> * = 0); +}; + +void test_X0() { + X0<int>().f<1, 2, 3, 4, 5>(); +} + +namespace PacksAtDifferentLevels { + + template<typename ...Types> + struct X { + template<typename> struct Inner { + static const unsigned value = 1; + }; + + template<typename ...YTypes> + struct Inner<tuple<pair<Types, YTypes>...> > { + static const unsigned value = sizeof...(Types) - sizeof...(YTypes); + }; + }; + + int check0[X<short, int, long>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>> + >::value == 0? 1 : -1]; + + int check1[X<short, int>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>> + >::value == 1? 1 : -1]; + + template<unsigned ...Values> struct unsigned_tuple { }; + template<typename ...Types> + struct X1 { + template<typename, typename> struct Inner { + static const unsigned value = 0; + }; + + template<typename ...YTypes> + struct Inner<tuple<pair<Types, YTypes>...>, + unsigned_tuple<sizeof(Types) + sizeof(YTypes)...>> { + static const unsigned value = 1; + }; + }; + + int check2[X1<short, int, long>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>>, + unsigned_tuple<sizeof(short) + sizeof(unsigned short), + sizeof(int) + sizeof(unsigned int), + sizeof(long) + sizeof(unsigned long)> + >::value == 1? 1 : -1]; + int check3[X1<short, int>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>>, + unsigned_tuple<sizeof(short) + sizeof(unsigned short), + sizeof(int) + sizeof(unsigned int), + sizeof(long) + sizeof(unsigned long)> + >::value == 0? 1 : -1]; + + template<typename ...Types> + struct X2 { + template<typename> struct Inner { + static const unsigned value = 1; + }; + + template<typename R, typename ...YTypes> + struct Inner<R(pair<Types, YTypes>...)> { + static const unsigned value = sizeof...(Types) - sizeof...(YTypes); + }; + }; + + int check4[X2<short, int, long>::Inner<int(pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>) + >::value == 0? 1 : -1]; + + int check5[X2<short, int>::Inner<int(pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>) + >::value == 1? 1 : -1]; + + template<typename T, typename U> + struct some_function_object { + template<typename> + struct result_of; + }; + + template<template<class> class...> struct metafun_tuple { }; + + template<typename ...Types1> + struct X3 { + template<typename, typename> struct Inner { + static const unsigned value = 0; + }; + + template<typename ...Types2> + struct Inner<tuple<pair<Types1, Types2>...>, + metafun_tuple<some_function_object<Types1, Types2>::template result_of...> > { + static const unsigned value = 1; + }; + }; + + int check6[X3<short, int, long>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>>, + metafun_tuple< + some_function_object<short, unsigned short>::result_of, + some_function_object<int, unsigned int>::result_of, + some_function_object<long, unsigned long>::result_of> + >::value == 1? 1 : -1]; + int check7[X3<short, int>::Inner<tuple<pair<short, unsigned short>, + pair<int, unsigned int>, + pair<long, unsigned long>>, + metafun_tuple< + some_function_object<short, unsigned short>::result_of, + some_function_object<int, unsigned int>::result_of, + some_function_object<long, unsigned long>::result_of> + >::value == 0? 1 : -1]; + + template<unsigned I, unsigned J> struct unsigned_pair { }; + + template<unsigned ...Values1> + struct X4 { + template<typename> struct Inner { + static const unsigned value = 0; + }; + + template<unsigned ...Values2> + struct Inner<tuple<unsigned_pair<Values1, Values2>...>> { + static const unsigned value = 1; + }; + }; + + int check8[X4<1, 3, 5>::Inner<tuple<unsigned_pair<1, 2>, + unsigned_pair<3, 4>, + unsigned_pair<5, 6>> + >::value == 1? 1 : -1]; + int check9[X4<1, 3>::Inner<tuple<unsigned_pair<1, 2>, + unsigned_pair<3, 4>, + unsigned_pair<5, 6>> + >::value == 0? 1 : -1]; + + template<class> struct add_reference; + template<class> struct add_pointer; + template<class> struct add_const; + + template<template<class> class ...Templates> + struct X5 { + template<typename> struct Inner { + static const unsigned value = 0; + }; + + template<typename ...Types> + struct Inner<tuple<Templates<Types>...>> { + static const unsigned value = 1; + }; + }; + + int check10[X5<add_reference, add_pointer, add_const> + ::Inner<tuple<add_reference<int>, + add_pointer<float>, + add_const<double>>>::value == 1? 1 : -1]; + int check11[X5<add_reference, add_pointer> + ::Inner<tuple<add_reference<int>, + add_pointer<float>, + add_const<double>>>::value == 0? 1 : -1]; + +} + +namespace ExpandingNonTypeTemplateParameters { + template<typename ...Types> + struct tuple_of_values { + template<Types ...Values> // expected-error{{a non-type template parameter cannot have type 'float'}} \ + // expected-note{{template parameter is declared here}} + struct apply { // expected-note 2{{template is declared here}} + typedef tuple<value_c<Types, Values>...> type; + }; + }; + + int i; + float f; + int check_tuple_of_values_1[ + is_same<tuple_of_values<int&, float&, char, int>::apply<i, f, 'a', 17> + ::type, + tuple<value_c<int&, i>, value_c<float&, f>, value_c<char, 'a'>, + value_c<int, 17>> + >::value? 1 : -1]; + + tuple_of_values<int, float> tv1; // expected-note{{in instantiation of template class 'ExpandingNonTypeTemplateParameters::tuple_of_values<int, float>' requested here}} + + tuple_of_values<int&, float&>::apply<i, i>::type tv2; // expected-error{{non-type template parameter of reference type 'float &' cannot bind to template argument of type 'int'}} + + tuple_of_values<int&, float&>::apply<i>::type tv3; // expected-error{{too few template arguments for class template 'apply'}} + + tuple_of_values<int&, float&>::apply<i, f, i>::type tv4; // expected-error{{too many template arguments for class template 'apply'}} +} diff --git a/test/CXX/temp/temp.decls/temp.variadic/p1.cpp b/test/CXX/temp/temp.decls/temp.variadic/p1.cpp new file mode 100644 index 0000000..02f4c59 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/p1.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template<class ...Types> struct Tuple; + +Tuple<> *t0; +Tuple<int> *t1; +Tuple<int, char> *t2a; +Tuple<int, float> *t2b = t2a; // expected-error{{cannot initialize a variable of type 'Tuple<int, float> *' with an lvalue of type 'Tuple<int, char> *'}} +Tuple<int, float, double> *t3; diff --git a/test/CXX/temp/temp.decls/temp.variadic/p2.cpp b/test/CXX/temp/temp.decls/temp.variadic/p2.cpp new file mode 100644 index 0000000..100ae2c --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/p2.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template<class ... Types> void f(Types ... args); + +void test() { + f(); + f(1); + f(2, 1.0); +} + +// Test simple recursive variadic function template +template<typename Head, typename ...Tail> +void recurse_until_fail(const Head &, const Tail &...tail) { // expected-note{{candidate function template not viable: requires at least 1 argument, but 0 were provided}} + recurse_until_fail(tail...); // expected-error{{no matching function for call to 'recurse_until_fail'}} \ + // expected-note{{in instantiation of function template specialization 'recurse_until_fail<char [7], >' requested here}} \ + // expected-note{{in instantiation of function template specialization 'recurse_until_fail<double, char [7]>' requested here}} +} + +void test_recurse_until_fail() { + recurse_until_fail(1, 3.14159, "string"); // expected-note{{in instantiation of function template specialization 'recurse_until_fail<int, double, char [7]>' requested here}} + +} diff --git a/test/CXX/temp/temp.decls/temp.variadic/p4.cpp b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp new file mode 100644 index 0000000..e2fa122 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp @@ -0,0 +1,135 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -fexceptions -verify %s + +template<typename... Types> struct tuple; +template<int I> struct int_c; + +template<typename T> +struct identity { + typedef T type; +}; + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +// FIXME: Several more bullets to go + +// In an initializer-list (8.5); the pattern is an initializer-clause. +// Note: this also covers expression-lists, since expression-list is +// just defined as initializer-list. +void five_args(int, int, int, int, int); // expected-note{{candidate function not viable: requires 5 arguments, but 6 were provided}} + +template<int ...Values> +void initializer_list_expansion() { + int values[5] = { Values... }; // expected-error{{excess elements in array initializer}} + five_args(Values...); // expected-error{{no matching function for call to 'five_args'}} +} + +template void initializer_list_expansion<1, 2, 3, 4, 5>(); +template void initializer_list_expansion<1, 2, 3, 4, 5, 6>(); // expected-note{{in instantiation of function template specialization 'initializer_list_expansion<1, 2, 3, 4, 5, 6>' requested here}} + +namespace PR8977 { + struct A { }; + template<typename T, typename... Args> void f(Args... args) { + T t(args...); + }; + + template void f<A>(); +} + +// In a base-specifier-list (Clause 10); the pattern is a base-specifier. +template<typename ...Mixins> +struct HasMixins : public Mixins... { + HasMixins(); + HasMixins(const HasMixins&); + HasMixins(int i); +}; + +struct A { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const A' for 1st argument}} \ +// expected-note{{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} +struct B { }; +struct C { }; +struct D { }; + +A *checkA = new HasMixins<A, B, C, D>; +B *checkB = new HasMixins<A, B, C, D>; +D *checkD = new HasMixins<A, B, C, D>; +C *checkC = new HasMixins<A, B, D>; // expected-error{{cannot initialize a variable of type 'C *' with an rvalue of type 'HasMixins<A, B, D> *'}} +HasMixins<> *checkNone = new HasMixins<>; + +template<typename Mixins> +struct BrokenMixins : public Mixins... { }; // expected-error{{pack expansion does not contain any unexpanded parameter packs}} + +// In a mem-initializer-list (12.6.2); the pattern is a mem-initializer. +template<typename ...Mixins> +HasMixins<Mixins...>::HasMixins(): Mixins()... { } + +template<typename ...Mixins> +HasMixins<Mixins...>::HasMixins(const HasMixins &other): Mixins(other)... { } + +template<typename ...Mixins> +HasMixins<Mixins...>::HasMixins(int i): Mixins(i)... { } // expected-error{{no matching constructor for initialization of 'A'}} + +void test_has_mixins() { + HasMixins<A, B> ab; + HasMixins<A, B> ab2 = ab; + HasMixins<A, B> ab3(17); // expected-note{{in instantiation of member function 'HasMixins<A, B>::HasMixins' requested here}} +} + +template<typename T> +struct X { + T member; + + X() : member()... { } // expected-error{{pack expansion for initialization of member 'member'}} +}; + +// In a template-argument-list (14.3); the pattern is a template-argument. +template<typename ...Types> +struct tuple_of_refs { + typedef tuple<Types& ...> types; +}; + +tuple<int&, float&> *t_int_ref_float_ref; +tuple_of_refs<int&, float&>::types *t_int_ref_float_ref_2 = t_int_ref_float_ref; + +template<typename ...Types> +struct extract_nested_types { + typedef tuple<typename Types::type...> types; +}; + +tuple<int, float> *t_int_float; +extract_nested_types<identity<int>, identity<float> >::types *t_int_float_2 + = t_int_float; + +template<int ...N> +struct tuple_of_ints { + typedef tuple<int_c<N>...> type; +}; + +int check_temp_arg_1[is_same<tuple_of_ints<1, 2, 3, 4, 5>::type, + tuple<int_c<1>, int_c<2>, int_c<3>, int_c<4>, + int_c<5>>>::value? 1 : -1]; + +// In a dynamic-exception-specification (15.4); the pattern is a type-id. +template<typename ...Types> +struct f_with_except { + virtual void f() throw(Types...); // expected-note{{overridden virtual function is here}} +}; + +struct check_f_with_except_1 : f_with_except<int, float> { + virtual void f() throw(int, float); +}; + +struct check_f_with_except_2 : f_with_except<int, float> { + virtual void f() throw(int); +}; + +struct check_f_with_except_3 : f_with_except<int, float> { + virtual void f() throw(int, float, double); // expected-error{{exception specification of overriding function is more lax than base version}} +}; diff --git a/test/CXX/temp/temp.decls/temp.variadic/p5.cpp b/test/CXX/temp/temp.decls/temp.variadic/p5.cpp new file mode 100644 index 0000000..1acc21e --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/p5.cpp @@ -0,0 +1,393 @@ +// RUN: %clang_cc1 -fexceptions -std=c++0x -fblocks -fms-extensions -fsyntax-only -verify %s + +template<typename T, typename U> struct pair; +template<typename ...> struct tuple; + +// A parameter pack whose name appears within the pattern of a pack +// expansion is expanded by that pack expansion. An appearance of the +// name of a parameter pack is only expanded by the innermost +// enclosing pack expansion. The pattern of a pack expansion shall +// name one or more parameter packs that are not expanded by a nested +// pack expansion. +template<typename... Types> +struct Expansion { + typedef pair<Types..., int> expand_with_pacs; // okay + typedef pair<Types, int...> expand_no_packs; // expected-error{{pack expansion does not contain any unexpanded parameter packs}} + typedef pair<pair<Types..., int>..., int> expand_with_expanded_nested; // expected-error{{pack expansion does not contain any unexpanded parameter packs}} +}; + +// All of the parameter packs expanded by a pack expansion shall have +// the same number of arguments specified. +template<typename ...Types> +struct ExpansionLengthMismatch { + template<typename ...OtherTypes> + struct Inner { + typedef tuple<pair<Types, OtherTypes>...> type; // expected-error{{pack expansion contains parameter packs 'Types' and 'OtherTypes' that have different lengths (3 vs. 2)}} + }; +}; + +ExpansionLengthMismatch<int, long>::Inner<unsigned int, unsigned long>::type + *il_pairs; +tuple<pair<int, unsigned int>, pair<long, unsigned long> >*il_pairs_2 = il_pairs; + +ExpansionLengthMismatch<short, int, long>::Inner<unsigned int, unsigned long>::type // expected-note{{in instantiation of template class 'ExpansionLengthMismatch<short, int, long>::Inner<unsigned int, unsigned long>' requested here}} + *il_pairs_bad; + + +// An appearance of a name of a parameter pack that is not expanded is +// ill-formed. + +// Test for unexpanded parameter packs in each of the type nodes. +template<typename T, int N, typename ... Types> +struct TestPPName + : public Types, public T // expected-error{{base type contains unexpanded parameter pack 'Types'}} +{ + // BuiltinType is uninteresting + // FIXME: ComplexType is uninteresting? + // PointerType + typedef Types *types_pointer; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // BlockPointerType + typedef Types (^block_pointer_1)(int); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + typedef int (^block_pointer_2)(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // LValueReferenceType + typedef Types &lvalue_ref; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // RValueReferenceType + typedef Types &&rvalue_ref; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // MemberPointerType + typedef Types TestPPName::* member_pointer_1; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + typedef int Types::*member_pointer_2; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // ConstantArrayType + typedef Types constant_array[17]; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // IncompleteArrayType + typedef Types incomplete_array[]; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // VariableArrayType + void f(int i) { + Types variable_array[i]; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + } + + // DependentSizedArrayType + typedef Types dependent_sized_array[N]; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // DependentSizedExtVectorType + typedef Types dependent_sized_ext_vector __attribute__((ext_vector_type(N))); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // VectorType is uninteresting + + // ExtVectorType + typedef Types ext_vector __attribute__((ext_vector_type(4))); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // FunctionProtoType + typedef Types (function_type_1)(int); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + typedef int (function_type_2)(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // FunctionNoProtoType is uninteresting + // UnresolvedUsingType is uninteresting + // ParenType is uninteresting + // TypedefType is uninteresting + + // TypeOfExprType + typedef __typeof__((static_cast<Types>(0))) typeof_expr; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // TypeOfType + typedef __typeof__(Types) typeof_type; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // DecltypeType + typedef decltype((static_cast<Types>(0))) typeof_expr; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // RecordType is uninteresting + // EnumType is uninteresting + // ElaboratedType is uninteresting + + // TemplateTypeParmType + typedef Types template_type_parm; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // SubstTemplateTypeParmType is uninteresting + + // TemplateSpecializationType + typedef pair<Types, int> template_specialization; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // InjectedClassName is uninteresting. + + // DependentNameType + typedef typename Types::type dependent_name; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // DependentTemplateSpecializationType + typedef typename Types::template apply<int> dependent_name_1; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + typedef typename T::template apply<Types> dependent_name_2; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + + // ObjCObjectType is uninteresting + // ObjCInterfaceType is uninteresting + // ObjCObjectPointerType is uninteresting +}; + +// FIXME: Test for unexpanded parameter packs in each of the expression nodes. +template<int ...Values> +void test_unexpanded_in_exprs() { + // PredefinedExpr is uninteresting + // DeclRefExpr + Values; // expected-error{{expression contains unexpanded parameter pack 'Values'}} + // IntegerLiteral is uninteresting + // FloatingLiteral is uninteresting + // ImaginaryLiteral is uninteresting + // StringLiteral is uninteresting + // CharacterLiteral is uninteresting + (Values); // expected-error{{expression contains unexpanded parameter pack 'Values'}} + // UnaryOperator + -Values; // expected-error{{expression contains unexpanded parameter pack 'Values'}} + // OffsetOfExpr + struct OffsetMe { + int array[17]; + }; + __builtin_offsetof(OffsetMe, array[Values]); // expected-error{{expression contains unexpanded parameter pack 'Values'}} + // FIXME: continue this... +} + +template<typename ... Types> +void TestPPNameFunc(int i) { + f(static_cast<Types>(i)); // expected-error{{expression contains unexpanded parameter pack 'Types'}} +} + +template<typename T, template<class> class ...Meta> +struct TestUnexpandedTTP { + typedef tuple<typename Meta<T>::type> type; // expected-error{{declaration type contains unexpanded parameter pack 'Meta'}} +}; + +// Test for unexpanded parameter packs in declarations. +// FIXME: Attributes? +template<typename T, typename... Types> +struct TestUnexpandedDecls : T{ + void member_function(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + void member_function () throw(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + operator Types() const; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + Types data_member; // expected-error{{data member type contains unexpanded parameter pack 'Types'}} + static Types static_data_member; // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + unsigned bit_field : static_cast<Types>(0); // expected-error{{bit-field size contains unexpanded parameter pack 'Types'}} + static_assert(static_cast<Types>(0), "Boom"); // expected-error{{static assertion contains unexpanded parameter pack 'Types'}} + + enum E0 : Types { // expected-error{{fixed underlying type contains unexpanded parameter pack 'Types'}} + EnumValue = static_cast<Types>(0) // expected-error{{enumerator value contains unexpanded parameter pack 'Types'}} + }; + + using typename Types::type; // expected-error{{using declaration contains unexpanded parameter pack 'Types'}} + using Types::value; // expected-error{{using declaration contains unexpanded parameter pack 'Types'}} + using T::operator Types; // expected-error{{using declaration contains unexpanded parameter pack 'Types'}} + + friend class Types::foo; // expected-error{{friend declaration contains unexpanded parameter pack 'Types'}} + friend void friend_func(Types); // expected-error{{friend declaration contains unexpanded parameter pack 'Types'}} + friend void Types::other_friend_func(int); // expected-error{{friend declaration contains unexpanded parameter pack 'Types'}} + + void test_initializers() { + T copy_init = static_cast<Types>(0); // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + T direct_init(0, static_cast<Types>(0)); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + T list_init = { static_cast<Types>(0) }; // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + } + + void default_function_args(T = static_cast<Types>(0)); // expected-error{{default argument contains unexpanded parameter pack 'Types'}} + + template<typename = Types*> // expected-error{{default argument contains unexpanded parameter pack 'Types'}} + struct default_template_args_1; + template<int = static_cast<Types>(0)> // expected-error{{default argument contains unexpanded parameter pack 'Types'}} + struct default_template_args_2; + template<template<typename> class = Types::template apply> // expected-error{{default argument contains unexpanded parameter pack 'Types'}} + struct default_template_args_3; + + template<Types value> // expected-error{{non-type template parameter type contains unexpanded parameter pack 'Types'}} + struct non_type_template_param_type; + + void decls_in_stmts() { + 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'}} + 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'}} + try { + } catch (Types*) { // expected-error{{exception type contains unexpanded parameter pack 'Types'}} + } + } +}; + +// FIXME: Test for unexpanded parameter packs in each of the statements. +struct X { + void f(int, int); + template<typename ...Types> + void f(Types...); +}; + +namespace std { + class type_info; +} + +typedef struct _GUID { + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[ 8 ]; +} GUID; + +template<typename T, typename ...Types> +void test_unexpanded_exprs(Types ...values) { + // CXXOperatorCallExpr + (void)(values + 0); // expected-error{{expression contains unexpanded parameter pack 'values'}} + (void)(0 + values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXMemberCallExpr + values.f(); // expected-error{{expression contains unexpanded parameter pack 'values'}} + X x; + x.f(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + x.Types::f(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + x.f<Types>(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // CXXStaticCastExpr + (void)static_cast<Types&>(values); // expected-error{{expression contains unexpanded parameter packs 'Types' and 'values'}} + + // CXXDynamicCastExpr + (void)dynamic_cast<Types&>(values); // expected-error{{expression contains unexpanded parameter packs 'Types' and 'values'}} + + // CXXReinterpretCastExpr + (void)reinterpret_cast<Types&>(values); // expected-error{{expression contains unexpanded parameter packs 'Types' and 'values'}} + + // CXXConstCastExpr + (void)const_cast<Types&>(values); // expected-error{{expression contains unexpanded parameter packs 'Types' and 'values'}} + + // CXXTypeidExpr + (void)typeid(Types); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + (void)typeid(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXUuidofExpr + (void)__uuidof(Types); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + (void)__uuidof(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXThisExpr is uninteresting + + // CXXThrowExpr + throw Types(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + throw values; // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXDefaultArgExpr is uninteresting + + // CXXBindTemporaryExpr is uninteresting + + // CXXConstructExpr is uninteresting + + // CXXFunctionalCastExpr + (void)Types(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // CXXTemporaryObjectExpr + (void)X(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXScalarValueInitExpr is uninteresting + + // CXXNewExpr + (void)new Types; // expected-error{{expression contains unexpanded parameter pack 'Types'}} + (void)new X(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + (void)new (values) X(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + (void)new X [values]; // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXDeleteExpr + delete values; // expected-error{{expression contains unexpanded parameter pack 'values'}} + delete [] values; // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXPseudoDestructorExpr + T t; + values.~T(); // expected-error{{expression contains unexpanded parameter pack 'values'}} + t.~Types(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + t.Types::~T(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // UnaryTypeTraitExpr + __is_pod(Types); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // BinaryTypeTraitExpr + __is_base_of(Types, T); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + __is_base_of(T, Types); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // UnresolvedLookupExpr + test_unexpanded_exprs(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + test_unexpanded_exprs<Types>(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // DependentScopeDeclRefExpr + Types::test_unexpanded_exprs(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + T::template test_unexpanded_exprs<Types>(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // CXXUnresolvedConstructExpr + Types(5); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // CXXDependentScopeMemberExpr + values.foo(); // expected-error{{expression contains unexpanded parameter pack 'values'}} + t.foo(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // FIXME: There's an evil ambiguity here, because we don't know if + // Types refers to the template type parameter pack in scope or a + // non-pack member. + // t.Types::foo(); + + t.template foo<Types>(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + + // UnresolvedMemberExpr + x.f<Types>(); // expected-error{{expression contains unexpanded parameter pack 'Types'}} + x.f(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // CXXNoexceptExpr + noexcept(values); // expected-error{{expression contains unexpanded parameter pack 'values'}} + + // PackExpansionExpr is uninteresting + // SizeOfPackExpr is uninteresting + + // FIXME: Objective-C expressions will need to go elsewhere +} + +// Test unexpanded parameter packs in partial specializations. +template<typename ...Types> +struct TestUnexpandedDecls<int, Types>; // expected-error{{partial specialization contains unexpanded parameter pack 'Types'}} + +// Test for diagnostics in the presence of multiple unexpanded +// parameter packs. +template<typename T, typename U> struct pair; + +template<typename ...OuterTypes> +struct MemberTemplatePPNames { + template<typename ...InnerTypes> + struct Inner { + typedef pair<OuterTypes, InnerTypes>* types; // expected-error{{declaration type contains unexpanded parameter packs 'OuterTypes' and 'InnerTypes'}} + + template<typename ...VeryInnerTypes> + struct VeryInner { + typedef pair<pair<VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types; // expected-error{{declaration type contains unexpanded parameter packs 'VeryInnerTypes', 'OuterTypes', ...}} + }; + }; +}; + +// Example from working paper +namespace WorkingPaperExample { + template<typename...> struct Tuple {}; + template<typename T1, typename T2> struct Pair {}; + + template<class ... Args1> struct zip { + template<class ... Args2> struct with { + typedef Tuple<Pair<Args1, Args2> ... > type; // expected-error{{pack expansion contains parameter packs 'Args1' and 'Args2' that have different lengths (1 vs. 2)}} + }; + }; + + typedef zip<short, int>::with<unsigned short, unsigned>::type T1; // T1 is Tuple<Pair<short, unsigned short>, Pair<int, unsigned>> + typedef Tuple<Pair<short, unsigned short>, Pair<int, unsigned>> T1; + + typedef zip<short>::with<unsigned short, unsigned>::type T2; // expected-note{{in instantiation of template class}} + + template<class ... Args> void f(Args...); + template<class ... Args> void h(Args...); + + template<class ... Args> + void g(Args ... args) { + f(const_cast<const Args*>(&args)...); // OK: "Args" and "args" are expanded within f + f(5 ...); // expected-error{{pack expansion does not contain any unexpanded parameter packs}} + f(args); // expected-error{{expression contains unexpanded parameter pack 'args'}} + f(h(args ...) + args ...); + } +} diff --git a/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp b/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp index 7352be2d..989ff9f 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp @@ -11,11 +11,33 @@ template<typename T> struct X1t; // expected-error{{template type parameter conf template<typename T> struct X2t; // expected-note{{previous template type parameter declared here}} template<typename ...T> struct X2t; // expected-error{{template type parameter pack conflicts with previous template type parameter}} -template<template<typename ...T> class> struct X0tt; -template<template<typename ...T> class> struct X0tt; +template<template<typename ...T> class> struct X0t_intt; +template<template<typename ...T> class> struct X0t_intt; -template<template<typename ...T> class> struct X1tt; // expected-note{{previous template type parameter pack declared here}} -template<template<typename T> class> struct X1tt; // expected-error{{template type parameter conflicts with previous template type parameter pack}} +template<template<typename ...T> class> struct X1t_intt; // expected-note{{previous template type parameter pack declared here}} +template<template<typename T> class> struct X1t_intt; // expected-error{{template type parameter conflicts with previous template type parameter pack}} -template<template<typename T> class> struct X2tt; // expected-note{{previous template type parameter declared here}} -template<template<typename ...T> class> struct X2tt; // expected-error{{template type parameter pack conflicts with previous template type parameter}} +template<template<typename T> class> struct X2t_intt; // expected-note{{previous template type parameter declared here}} +template<template<typename ...T> class> struct X2t_intt; // expected-error{{template type parameter pack conflicts with previous template type parameter}} + +template<int ...Values> struct X1nt; // expected-note{{previous non-type template parameter pack declared here}} +template<int Values> struct X1nt; // expected-error{{non-type template parameter conflicts with previous non-type template parameter pack}} + +template<template<class T> class> class X1tt; // expected-note{{previous template template parameter declared here}} +template<template<class T> class...> class X1tt; // expected-error{{template template parameter pack conflicts with previous template template parameter}} + +// Check for matching with out-of-line definitions +namespace rdar8859985 { + template<typename ...> struct tuple { }; + template<int ...> struct int_tuple { }; + + template<typename T> + struct X { + template<typename ...Args1, int ...Indices1> + X(tuple<Args1...>, int_tuple<Indices1...>); + }; + + template<typename T> + template<typename ...Args1, int ...Indices1> + X<T>::X(tuple<Args1...>, int_tuple<Indices1...>) {} +} diff --git a/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp b/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp new file mode 100644 index 0000000..3723178 --- /dev/null +++ b/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Various tests related to partial ordering of variadic templates. +template<typename ...Types> struct tuple; + +template<typename Tuple> +struct X1 { + static const unsigned value = 0; +}; + +template<typename Head, typename ...Tail> +struct X1<tuple<Head, Tail...> > { + static const unsigned value = 1; +}; + +template<typename Head, typename ...Tail> +struct X1<tuple<Head, Tail&...> > { + static const unsigned value = 2; +}; + +template<typename Head, typename ...Tail> +struct X1<tuple<Head&, Tail&...> > { + static const unsigned value = 3; +}; + +int check0[X1<tuple<>>::value == 0? 1 : -1]; +int check1[X1<tuple<int>>::value == 2? 1 : -1]; +int check2[X1<tuple<int, int>>::value == 1? 1 : -1]; +int check3[X1<tuple<int, int&>>::value == 2? 1 : -1]; +int check4[X1<tuple<int&, int&>>::value == 3? 1 : -1]; + +// Partial ordering of function templates. +template<typename T1, typename T2, typename ...Rest> +int &f0(T1, T2, Rest...); + +template<typename T1, typename T2> +float &f0(T1, T2); + +void test_f0() { + int &ir1 = f0(1, 2.0, 'a'); + float &fr1 = f0(1, 2.0); +} + +template<typename T1, typename T2, typename ...Rest> +int &f1(T1, T2, Rest...); + +template<typename T1, typename T2> +float &f1(T1, T2, ...); + +void test_f1() { + int &ir1 = f1(1, 2.0, 'a'); +} + +template<typename T1, typename T2, typename ...Rest> +int &f2(T1, T2, Rest...); + +float &f2(...); + +void test_f2() { + int &ir1 = f2(1, 2.0, 'a'); +} diff --git a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp new file mode 100644 index 0000000..46d70b6 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +namespace ParameterPacksWithFunctions { + template<typename ...> struct count; + + template<typename Head, typename ...Tail> + struct count<Head, Tail...> { + static const unsigned value = 1 + count<Tail...>::value; + }; + + template<> + struct count<> { + static const unsigned value = 0; + }; + + template<unsigned> struct unsigned_c { }; + + template<typename ... Types> + unsigned_c<count<Types...>::value> f(); + + void test_f() { + unsigned_c<0> uc0a = f(); // okay, deduced to an empty pack + unsigned_c<0> uc0b = f<>(); + unsigned_c<1> uc1 = f<int>(); + unsigned_c<2> uc2 = f<float, double>(); + } +} diff --git a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp index eb5465c..9ec8f0c 100644 --- a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp @@ -33,4 +33,4 @@ template <typename T> void g(T); template <typename T> void g(T, T); int typeof2[is_same<__typeof__(g<float>), void (int)>::value? 1 : -1]; // \ - // expected-error{{cannot determine the type of an overloaded function}} + // expected-error{{cannot resolve overloaded function from context}} diff --git a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp new file mode 100644 index 0000000..b38cc27 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Metafunction to extract the Nth type from a set of types. +template<unsigned N, typename ...Types> struct get_nth_type; + +template<unsigned N, typename Head, typename ...Tail> +struct get_nth_type<N, Head, Tail...> : get_nth_type<N-1, Tail...> { }; + +template<typename Head, typename ...Tail> +struct get_nth_type<0, Head, Tail...> { + typedef Head type; +}; + +// Placeholder type when get_nth_type fails. +struct no_type {}; + +template<unsigned N> +struct get_nth_type<N> { + typedef no_type type; +}; + +template<typename ...Args> +typename get_nth_type<0, Args...>::type first_arg(Args...); + +template<typename ...Args> +typename get_nth_type<1, Args...>::type second_arg(Args...); + +// Test explicit specification of function template arguments. +void test_explicit_spec_simple() { + int *ip1 = first_arg<int *>(0); + int *ip2 = first_arg<int *, float*>(0, 0); + float *fp1 = first_arg<float *, double*, int*>(0, 0, 0); +} + +// Template argument deduction can extend the sequence of template +// arguments corresponding to a template parameter pack, even when the +// sequence contains explicitly specified template arguments. +void test_explicit_spec_extension(double *dp) { + int *ip1 = first_arg<int *>(0, 0); + int *ip2 = first_arg<int *, float*>(0, 0, 0, 0); + float *fp1 = first_arg<float *, double*, int*>(0, 0, 0); + int *i1 = second_arg<float *>(0, (int*)0, 0); + double *dp1 = first_arg<>(dp); +} + +template<typename ...Types> +struct tuple { }; + +template<typename ...Types> +void accept_tuple(tuple<Types...>); + +void test_explicit_spec_extension_targs(tuple<int, float, double> t3) { + accept_tuple(t3); + accept_tuple<int, float, double>(t3); + accept_tuple<int>(t3); + accept_tuple<int, float>(t3); +} + +template<typename R, typename ...ParmTypes> +void accept_function_ptr(R(*)(ParmTypes...)); + +void test_explicit_spec_extension_funcparms(int (*f3)(int, float, double)) { + accept_function_ptr(f3); + accept_function_ptr<int>(f3); + accept_function_ptr<int, int>(f3); + accept_function_ptr<int, int, float>(f3); + accept_function_ptr<int, int, float, double>(f3); +} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp new file mode 100644 index 0000000..8933b63 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp @@ -0,0 +1,88 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Metafunction to extract the Nth type from a set of types. +template<unsigned N, typename ...Types> struct get_nth_type; + +template<unsigned N, typename Head, typename ...Tail> +struct get_nth_type<N, Head, Tail...> : get_nth_type<N-1, Tail...> { }; + +template<typename Head, typename ...Tail> +struct get_nth_type<0, Head, Tail...> { + typedef Head type; +}; + +// Placeholder type when get_nth_type fails. +struct no_type {}; + +template<unsigned N> +struct get_nth_type<N> { + typedef no_type type; +}; + +template<typename T, typename U> struct pair { }; +template<typename T, typename U> pair<T, U> make_pair(T, U); + +// For a function parameter pack that occurs at the end of the +// parameter-declaration-list, the type A of each remaining argument +// of the call is compared with the type P of the declarator-id of the +// function parameter pack. +template<typename ...Args> +typename get_nth_type<0, Args...>::type first_arg(Args...); + +template<typename ...Args> +typename get_nth_type<1, Args...>::type second_arg(Args...); + +void test_simple_deduction(int *ip, float *fp, double *dp) { + int *ip1 = first_arg(ip); + int *ip2 = first_arg(ip, fp); + int *ip3 = first_arg(ip, fp, dp); + no_type nt1 = first_arg(); +} + +template<typename ...Args> +typename get_nth_type<0, Args...>::type first_arg_ref(Args&...); + +template<typename ...Args> +typename get_nth_type<1, Args...>::type second_arg_ref(Args&...); + +void test_simple_ref_deduction(int *ip, float *fp, double *dp) { + int *ip1 = first_arg_ref(ip); + int *ip2 = first_arg_ref(ip, fp); + int *ip3 = first_arg_ref(ip, fp, dp); + no_type nt1 = first_arg_ref(); +} + + +template<typename ...Args1, typename ...Args2> +typename get_nth_type<0, Args1...>::type first_arg_pair(pair<Args1, Args2>...); // expected-note{{candidate template ignored: failed template argument deduction}} + +template<typename ...Args1, typename ...Args2> +typename get_nth_type<1, Args1...>::type second_arg_pair(pair<Args1, Args2>...); + +void test_pair_deduction(int *ip, float *fp, double *dp) { + int *ip1 = first_arg_pair(make_pair(ip, 17)); + int *ip2 = first_arg_pair(make_pair(ip, 17), make_pair(fp, 17)); + int *ip3 = first_arg_pair(make_pair(ip, 17), make_pair(fp, 17), + make_pair(dp, 17)); + float *fp1 = second_arg_pair(make_pair(ip, 17), make_pair(fp, 17)); + float *fp2 = second_arg_pair(make_pair(ip, 17), make_pair(fp, 17), + make_pair(dp, 17)); + no_type nt1 = first_arg_pair(); + no_type nt2 = second_arg_pair(); + no_type nt3 = second_arg_pair(make_pair(ip, 17)); + + + first_arg_pair(make_pair(ip, 17), 16); // expected-error{{no matching function for call to 'first_arg_pair'}} +} + +// For a function parameter pack that does not occur at the end of the +// parameter-declaration-list, the type of the parameter pack is a +// non-deduced context. +template<typename ...Types> struct tuple { }; + +template<typename ...Types> +void pack_not_at_end(tuple<Types...>, Types... values, int); + +void test_pack_not_at_end(tuple<int*, double*> t2) { + pack_not_at_end(t2, 0, 0, 0); +} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp new file mode 100644 index 0000000..f18a74a --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + + +// If P is an rvalue reference to a cv-unqualified template parameter +// and the argument is an lvalue, the type "lvalue reference to A" is +// used in place of A for type deduction. +template<typename T> struct X { }; + +template<typename T> X<T> f0(T&&); + +struct Y { }; + +template<typename T> T prvalue(); +template<typename T> T&& xvalue(); +template<typename T> T& lvalue(); + +void test_f0() { + X<int> xi0 = f0(prvalue<int>()); + X<int> xi1 = f0(xvalue<int>()); + X<int&> xi2 = f0(lvalue<int>()); + X<Y> xy0 = f0(prvalue<Y>()); + X<Y> xy1 = f0(xvalue<Y>()); + X<Y&> xy2 = f0(lvalue<Y>()); +} + +template<typename T> X<T> f1(const T&&); // expected-note{{candidate function [with T = int] not viable: no known conversion from 'int' to 'const int &&' for 1st argument}} \ +// expected-note{{candidate function [with T = Y] not viable: no known conversion from 'Y' to 'const Y &&' for 1st argument}} + +void test_f1() { + X<int> xi0 = f1(prvalue<int>()); + X<int> xi1 = f1(xvalue<int>()); + f1(lvalue<int>()); // expected-error{{no matching function for call to 'f1'}} + X<Y> xy0 = f1(prvalue<Y>()); + X<Y> xy1 = f1(xvalue<Y>()); + f1(lvalue<Y>()); // expected-error{{no matching function for call to 'f1'}} +} + +namespace std_example { + template <class T> int f(T&&); + template <class T> int g(const T&&); // expected-note{{candidate function [with T = int] not viable: no known conversion from 'int' to 'const int &&' for 1st argument}} + + int i; + int n1 = f(i); + int n2 = f(0); + int n3 = g(i); // expected-error{{no matching function for call to 'g'}} +} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp index 19962c5..3c22cf3 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp @@ -101,3 +101,25 @@ void test_f4(D d, E e, F f, G g) { C<int, 1> *ci3c = f4c(&g); int *ip1 = f4c(&f); } + +// PR8462 +namespace N { + struct T0; + struct T1; + + template<typename X, typename Y> struct B {}; + + struct J : B<T0,T0> {}; + struct K : B<T1,T1> {}; + + struct D : J, K {}; + + template<typename X, typename Y> void F(B<Y,X>); + + void test() + { + D d; + N::F<T0>(d); // Fails + N::F<T1>(d); // OK + } +} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp index 99ade4b..01155e1 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp @@ -13,10 +13,35 @@ struct identity { }; template <class T> - T* f2(int, typename identity<T>::type = 0); // expected-note{{candidate}} + T* f2(int, typename identity<T>::type = 0); template <class T, class U> - T& f2(U, typename identity<T>::type = 0); // expected-note{{candidate}} + T& f2(U, typename identity<T>::type = 0); void g2() { - f2<int>(1); // expected-error{{ambiguous}} + int* ip = f2<int>(1); +} + +template<class T, class U> struct A { }; + +template<class T, class U> inline int *f3( U, A<U,T>* p = 0 ); // #1 expected-note{{candidate function [with T = int, U = int]}} +template< class U> inline float *f3( U, A<U,U>* p = 0 ); // #2 expected-note{{candidate function [with U = int]}} + +void g3() { + float *fp = f3<int>( 42, (A<int,int>*)0 ); // Ok, picks #2. + f3<int>( 42 ); // expected-error{{call to 'f3' is ambiguous}} + +} + +namespace PR9006 { + struct X { + template <class Get> + int &f(char const* name, Get fget, char const* docstr = 0); + + template <class Get, class Set> + float &f(char const* name, Get fget, Set fset, char const* docstr = 0); + }; + + void test(X x) { + int &ir = x.f("blah", 0, "blah"); + } } diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p12.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p12.cpp new file mode 100644 index 0000000..1168100 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p12.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Note: Partial ordering of function templates containing template +// parameter packs is independent of the number of deduced arguments +// for those template parameter packs. +template<class ...> struct Tuple { }; +template<class ... Types> int &g(Tuple<Types ...>); // #1 +template<class T1, class ... Types> float &g(Tuple<T1, Types ...>); // #2 +template<class T1, class ... Types> double &g(Tuple<T1, Types& ...>); // #3 + +void test_g() { + int &ir1 = g(Tuple<>()); + float &fr1 = g(Tuple<int, float>()); + double &dr1 = g(Tuple<int, float&>()); + double &dr2 = g(Tuple<int>()); +} + +template<class ... Types> int &h(int (*)(Types ...)); // #1 +template<class T1, class ... Types> float &h(int (*)(T1, Types ...)); // #2 +template<class T1, class ... Types> double &h(int (*)(T1, Types& ...)); // #3 + +void test_h() { + int &ir1 = h((int(*)())0); + float &fr1 = h((int(*)(int, float))0); + double &dr1 = h((int(*)(int, float&))0); + double &dr2 = h((int(*)(int))0); +} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp new file mode 100644 index 0000000..46ea4db --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template<typename T> int &f0(T&); +template<typename T> float &f0(T&&); + +// Core issue 1164 +void test_f0(int i) { + int &ir0 = f0(i); + float &fr0 = f0(5); +} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp new file mode 100644 index 0000000..9d342c8 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +template<typename T> void f(T&&); +template<> void f(int&) { } +void (*fp)(int&) = &f; diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p2-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p2-0x.cpp new file mode 100644 index 0000000..198f11f --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p2-0x.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// If type deduction cannot be done for any P/A pair, or if for any +// pair the deduction leads to more than one possible set of deduced +// values, or if different pairs yield different deduced values, or if +// any template argument remains neither deduced nor explicitly +// specified, template argument deduction fails. + +template<typename ...> struct tuple; + +template<typename T, typename U> +struct same_tuple { + static const bool value = false; +}; + +template<typename ...Types1> +struct same_tuple<tuple<Types1...>, tuple<Types1...> > { + static const bool value = true; +}; + +int same_tuple_check1[same_tuple<tuple<int, float>, tuple<int, double>>::value? -1 : 1]; +int same_tuple_check2[same_tuple<tuple<float, double>, tuple<float, double>>::value? 1 : -1]; + diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p21.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p21.cpp new file mode 100644 index 0000000..247b981 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p21.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Note: Template argument deduction involving parameter packs +// (14.5.3) can deduce zero or more arguments for each parameter pack. + +template<class> struct X { + static const unsigned value = 0; +}; + +template<class R, class ... ArgTypes> struct X<R(int, ArgTypes ...)> { + static const unsigned value = 1; +}; + +template<class ... Types> struct Y { + static const unsigned value = 0; +}; + +template<class T, class ... Types> struct Y<T, Types& ...> { + static const unsigned value = 1; +}; + +template<class ... Types> int f(void (*)(Types ...)); +void g(int, float); + +int check0[X<int>::value == 0? 1 : -1]; // uses primary template +int check1[X<int(int, float, double)>::value == 1? 1 : -1]; // uses partial specialization +int check2[X<int(float, int)>::value == 0? 1 : -1]; // uses primary template +int check3[Y<>::value == 0? 1 : -1]; // uses primary template +int check4[Y<int&, float&, double&>::value == 1? 1 : -1]; // uses partial specialization +int check5[Y<int, float, double>::value == 0? 1 : -1]; // uses primary template +int fv = f(g); // okay diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p22.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p22.cpp new file mode 100644 index 0000000..4326a69 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p22.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// If the original function parameter associated with A is a function +// parameter pack and the function parameter associated with P is not +// a function parameter pack, then template argument deduction fails. +template<class ... Args> int& f(Args ... args); +template<class T1, class ... Args> float& f(T1 a1, Args ... args); +template<class T1, class T2> double& f(T1 a1, T2 a2); + +void test_f() { + int &ir1 = f(); + float &fr1 = f(1, 2, 3); + double &dr1 = f(1, 2); +} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp new file mode 100644 index 0000000..cf68a01 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// FIXME: More bullets to go! + +template<typename T, typename U> +struct has_nondeduced_pack_test { + static const bool value = false; +}; + +template<typename R, typename FirstType, typename ...Types> +struct has_nondeduced_pack_test<R(FirstType, Types..., int), + R(FirstType, Types...)> { + static const bool value = true; +}; + +// - A function parameter pack that does not occur at the end of the +// parameter-declaration-clause. +int check_nondeduced_pack_test0[ + has_nondeduced_pack_test<int(float, double, int), + int(float, double)>::value? 1 : -1]; + + diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp new file mode 100644 index 0000000..a9173fd --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Deductions specific to C++0x. + +template<typename T> +struct member_pointer_kind { + static const unsigned value = 0; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...)> { + static const unsigned value = 1; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) &> { + static const unsigned value = 2; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) &&> { + static const unsigned value = 3; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) const> { + static const unsigned value = 4; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) const &> { + static const unsigned value = 5; +}; + +template<class C, typename R, typename ...Args> +struct member_pointer_kind<R (C::*)(Args...) const &&> { + static const unsigned value = 6; +}; + +struct X { }; + +static_assert(member_pointer_kind<int (X::*)(int)>::value == 1, ""); +static_assert(member_pointer_kind<int (X::*)(int) &>::value == 2, ""); +static_assert(member_pointer_kind<int (X::*)(int) &&>::value == 3, ""); +static_assert(member_pointer_kind<int (X::*)(int) const>::value == 4, ""); +static_assert(member_pointer_kind<int (X::*)(int) const&>::value == 5, ""); +static_assert(member_pointer_kind<int (X::*)(int) const&&>::value == 6, ""); diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp new file mode 100644 index 0000000..5087224 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +template<typename ...Types> struct tuple; +template<unsigned> struct unsigned_c; + +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +namespace PackExpansionNotAtEnd { + template<typename T, typename U> + struct tuple_same_with_int { + static const bool value = false; + }; + + template<typename ...Types> + struct tuple_same_with_int<tuple<Types...>, tuple<Types..., int>> { + static const bool value = true; + }; + + int tuple_same_with_int_1[tuple_same_with_int<tuple<int, float, double>, + tuple<int, float, double, int> + >::value? 1 : -1]; + + template<typename ... Types> struct UselessPartialSpec; + + template<typename ... Types, // expected-note{{non-deducible template parameter 'Types'}} + typename Tail> // expected-note{{non-deducible template parameter 'Tail'}} + struct UselessPartialSpec<Types..., Tail>; // expected-warning{{class template partial specialization contains template parameters that can not be deduced; this partial specialization will never be used}} +} + +namespace DeduceNonTypeTemplateArgsInArray { + template<typename ...ArrayTypes> + struct split_arrays; + + template<typename ...ElementTypes, unsigned ...Bounds> + struct split_arrays<ElementTypes[Bounds]...> { + typedef tuple<ElementTypes...> element_types; + + // FIXME: Would like to have unsigned_tuple<Bounds...> here. + typedef tuple<unsigned_c<Bounds>...> bounds_types; + }; + + int check1[is_same<split_arrays<int[1], float[2], double[3]>::element_types, + tuple<int, float, double>>::value? 1 : -1]; + int check2[is_same<split_arrays<int[1], float[2], double[3]>::bounds_types, + tuple<unsigned_c<1>, unsigned_c<2>, unsigned_c<3>> + >::value? 1 : -1]; +} diff --git a/test/CXX/temp/temp.param/p1.cpp b/test/CXX/temp/temp.param/p1.cpp index 676bffe..e9a9789 100644 --- a/test/CXX/temp/temp.param/p1.cpp +++ b/test/CXX/temp/temp.param/p1.cpp @@ -1,4 +1,12 @@ // Suppress 'no run line' failure. -// RUN: echo ok +// RUN: %clang_cc1 -fsyntax-only -verify %s -// Paragraph 1 is descriptive, and therefore requires no tests. +template<template<> class C> class D; // expected-error{{template template parameter must have its own template parameters}} + + +struct A {}; +template<class M, + class T = A, // expected-note{{previous default template argument defined here}} + class C> // expected-error{{template parameter missing a default argument}} +class X0 {}; // expected-note{{template is declared here}} +X0<int> x0; // expected-error{{too few template arguments for class template 'X0'}} diff --git a/test/CXX/temp/temp.param/p11-0x.cpp b/test/CXX/temp/temp.param/p11-0x.cpp new file mode 100644 index 0000000..0bf4341 --- /dev/null +++ b/test/CXX/temp/temp.param/p11-0x.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// If a template-parameter of a class template has a default +// template-argument, each subsequent template-parameter shall either +// have a default template-argument supplied or be a template +// parameter pack. +template<typename> struct vector; + +template<typename T = int, typename ...Types> struct X2t; +template<int V = 0, int ...Values> struct X2nt; +template<template<class> class M = vector, template<class> class... Metas> + struct X2tt; + +// If a template-parameter of a primary class template is a template +// parameter pack, it shall be the last template-parameter . +template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}} + int After> +struct X0t; + +template<int ...Values, // expected-error{{template parameter pack must be the last template parameter}} + int After> +struct X0nt; + +template<template<typename> class ...Templates, // expected-error{{template parameter pack must be the last template parameter}} + int After> +struct X0tt; + +// [ Note: These are not requirements for function templates or class +// template partial specializations because template arguments can be +// deduced (14.8.2). -- end note] +template<typename... Types> struct X1t; +template<typename ...Types, typename T> struct X1t<T, Types...> { }; + +template<int... Values> struct X1nt; +template<int ...Values, int V> struct X1nt<V, Values...> { }; + +template<template<int> class... Meta> struct X1tt; +template<template<int> class... Meta, template<int> class M> + struct X1tt<M, Meta...> { }; + +template<typename ...Types, typename T> +void f1t(X1t<T, Types...>); + +template<int ...Values, int V> +void f1nt(X1nt<V, Values...>); + +template<template<int> class... Meta, template<int> class M> +void f1tt(X1tt<M, Meta...>); + +namespace DefaultTemplateArgsInFunction { + template<typename T = int, typename U> T &f0(U) { T *x = 0; return *x; } + + void test_f0() { + int &ir0 = f0(3.14159); + int &ir1 = f0<int>(3.14159); + float &fr0 = f0<float>(3.14159); + } + + template<> int &f0(int*); + template int &f0(double&); +} diff --git a/test/CXX/temp/temp.param/p15-cxx0x.cpp b/test/CXX/temp/temp.param/p15-cxx0x.cpp index 0ce6699..f4be5b9 100644 --- a/test/CXX/temp/temp.param/p15-cxx0x.cpp +++ b/test/CXX/temp/temp.param/p15-cxx0x.cpp @@ -20,3 +20,5 @@ void f(const X<int> x) { X<X<int>> *x1; } +template<typename T = void> struct X1 { }; +X1<X1<>> x1a; diff --git a/test/CXX/temp/temp.param/p9-0x.cpp b/test/CXX/temp/temp.param/p9-0x.cpp new file mode 100644 index 0000000..17eca7f --- /dev/null +++ b/test/CXX/temp/temp.param/p9-0x.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// A default template-argument may be specified for any kind of +// template-parameter that is not a template parameter pack. +template<typename ...Types = int> // expected-error{{template parameter pack cannot have a default argument}} +struct X0; + +template<int ...Values = 0> // expected-error{{template parameter pack cannot have a default argument}} +struct X1; + +template<typename T> struct vector; + +template<template<class> class ...Templates = vector> // expected-error{{template parameter pack cannot have a default argument}} +struct X2; + +struct X3 { + template<typename T = int> // expected-error{{default template argument not permitted on a friend template}} + friend void f0(X3); + + template<typename T = int> + friend void f1(X3) { + } +}; + +namespace PR8748 { + // Testcase 1 + struct A0 { template<typename U> struct B; }; + template<typename U = int> struct A0::B { }; + + // Testcase 2 + template<typename T> struct A1 { template<typename U> struct B; }; + template<typename T> template<typename U = int> struct A1<T>::B { }; // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + + // Testcase 3 + template<typename T> + struct X2 { + void f0(); + template<typename U> void f1(); + }; + + template<typename T = int> void X2<T>::f0() { } // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + template<typename T> template<typename U = int> void X2<T>::f1() { } // expected-error{{cannot add a default template argument to the definition of a member of a class template}} + + namespace Inner { + template<typename T> struct X3; + template<typename T> void f2(); + } + + // Okay; not class members. + template<typename T = int> struct Inner::X3 { }; + template<typename T = int> void Inner::f2() {} +} diff --git a/test/CXX/temp/temp.param/p9.cpp b/test/CXX/temp/temp.param/p9.cpp index 625477c..62af522 100644 --- a/test/CXX/temp/temp.param/p9.cpp +++ b/test/CXX/temp/temp.param/p9.cpp @@ -2,9 +2,9 @@ // A default template-argument shall not be specified in a function // template declaration or a function template definition -template<typename T = int> // expected-error{{cannot have a default argument}} +template<typename T = int> // expected-warning{{default template arguments for a function template are a C++0x extension}} void foo0(T); -template<typename T = int> // expected-error{{cannot have a default argument}} +template<typename T = int> // expected-warning{{default template arguments for a function template are a C++0x extension}} void foo1(T) { } // [...] nor in the template-parameter-list of the definition of a diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp new file mode 100644 index 0000000..ed600e4 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp @@ -0,0 +1,239 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +// This test creates cases where implicit instantiations of various entities +// would cause a diagnostic, but provides expliict specializations for those +// entities that avoid the diagnostic. The specializations are alternately +// declarations and definitions, and the intent of this test is to verify +// that we allow specializations only in the appropriate namespaces (and +// nowhere else). +struct NonDefaultConstructible { + NonDefaultConstructible(int); +}; + + +// C++ [temp.expl.spec]p1: +// An explicit specialization of any of the following: + +// -- function template +namespace N0 { + template<typename T> void f0(T) { + T t; + } + + template<> void f0(NonDefaultConstructible) { } + + void test_f0(NonDefaultConstructible NDC) { + f0(NDC); + } + + template<> void f0(int); + template<> void f0(long); +} + +template<> void N0::f0(int) { } // okay + +namespace N1 { + template<> void N0::f0(long) { } // expected-error{{not in a namespace enclosing}} +} + +template<> void N0::f0(double) { } + +struct X1 { + template<typename T> void f(T); + + template<> void f(int); // expected-error{{in class scope}} +}; + +// -- class template +namespace N0 { + +template<typename T> +struct X0 { // expected-note {{here}} + static T member; + + void f1(T t) { + t = 17; + } + + struct Inner : public T { }; // expected-note 2{{here}} + + template<typename U> + struct InnerTemplate : public T { }; // expected-note 1{{explicitly specialized}} \ + // expected-error{{base specifier}} + + template<typename U> + void ft1(T t, U u); +}; + +} + +template<typename T> +template<typename U> +void N0::X0<T>::ft1(T t, U u) { + t = u; +} + +template<typename T> T N0::X0<T>::member; + +template<> struct N0::X0<void> { }; +N0::X0<void> test_X0; + +namespace N1 { + template<> struct N0::X0<const void> { }; // expected-error{{class template specialization of 'X0' must originally be declared in namespace 'N0'}} +} + +namespace N0 { + template<> struct X0<volatile void>; +} + +template<> struct N0::X0<volatile void> { + void f1(void *); +}; + +// -- member function of a class template +template<> void N0::X0<void*>::f1(void *) { } + +void test_spec(N0::X0<void*> xvp, void *vp) { + xvp.f1(vp); +} + +namespace N0 { + template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}} + + template<> void X0<const volatile void*>::f1(const volatile void*); +} + +void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) { + x0.f1(cvp); // okay: we've explicitly specialized +} + +// -- static data member of a class template +namespace N0 { + // This actually tests p15; the following is a declaration, not a definition. + template<> + NonDefaultConstructible X0<NonDefaultConstructible>::member; + + template<> long X0<long>::member = 17; + + template<> float X0<float>::member; + + template<> double X0<double>::member; +} + +NonDefaultConstructible &get_static_member() { + return N0::X0<NonDefaultConstructible>::member; +} + +template<> int N0::X0<int>::member; + +template<> float N0::X0<float>::member = 3.14f; + +namespace N1 { + template<> double N0::X0<double>::member = 3.14; // expected-error{{not in a namespace enclosing}} +} + +// -- member class of a class template +namespace N0 { + + template<> + struct X0<void*>::Inner { }; + + template<> + struct X0<int>::Inner { }; + + template<> + struct X0<unsigned>::Inner; + + template<> + struct X0<float>::Inner; + + template<> + struct X0<double>::Inner; // expected-note{{forward declaration}} +} + +template<> +struct N0::X0<long>::Inner { }; + +template<> +struct N0::X0<float>::Inner { }; + +namespace N1 { + template<> + struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}} + + template<> + struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}} +}; + +N0::X0<void*>::Inner inner0; +N0::X0<int>::Inner inner1; +N0::X0<long>::Inner inner2; +N0::X0<float>::Inner inner3; +N0::X0<double>::Inner inner4; // expected-error{{incomplete}} + +// -- member class template of a class template +namespace N0 { + template<> + template<> + struct X0<void*>::InnerTemplate<int> { }; + + template<> template<> + struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}} + + template<> template<> + struct X0<int>::InnerTemplate<long>; + + template<> template<> + struct X0<int>::InnerTemplate<double>; +} + +template<> template<> +struct N0::X0<int>::InnerTemplate<long> { }; // okay + +template<> template<> +struct N0::X0<int>::InnerTemplate<float> { }; + +namespace N1 { + template<> template<> + struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}} +} + +N0::X0<void*>::InnerTemplate<int> inner_template0; +N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}} +N0::X0<int>::InnerTemplate<long> inner_template2; +N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}} + +// -- member function template of a class template +namespace N0 { + template<> + template<> + void X0<void*>::ft1(void*, const void*) { } + + template<> template<> + void X0<void*>::ft1(void *, int); + + template<> template<> + void X0<void*>::ft1(void *, unsigned); + + template<> template<> + void X0<void*>::ft1(void *, long); +} + +template<> template<> +void N0::X0<void*>::ft1(void *, unsigned) { } // okay + +template<> template<> +void N0::X0<void*>::ft1(void *, float) { } + +namespace N1 { + template<> template<> + void N0::X0<void*>::ft1(void *, long) { } // expected-error{{enclosing}} +} + + +void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp, + int i, unsigned u) { + xvp.ft1(vp, cvp); + xvp.ft1(vp, i); + xvp.ft1(vp, u); +} diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp index 654f5ab..1032a87 100644 --- a/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp @@ -36,7 +36,7 @@ namespace N1 { template<> void N0::f0(long) { } // expected-error{{not in a namespace enclosing}} } -template<> void N0::f0(double) { } // expected-error{{originally be declared}} +template<> void N0::f0(double) { } // expected-warning{{originally be declared}} struct X1 { template<typename T> void f(T); @@ -75,7 +75,7 @@ void N0::X0<T>::ft1(T t, U u) { template<typename T> T N0::X0<T>::member; -template<> struct N0::X0<void> { }; // expected-error{{originally}} +template<> struct N0::X0<void> { }; // expected-warning{{originally}} N0::X0<void> test_X0; namespace N1 { @@ -91,7 +91,7 @@ template<> struct N0::X0<volatile void> { }; // -- member function of a class template -template<> void N0::X0<void*>::f1(void *) { } // expected-error{{member function specialization}} +template<> void N0::X0<void*>::f1(void *) { } // expected-warning{{member function specialization}} void test_spec(N0::X0<void*> xvp, void *vp) { xvp.f1(vp); @@ -124,7 +124,7 @@ NonDefaultConstructible &get_static_member() { return N0::X0<NonDefaultConstructible>::member; } -template<> int N0::X0<int>::member; // expected-error{{originally}} +template<> int N0::X0<int>::member; // expected-warning{{originally}} template<> float N0::X0<float>::member = 3.14f; @@ -152,7 +152,7 @@ namespace N0 { } template<> -struct N0::X0<long>::Inner { }; // expected-error{{originally}} +struct N0::X0<long>::Inner { }; // expected-warning{{originally}} template<> struct N0::X0<float>::Inner { }; @@ -191,7 +191,7 @@ template<> template<> struct N0::X0<int>::InnerTemplate<long> { }; // okay template<> template<> -struct N0::X0<int>::InnerTemplate<float> { }; // expected-error{{class template specialization}} +struct N0::X0<int>::InnerTemplate<float> { }; // expected-warning{{class template specialization}} namespace N1 { template<> template<> @@ -223,7 +223,7 @@ template<> template<> void N0::X0<void*>::ft1(void *, unsigned) { } // okay template<> template<> -void N0::X0<void*>::ft1(void *, float) { } // expected-error{{function template specialization}} +void N0::X0<void*>::ft1(void *, float) { } // expected-warning{{function template specialization}} namespace N1 { template<> template<> diff --git a/test/CXX/temp/temp.spec/temp.explicit/p12.cpp b/test/CXX/temp/temp.spec/temp.explicit/p12.cpp index 912b8e1..c756486 100644 --- a/test/CXX/temp/temp.spec/temp.explicit/p12.cpp +++ b/test/CXX/temp/temp.spec/temp.explicit/p12.cpp @@ -2,5 +2,5 @@ char* p = 0; template<class T> T g(T x = &p) { return x; } -template int g<int>(int); // OK even though &p isn’t an int. +template int g<int>(int); // OK even though &p isn't an int. |