diff options
author | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
---|---|---|
committer | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
commit | 222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch) | |
tree | 7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/test/CXX | |
parent | 3d206f03985b50beacae843d880bccdc91a9f424 (diff) |
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/test/CXX')
511 files changed, 26163 insertions, 0 deletions
diff --git a/clang/test/CXX/basic/basic.def.odr/p1-var.cpp b/clang/test/CXX/basic/basic.def.odr/p1-var.cpp new file mode 100644 index 0000000..892f546 --- /dev/null +++ b/clang/test/CXX/basic/basic.def.odr/p1-var.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++ [basic.def.odr]p1: +// No translation unit shall contain more than one definition of any +// variable, [...]. + +// Bad: in C++, these are both definitions. None of that C99 tentative stuff. +int i; // expected-note {{previous}} +int i; // expected-error {{redefinition}} + +// OK: decl + def +extern int j; +int j; + +// OK: def + decl +int k; +extern int k; + +// Bad. The important thing here is that we don't emit the diagnostic twice. +int l = 1; // expected-note {{previous}} +int l = 2; // expected-error {{redefinition}} diff --git a/clang/test/CXX/basic/basic.def.odr/p2-typeid.cpp b/clang/test/CXX/basic/basic.def.odr/p2-typeid.cpp new file mode 100644 index 0000000..55debe3 --- /dev/null +++ b/clang/test/CXX/basic/basic.def.odr/p2-typeid.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++ [basic.def.odr]p2: +// An expression is potentially evaluated unless it [...] is the +// operand of the typeid operator and the expression does not +// designate an lvalue of polymorphic class type. + +// FIXME: This should really include <typeinfo>, but we don't have that yet. +namespace std { + class type_info; +} + +struct Poly { + virtual ~Poly(); +}; + +struct NonPoly { }; + +template<typename T, typename Result = T> +struct X { + Result f(T t) { return t + t; } // expected-error{{invalid operands}} + + void g(T t) { + (void)typeid(f(t)); // expected-note{{here}} + } +}; + +void test(X<Poly> xp, X<Poly, Poly&> xpr, X<NonPoly> xnp, X<NonPoly, NonPoly&> xnpr) { + // These are okay (although GCC and EDG get them wrong). + xp.g(Poly()); + xnp.g(NonPoly()); + xnpr.g(NonPoly()); + + // Triggers an error (as it should); + xpr.g(Poly()); // expected-note{{instantiation of member function}} +} diff --git a/clang/test/CXX/basic/basic.link/p9.cpp b/clang/test/CXX/basic/basic.link/p9.cpp new file mode 100644 index 0000000..680c93d --- /dev/null +++ b/clang/test/CXX/basic/basic.link/p9.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// FIXME: This test is woefully incomplete. +namespace N { } // expected-note{{here}} + +// First bullet: two names with external linkage that refer to +// different kinds of entities. +void f() { + int N(); // expected-error{{redefinition}} expected-warning{{interpreted as a function declaration}} expected-note {{replace parentheses with an initializer}} +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp new file mode 100644 index 0000000..f650ad5 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace N1 { + struct X { }; + int& f(void*); +} + +namespace N2 { + template<typename T> struct Y { }; +} + +namespace N3 { + void test() { + int &ir = f((N2::Y<N1::X>*)0); + } +} + +int g(void *); +long g(N1::X); + +namespace N1 { + void h(int (*)(void *)); +} + +void test() { + h((&g)); +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp new file mode 100644 index 0000000..f5ad68b --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace N { + struct X { }; + + X operator+(X, X); + + void f(X); + void g(X); // expected-note{{candidate function}} + + void test_multiadd(X x) { + (void)(x + x); + } +} + +namespace M { + struct Y : N::X { }; +} + +void f(); // expected-note 2 {{'f' declared here}} + +void test_operator_adl(N::X x, M::Y y) { + (void)(x + x); + (void)(y + y); +} + +void test_func_adl(N::X x, M::Y y) { + f(x); + f(y); + (f)(x); // expected-error{{too many arguments to function call}} + ::f(x); // expected-error{{too many arguments to function call}} +} + +namespace N { + void test_multiadd2(X x) { + (void)(x + x); + } +} + + +void test_func_adl_only(N::X x) { + g(x); +} + +namespace M { + int g(N::X); // expected-note{{candidate function}} + + void test(N::X x) { + g(x); // expected-error{{call to 'g' is ambiguous}} + int i = (g)(x); + + int g(N::X); + g(x); // okay; calls locally-declared function, no ADL + } +} + + +void test_operator_name_adl(N::X x) { + (void)operator+(x, x); +} + +struct Z { }; +int& f(Z); + +namespace O { + char &f(); + void test_global_scope_adl(Z z) { + { + int& ir = f(z); + } + } +} + +extern "C" { + struct L { }; +} + +void h(L); // expected-note{{candidate function}} + +namespace P { + void h(L); // expected-note{{candidate function}} + void test_transparent_context_adl(L l) { + { + h(l); // expected-error {{call to 'h' is ambiguous}} + } + } +} + +namespace test5 { + namespace NS { + struct A; + void foo(void (*)(A&)); + } + void bar(NS::A& a); + + void test() { + foo(&bar); + } +} + +// PR6762: __builtin_va_list should be invisible to ADL on all platforms. +void test6_function(__builtin_va_list &argv); +namespace test6 { + void test6_function(__builtin_va_list &argv); + + void test() { + __builtin_va_list args; + test6_function(args); + } +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p3.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p3.cpp new file mode 100644 index 0000000..c4c2c8d --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p3.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// FIXME: embellish + +namespace test0 { + namespace A { + class Foo { + }; + + void foo(const Foo &foo); + } + + class Test { + enum E { foo = 0 }; + + void test() { + foo(A::Foo()); // expected-error {{not a function}} + } + }; +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp new file mode 100644 index 0000000..32dd75a --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace A { + class A { + friend void func(A); + friend A operator+(A,A); + }; +} + +namespace B { + class B { + static void func(B); + }; + B operator+(B,B); +} + +namespace D { + class D {}; +} + +namespace C { + class C {}; // expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'B::B' to 'const C::C &' for 1st argument}} + void func(C); // expected-note {{'C::func' declared here}} \ + // expected-note {{passing argument to parameter here}} + C operator+(C,C); + D::D operator+(D::D,D::D); +} + +namespace D { + using namespace C; +} + +namespace Test { + void test() { + func(A::A()); + // FIXME: namespace-aware typo correction causes an extra, misleading + // message in this case; some form of backtracking, diagnostic message + // delaying, or argument checking before emitting diagnostics is needed to + // avoid accepting and printing out a typo correction that proves to be + // incorrect once argument-dependent lookup resolution has occurred. + func(B::B()); // expected-error {{use of undeclared identifier 'func'; did you mean 'C::func'?}} \ + // expected-error {{no viable conversion from 'B::B' to 'C::C'}} + func(C::C()); + A::A() + A::A(); + B::B() + B::B(); + C::C() + C::C(); + D::D() + D::D(); // expected-error {{invalid operands to binary expression ('D::D' and 'D::D')}} + } +} + +// PR6716 +namespace test1 { + template <class T> class A { + template <class U> friend void foo(A &, U); // expected-note {{not viable: 1st argument ('const A<int>') would lose const qualifier}} + + public: + A(); + }; + + void test() { + const A<int> a; + foo(a, 10); // expected-error {{no matching function for call to 'foo'}} + } +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp new file mode 100644 index 0000000..c207283 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-show-option -verify %s + +// C++98 [basic.lookup.classref]p1: +// In a class member access expression (5.2.5), if the . or -> token is +// immediately followed by an identifier followed by a <, the identifier must +// be looked up to determine whether the < is the beginning of a template +// argument list (14.2) or a less-than operator. The identifier is first +// looked up in the class of the object expression. If the identifier is not +// found, it is then looked up in the context of the entire postfix-expression +// and shall name a class or function template. If the lookup in the class of +// the object expression finds a template, the name is also looked up in the +// context of the entire postfix-expression and +// -- if the name is not found, the name found in the class of the object +// expression is used, otherwise +// -- if the name is found in the context of the entire postfix-expression +// and does not name a class template, the name found in the class of the +// object expression is used, otherwise +// -- if the name found is a class template, it must refer to the same +// entity as the one found in the class of the object expression, +// otherwise the program is ill-formed. + +// From PR 7247 +template<typename T> +struct set{}; // expected-note{{lookup from the current scope refers here}} +struct Value { + template<typename T> + void set(T value) {} // expected-note{{lookup in the object type 'Value' refers here}} + + void resolves_to_same() { + Value v; + v.set<double>(3.2); + } +}; +void resolves_to_different() { + { + Value v; + // The fact that the next line is a warning rather than an error is an + // extension. + v.set<double>(3.2); // expected-warning{{lookup of 'set' in member access expression is ambiguous; using member of 'Value'}} + } + { + int set; // Non-template. + Value v; + v.set<double>(3.2); + } +} + +namespace rdar9915664 { + struct A { + template<typename T> void a(); + }; + + struct B : A { }; + + struct C : A { }; + + struct D : B, C { + A &getA() { return static_cast<B&>(*this); } + + void test_a() { + getA().a<int>(); + } + }; +} + +namespace PR11856 { + template<typename T> T end(T); + + template <typename T> + void Foo() { + T it1; + if (it1->end < it1->end) { + } + } + + template<typename T> T *end(T*); + + class X { }; + template <typename T> + void Foo2() { + T it1; + if (it1->end < it1->end) { + } + + X *x; + if (x->end < 7) { // expected-error{{no member named 'end' in 'PR11856::X'}} + } + } +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p3.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p3.cpp new file mode 100644 index 0000000..cd7e669 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p3.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [basic.lookup.classref]p3: +// If the unqualified-id is ~type-name, the type-name is looked up in the +// context of the entire postfix-expression. If the type T of the object +// expression is of a class type C, the type-name is also looked up in the +// scope of class C. At least one of the lookups shall find a name that +// refers to (possibly cv-qualified) T. + +// From core issue 305 +struct A { +}; + +struct C { + struct A {}; + void f (); +}; + +void C::f () { + ::A *a; + a->~A (); +} + +// From core issue 414 +struct X {}; +void f() { + X x; + struct X {}; + x.~X(); +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp new file mode 100644 index 0000000..004d1e4 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test0 { + struct A { + static int foo; + }; + + namespace i0 { + typedef int A; // expected-note {{declared here}} + + int test() { + struct A a; // expected-error {{elaborated type refers to a typedef}} + return a.foo; + } + } + + namespace i1 { + template <class> class A; // expected-note {{declared here}} + + int test() { + struct A a; // expected-error {{elaborated type refers to a template}} + return a.foo; + } + } + + namespace i2 { + int A; + + int test() { + struct A a; + return a.foo; + } + } + + namespace i3 { + void A(); + + int test() { + struct A a; + return a.foo; + } + } + + namespace i4 { + template <class T> void A(); + + int test() { + struct A a; + return a.foo; + } + } + + // This should magically be okay; see comment in SemaDecl.cpp. + // rdar://problem/7898108 + typedef struct A A; + int test() { + struct A a; + return a.foo; + } +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp new file mode 100644 index 0000000..8126d28 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// elaborated-type-specifier: +// class-key '::'? nested-name-specifier? 'template'? simple-template-id +// Tests that this form is accepted by the compiler but does not follow +// the elaborated lookup rules of [basic.lookup.elab]. + +template <typename> class Ident {}; // expected-note {{previous use is here}} + +namespace A { + template <typename> void Ident(); + + class Ident<int> AIdent; // expected-error {{refers to a function template}} + class ::Ident<int> AnotherIdent; +} + +class Ident<int> GlobalIdent; +union Ident<int> GlobalIdent2; // expected-error {{ tag type that does not match }} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp new file mode 100644 index 0000000..7ecedd5 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct X0 { + X0 f1(); + X0 f2(); +}; + +template<typename T> +struct X1 { + X1<T>(int); + (X1<T>)(float); + X1 f2(); + X1 f2(int); + X1 f2(float); +}; + +// Error recovery: out-of-line constructors whose names have template arguments. +template<typename T> X1<T>::X1<T>(int) { } // expected-error{{out-of-line constructor for 'X1' cannot have template arguments}} +template<typename T> (X1<T>::X1<T>)(float) { } // expected-error{{out-of-line constructor for 'X1' cannot have template arguments}} + +// Error recovery: out-of-line constructor names intended to be types +X0::X0 X0::f1() { return X0(); } // expected-error{{qualified reference to 'X0' is a constructor name rather than a type wherever a constructor can be declared}} + +struct X0::X0 X0::f2() { return X0(); } + +template<typename T> X1<T>::X1<T> X1<T>::f2() { } // expected-error{{qualified reference to 'X1' is a constructor name rather than a template name wherever a constructor can be declared}} +template<typename T> X1<T>::X1<T> (X1<T>::f2)(int) { } // expected-error{{qualified reference to 'X1' is a constructor name rather than a template name wherever a constructor can be declared}} +template<typename T> struct X1<T>::X1<T> (X1<T>::f2)(float) { } diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp new file mode 100644 index 0000000..3039396 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace Ints { + int zero = 0; // expected-note {{candidate found by name lookup is 'Ints::zero'}} + void f(int); // expected-note 3 {{candidate function}} + void g(int); +} + +namespace Floats { + float zero = 0.0f; // expected-note {{candidate found by name lookup is 'Floats::zero'}} + void f(float); // expected-note 3 {{candidate function}} + void g(float); +} + +namespace Numbers { + using namespace Ints; + using namespace Floats; +} + +void test() { + int i = Ints::zero; + Ints::f(i); + + float f = Floats::zero; + Floats::f(f); + + double n = Numbers::zero; // expected-error {{reference to 'zero' is ambiguous}} + Numbers::f(n); // expected-error{{call to 'f' is ambiguous}} + Numbers::f(i); + Numbers::f(f); +} + +namespace Numbers { + struct Number { // expected-note 2 {{candidate}} + explicit Number(double d) : d(d) {} + double d; + }; + Number zero(0.0f); + void g(Number); // expected-note 2{{passing argument to parameter here}} +} + +void test2() { + Numbers::Number n = Numbers::zero; + Numbers::f(n); // expected-error {{no matching function for call to 'f'}} + Numbers::g(n); +} + +namespace Numbers2 { + using Numbers::f; + using Numbers::g; +} + +void test3() { + Numbers::Number n = Numbers::zero; + Numbers2::f(n); // expected-error {{no matching function for call to 'f'}} + Numbers2::g(n); + + int i = Ints::zero; + Numbers2::f(i); + Numbers2::g(i); // expected-error {{no viable conversion from 'int' to 'Numbers::Number'}} + + float f = Floats::zero; + Numbers2::f(f); + Numbers2::g(f); // expected-error {{no viable conversion from 'float' to 'Numbers::Number'}} +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p3.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p3.cpp new file mode 100644 index 0000000..dc0f8b4 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p3.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// This is basically paraphrased from the standard. + +namespace Root { + int i = 0; + void f(); +} + +namespace A { + using namespace Root; +} + +namespace B { + using namespace Root; +} + +namespace AB { + using namespace A; + using namespace B; +} + +void test() { + if (AB::i) + AB::f(); +} + +namespace C { + using Root::i; + using Root::f; +} + +namespace AC { + using namespace A; + using namespace C; +} + +void test2() { + if (AC::i) + AC::f(); +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p4.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p4.cpp new file mode 100644 index 0000000..38eccfa --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p4.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace A { + int a; +} + +namespace C { + int c; +} + +namespace B { + using namespace C; + int b; +} + +namespace C { + using namespace B; + using namespace A; +} + +void test() { + C::a++; + C::b++; + C::c++; +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p5.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p5.cpp new file mode 100644 index 0000000..5045bac --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p5.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace A { + struct x {}; // expected-note {{candidate found by name lookup is 'A::x'}} + int x; // expected-note {{candidate found by name lookup is 'A::x'}} + + struct y {}; // expected-note {{type declaration hidden}} + + struct z; + void z(float); +} + +namespace B { + struct x {}; // expected-note {{candidate found by name lookup is 'B::x'}} + float x; // expected-note {{candidate found by name lookup is 'B::x'}} + + float y; // expected-note {{declaration hides type}} + + void z(int); +} + +namespace AB { + using namespace A; + using namespace B; +} + +void test() { + struct AB::x foo; // expected-error {{reference to 'x' is ambiguous}} + int i = AB::x; // expected-error {{reference to 'x' is ambiguous}} + + struct AB::y bar; + float f = AB::y; // expected-error {{a type named 'y' is hidden by a declaration in a different namespace}} + AB::z(i); + AB::z(f); +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/p6-0x.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/p6-0x.cpp new file mode 100644 index 0000000..c745c84 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/p6-0x.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +// XFAIL: * +// Our C++0x doesn't currently have specialized destructor name handling, +// since the specification is still in flux. +struct C { + typedef int I; +}; + +typedef int I1, I2; +extern int* p; +extern int* q; + +void f() { + p->C::I::~I(); + q->I1::~I2(); +} + +struct A { + ~A(); +}; + +typedef A AB; +int main() { + AB *p; + p->AB::~AB(); +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/p6.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/p6.cpp new file mode 100644 index 0000000..0956de3 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/p6.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct C { + typedef int I; +}; + +typedef int I1, I2; +extern int* p; +extern int* q; + +void f() { + p->C::I::~I(); + q->I1::~I2(); +} + +struct A { + ~A(); +}; + +typedef A AB; +int main() { + AB *p; + p->AB::~AB(); // expected-error{{expected the class name after '~' to name a destructor}} +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.udir/p1.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.udir/p1.cpp new file mode 100644 index 0000000..ab0dc24 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.udir/p1.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// When looking up a namespace-name in a using-directive or +// namespace-alias-definition, only namespace names are considered. + +struct ns1 {}; +void ns2(); +int ns3 = 0; + +namespace ns0 { + namespace ns1 { + struct test0 {}; + } + namespace ns2 { + struct test1 {}; + } + namespace ns3 { + struct test2 {}; + } +} + +using namespace ns0; + +namespace test3 = ns1; +namespace test4 = ns2; +namespace test5 = ns3; + +using namespace ns1; +using namespace ns2; +using namespace ns3; + +test0 a; +test1 b; +test2 c; + diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p11.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p11.cpp new file mode 100644 index 0000000..a1cf529 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p11.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +static const int a = 10; + +void f0(int a, + int b = a) { // expected-error {{default argument references parameter 'a'}} +} + +template<int a, + int b = a> +class A { +}; diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p12.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p12.cpp new file mode 100644 index 0000000..878ff07 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p12.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct S {}; +S E0; + +namespace { + enum { + E0 = 1, + E1 = E0 + 1 + }; +} + + diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p13.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p13.cpp new file mode 100644 index 0000000..58d7ff4 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p13.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct S { + static const int f0 = 0; + static int f1; +}; + +int S::f1 = f0; diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp new file mode 100644 index 0000000..0fa4f65 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [basic.lookup.unqual]p14: +// If a variable member of a namespace is defined outside of the +// scope of its namespace then any name used in the definition of +// the variable member (after the declarator-id) is looked up as if +// the definition of the variable member occurred in its namespace. + +namespace N { + struct S {}; + S i; + extern S j; + extern S j2; +} + +int i = 2; +N::S N::j = i; +N::S N::j2(i); diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p15.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p15.cpp new file mode 100644 index 0000000..253d15e --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p15.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// XFAIL: * + +class C { +public: + C(int a, int b); +}; + +C::C(int a, // expected-note {{previous definition}} + int b) // expected-note {{previous definition}} +try { + int c; + +} catch (int a) { // expected-error {{redefinition of 'a'}} + int b; // expected-error {{redefinition of 'b'}} + ++c; // expected-error {{use of undeclared identifier 'c'}} +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp new file mode 100644 index 0000000..20a7ae0 --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +typedef int f; + +namespace N0 { + struct A { + friend void f(); + void g() { + int i = f(1); + } + }; +} + +namespace N1 { + struct A { + friend void f(A &); + operator int(); + void g(A a) { + // ADL should not apply to the lookup of 'f', it refers to the typedef + // above. + int i = f(a); + } + }; +} diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp new file mode 100644 index 0000000..d2afd5d --- /dev/null +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.unqual/p7.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5741 +namespace test0 { + struct A { + struct B { }; + struct C; + }; + + struct A::C : B { }; +} + +// Test that successive base specifiers don't screw with each other. +namespace test1 { + struct Opaque1 {}; + struct Opaque2 {}; + + struct A { + struct B { B(Opaque1); }; + }; + struct B { + B(Opaque2); + }; + + struct C : A, B { + // Apparently the base-or-member lookup is actually ambiguous + // without this qualification. + C() : A(), test1::B(Opaque2()) {} + }; +} + +// Test that we don't find the injected class name when parsing base +// specifiers. +namespace test2 { + template <class T> struct bar {}; + template <class T> struct foo : bar<foo> {}; // expected-error {{use of class template foo requires template arguments}} expected-note {{template is declared here}} +} diff --git a/clang/test/CXX/basic/basic.scope/basic.scope.hiding/p2.cpp b/clang/test/CXX/basic/basic.scope/basic.scope.hiding/p2.cpp new file mode 100644 index 0000000..911df98 --- /dev/null +++ b/clang/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/clang/test/CXX/basic/basic.scope/basic.scope.local/p4-0x.cpp b/clang/test/CXX/basic/basic.scope/basic.scope.local/p4-0x.cpp new file mode 100644 index 0000000..cd51c78 --- /dev/null +++ b/clang/test/CXX/basic/basic.scope/basic.scope.local/p4-0x.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +void f() { + int b; + int arr[] = {1, 2, 3}; + + if (bool b = true) // expected-note 2{{previous definition}} + bool b; // expected-error {{redefinition}} + else + int b; // expected-error {{redefinition}} + while (bool b = true) // expected-note {{previous definition}} + int b; // expected-error {{redefinition}} + for (int c; // expected-note 2{{previous definition}} + bool c = true;) // expected-error {{redefinition}} + double c; // expected-error {{redefinition}} + switch (int n = 37 + 5) // expected-note {{previous definition}} + int n; // expected-error {{redefinition}} + for (int a : arr) // expected-note {{previous definition}} + int a = 0; // expected-error {{redefinition}} + + if (bool b = true) { // expected-note 2{{previous definition}} + int b; // expected-error {{redefinition}} + } else { + int b; // expected-error {{redefinition}} + } + while (bool b = true) { // expected-note {{previous definition}} + int b; // expected-error {{redefinition}} + } + for (int c; // expected-note 2{{previous definition}} + bool c = true;) { // expected-error {{redefinition}} + double c; // expected-error {{redefinition}} + } + switch (int n = 37 + 5) { // expected-note {{previous definition}} + int n; // expected-error {{redefinition}} + } + for (int &a : arr) { // expected-note {{previous definition}} + int a = 0; // expected-error {{redefinition}} + } + + if (bool b = true) {{ // expected-note {{previous definition}} + bool b; + }} else { + int b; // expected-error {{redefinition}} + } + if (bool b = true) { // expected-note {{previous definition}} + bool b; // expected-error {{redefinition}} + } else {{ + int b; + }} + if (bool b = true) {{ + bool b; + }} else {{ + int b; + }} + while (bool b = true) {{ + int b; + }} + for (int c; // expected-note {{previous definition}} + bool c = true; ) {{ // expected-error {{redefinition}} + double c; + }} + switch (int n = 37 + 5) {{ + int n; + }} + for (int &a : arr) {{ + int a = 0; + }} +} diff --git a/clang/test/CXX/basic/basic.scope/basic.scope.pdecl/p3.cpp b/clang/test/CXX/basic/basic.scope/basic.scope.pdecl/p3.cpp new file mode 100644 index 0000000..407a5f7 --- /dev/null +++ b/clang/test/CXX/basic/basic.scope/basic.scope.pdecl/p3.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// Classes. +namespace Class { + namespace NS { + class C {}; // expected-note {{candidate}} + } + using namespace NS; + class C : C {}; // expected-error {{reference to 'C' is ambiguous}} \ + expected-note {{candidate}} +} + +// Enumerations. +enum E { + EPtrSize = sizeof((E*)0) // ok, E is already declared +}; + +// Alias declarations. clang implements the proposed resolution to N1044. +namespace Alias { + namespace NS { + class C; + } + using namespace NS; + using C = C; // ok, C = B::C + using C = NS::C; // ok, same type +} diff --git a/clang/test/CXX/basic/basic.scope/basic.scope.pdecl/p9.cpp b/clang/test/CXX/basic/basic.scope/basic.scope.pdecl/p9.cpp new file mode 100644 index 0000000..e64b675 --- /dev/null +++ b/clang/test/CXX/basic/basic.scope/basic.scope.pdecl/p9.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Template type parameters. +typedef unsigned char T; +template<typename T = T> struct X0 { }; +template<> struct X0<unsigned char> { static const bool value = true; }; +int array0[X0<>::value? 1 : -1]; + +// Non-type template parameters. +const int N = 17; +template<int N = N> struct X1 { }; +template<> struct X1<17> { static const bool value = true; }; +int array1[X1<>::value? 1 : -1]; + +// Template template parameters. +template<template<class> class X0 = X0> struct X2 { }; +template<> struct X2<X0> { static const bool value = true; }; +int array2[X2<>::value? 1 : -1]; diff --git a/clang/test/CXX/basic/basic.start/basic.start.main/p2a.cpp b/clang/test/CXX/basic/basic.start/basic.start.main/p2a.cpp new file mode 100644 index 0000000..b8dfbe7 --- /dev/null +++ b/clang/test/CXX/basic/basic.start/basic.start.main/p2a.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +typedef int Int; +typedef char Char; +typedef Char* Carp; + +Int main(Int argc, Carp argv[]) { +} diff --git a/clang/test/CXX/basic/basic.start/basic.start.main/p2b.cpp b/clang/test/CXX/basic/basic.start/basic.start.main/p2b.cpp new file mode 100644 index 0000000..785382c --- /dev/null +++ b/clang/test/CXX/basic/basic.start/basic.start.main/p2b.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +typedef int Int; +typedef char Char; +typedef Char* Carp; + +Int main(Int argc, Carp argv[], Char *env[]) { +} diff --git a/clang/test/CXX/basic/basic.start/basic.start.main/p2c.cpp b/clang/test/CXX/basic/basic.start/basic.start.main/p2c.cpp new file mode 100644 index 0000000..81b08b9 --- /dev/null +++ b/clang/test/CXX/basic/basic.start/basic.start.main/p2c.cpp @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int main() { +} diff --git a/clang/test/CXX/basic/basic.start/basic.start.main/p2d.cpp b/clang/test/CXX/basic/basic.start/basic.start.main/p2d.cpp new file mode 100644 index 0000000..bcdbdb2 --- /dev/null +++ b/clang/test/CXX/basic/basic.start/basic.start.main/p2d.cpp @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +static int main() { // expected-error {{'main' is not allowed to be declared static}} +} diff --git a/clang/test/CXX/basic/basic.start/basic.start.main/p2e.cpp b/clang/test/CXX/basic/basic.start/basic.start.main/p2e.cpp new file mode 100644 index 0000000..954fdbd --- /dev/null +++ b/clang/test/CXX/basic/basic.start/basic.start.main/p2e.cpp @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +inline int main() { // expected-error {{'main' is not allowed to be declared inline}} +} diff --git a/clang/test/CXX/basic/basic.start/basic.start.main/p2f.cpp b/clang/test/CXX/basic/basic.start/basic.start.main/p2f.cpp new file mode 100644 index 0000000..ea5a752 --- /dev/null +++ b/clang/test/CXX/basic/basic.start/basic.start.main/p2f.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void // expected-error {{'main' must return 'int'}} +main( // expected-error {{first parameter of 'main' (argument count) must be of type 'int'}} + float a +) { +} diff --git a/clang/test/CXX/basic/basic.start/basic.start.main/p2g.cpp b/clang/test/CXX/basic/basic.start/basic.start.main/p2g.cpp new file mode 100644 index 0000000..e3209fd --- /dev/null +++ b/clang/test/CXX/basic/basic.start/basic.start.main/p2g.cpp @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int main(int argc, const char* const* argv) { +} diff --git a/clang/test/CXX/basic/basic.start/basic.start.main/p2h.cpp b/clang/test/CXX/basic/basic.start/basic.start.main/p2h.cpp new file mode 100644 index 0000000..abf8faa --- /dev/null +++ b/clang/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/clang/test/CXX/basic/basic.start/basic.start.main/p2i.cpp b/clang/test/CXX/basic/basic.start/basic.start.main/p2i.cpp new file mode 100644 index 0000000..db8da3c --- /dev/null +++ b/clang/test/CXX/basic/basic.start/basic.start.main/p2i.cpp @@ -0,0 +1,6 @@ +// RUN: cp %s %t +// RUN: %clang_cc1 -x c++ %s -std=c++11 -fsyntax-only -verify +// RUN: not %clang_cc1 -x c++ %t -std=c++11 -fixit +// RUN: %clang_cc1 -x c++ %t -std=c++11 -fsyntax-only + +constexpr int main() { } // expected-error{{'main' is not allowed to be declared constexpr}} diff --git a/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp b/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp new file mode 100644 index 0000000..8a62ae8 --- /dev/null +++ b/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +#include <stddef.h> + +struct A { + void *operator new(size_t); +}; + +namespace NS { + void *operator new(size_t);; // expected-error {{'operator new' cannot be declared inside a namespace}} +} + +static void *operator new(size_t); // expected-error {{'operator new' cannot be declared static in global scope}} + +struct B { + void operator new(size_t); // expected-error {{'operator new' must return type 'void *'}} +}; + +struct C { + void *operator new(); // expected-error {{'operator new' must have at least one parameter}} +}; + +struct D { + void *operator new(bool); // expected-error {{'operator new' takes type size_t}} +}; + +struct E { + void *operator new(size_t = 0); // expected-error {{parameter of 'operator new' cannot have a default argument}} +}; + +struct F { + template<typename T> void *operator new(size_t, int); +}; + +struct G { + template<typename T> T operator new(size_t, int); // expected-error {{'operator new' cannot have a dependent return type; use 'void *' instead}} +}; + +struct H { + template<typename T> void *operator new(T, int); // expected-error {{'operator new' cannot take a dependent type as first parameter; use size_t}} +}; + +struct I { + template<typename T> void *operator new(size_t); // expected-error {{'operator new' template must have at least two parameters}} +}; diff --git a/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp b/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp new file mode 100644 index 0000000..e00e948 --- /dev/null +++ b/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A { + void operator delete(void*); +}; + +namespace NS { + void operator delete(void *); // expected-error {{'operator delete' cannot be declared inside a namespace}} +} + +static void operator delete(void *); // expected-error {{'operator delete' cannot be declared static in global scope}} diff --git a/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-nodef.cpp b/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-nodef.cpp new file mode 100644 index 0000000..6cd587c --- /dev/null +++ b/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-nodef.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int *use_new(int N) { + return new int [N]; +} + +int std = 17; diff --git a/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-noexceptions.cpp b/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-noexceptions.cpp new file mode 100644 index 0000000..4567c46 --- /dev/null +++ b/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-noexceptions.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +namespace std { + class bad_alloc { }; + + typedef __SIZE_TYPE__ size_t; +} + +class foo { virtual ~foo(); }; + +void* operator new(std::size_t); +void* operator new[](std::size_t); +void operator delete(void*); +void operator delete[](void*); diff --git a/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp b/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp new file mode 100644 index 0000000..47b5158 --- /dev/null +++ b/clang/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -fexceptions -fcxx-exceptions -verify %s +int *use_new(int N) { + if (N == 1) + return new int; + + return new int [N]; +} + +void use_delete(int* ip, int N) { + if (N == 1) + delete ip; + else + delete [] ip; +} + +namespace std { + class bad_alloc { }; + + typedef __SIZE_TYPE__ size_t; +} + +void* operator new(std::size_t) throw(std::bad_alloc); // expected-note{{previous declaration}} +void* operator new[](std::size_t) throw(std::bad_alloc); +void operator delete(void*) throw(); // expected-note{{previous declaration}} +void operator delete[](void*) throw(); + +void* operator new(std::size_t); // expected-warning{{'operator new' is missing exception specification 'throw(std::bad_alloc)'}} +void operator delete(void*); // expected-warning{{'operator delete' is missing exception specification 'throw()'}} diff --git a/clang/test/CXX/basic/basic.types/p10.cpp b/clang/test/CXX/basic/basic.types/p10.cpp new file mode 100644 index 0000000..83b910b --- /dev/null +++ b/clang/test/CXX/basic/basic.types/p10.cpp @@ -0,0 +1,132 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct NonLiteral { NonLiteral(); }; + +// A type is a literal type if it is: + +// - a scalar type +constexpr int f1(double) { return 0; } + +// - a reference type +struct S { S(); }; +constexpr int f2(S &) { return 0; } + +// FIXME: I'm not entirely sure whether the following is legal or not... +struct BeingDefined; +extern BeingDefined beingdefined; +struct BeingDefined { + static constexpr BeingDefined& t = beingdefined; +}; + +// - a class type that has all of the following properties: + +// (implied) - it is complete + +struct Incomplete; +template<class T> struct ClassTemp {}; + +constexpr Incomplete incomplete = {}; // expected-error {{constexpr variable cannot have non-literal type 'const Incomplete'}} +constexpr Incomplete incomplete2[] = {}; // expected-error {{constexpr variable cannot have non-literal type 'Incomplete const[]'}} +constexpr ClassTemp<int> classtemplate = {}; +constexpr ClassTemp<int> classtemplate2[] = {}; + +// - it has a trivial destructor +struct UserProvDtor { + constexpr int f(); // expected-error {{non-literal type 'UserProvDtor' cannot have constexpr members}} + ~UserProvDtor(); // expected-note {{has a user-provided destructor}} +}; + +struct NonTrivDtor { + constexpr NonTrivDtor(); + constexpr int f(); // expected-error {{non-literal type 'NonTrivDtor' cannot have constexpr members}} + virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} +}; +struct NonTrivDtorBase { + ~NonTrivDtorBase(); +}; +template<typename T> +struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}} + constexpr DerivedFromNonTrivDtor(); +}; +constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>) { return 0; } // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}} +struct TrivDtor { + constexpr TrivDtor(); +}; +constexpr int f(TrivDtor) { return 0; } +struct TrivDefaultedDtor { + constexpr TrivDefaultedDtor(); + ~TrivDefaultedDtor() = default; +}; +constexpr int f(TrivDefaultedDtor) { return 0; } + +// - it is an aggregate type or has at least one constexpr constructor or +// constexpr constructor template that is not a copy or move constructor +struct Agg { + int a; + char *b; +}; +constexpr int f3(Agg a) { return a.a; } +struct CtorTemplate { + template<typename T> constexpr CtorTemplate(T); +}; +struct CopyCtorOnly { // expected-note {{'CopyCtorOnly' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}} + constexpr CopyCtorOnly(CopyCtorOnly&); + constexpr int f(); // expected-error {{non-literal type 'CopyCtorOnly' cannot have constexpr members}} +}; +struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}} + constexpr MoveCtorOnly(MoveCtorOnly&&); + constexpr int f(); // expected-error {{non-literal type 'MoveCtorOnly' cannot have constexpr members}} +}; +template<typename T> +struct CtorArg { + constexpr CtorArg(T); +}; +constexpr int f(CtorArg<int>) { return 0; } // ok +constexpr int f(CtorArg<NonLiteral>) { return 0; } // ok, ctor is still constexpr +// We have a special-case diagnostic for classes with virtual base classes. +struct VBase {}; +struct HasVBase : virtual VBase {}; // expected-note 2{{virtual base class declared here}} +struct Derived : HasVBase { + constexpr Derived() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}} +}; +template<typename T> struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}} + constexpr DerivedFromVBase(); +}; +constexpr int f(DerivedFromVBase<HasVBase>) {} // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase<HasVBase>' is not a literal type}} +template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {} +constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // expected-error {{constant expression}} expected-note {{cannot construct object of type 'DerivedFromVBase<HasVBase>' with virtual base class in a constant expression}} + +// - it has all non-static data members and base classes of literal types +struct NonLitMember { + S s; // expected-note {{has data member 's' of non-literal type 'S'}} +}; +constexpr int f(NonLitMember) {} // expected-error {{1st parameter type 'NonLitMember' is not a literal type}} +struct NonLitBase : + S { // expected-note {{base class 'S' of non-literal type}} + constexpr NonLitBase(); + constexpr int f() { return 0; } // expected-error {{non-literal type 'NonLitBase' cannot have constexpr members}} +}; +struct LitMemBase : Agg { + Agg agg; +}; +template<typename T> +struct MemberType { + T t; // expected-note {{'MemberType<NonLiteral>' is not literal because it has data member 't' of non-literal type 'NonLiteral'}} + constexpr MemberType(); +}; +constexpr int f(MemberType<int>) { return 0; } +constexpr int f(MemberType<NonLiteral>) { return 0; } // expected-error {{not a literal type}} + +// - an array of literal type +struct ArrGood { + Agg agg[24]; + double d[12]; + TrivDtor td[3]; + TrivDefaultedDtor tdd[3]; +}; +constexpr int f(ArrGood) { return 0; } + +struct ArrBad { + S s[3]; // expected-note {{data member 's' of non-literal type 'S [3]'}} +}; +constexpr int f(ArrBad) { return 0; } // expected-error {{1st parameter type 'ArrBad' is not a literal type}} diff --git a/clang/test/CXX/class.access/class.access.base/p1.cpp b/clang/test/CXX/class.access/class.access.base/p1.cpp new file mode 100644 index 0000000..43cc99e --- /dev/null +++ b/clang/test/CXX/class.access/class.access.base/p1.cpp @@ -0,0 +1,155 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [class.access.base]p1(a): +// If a class is declared to be a base class for another class using +// the public access specifier, the public members of the base class +// are accessible as public members of the derived class and protected +// members of the base class are accessible as protected members of +// the derived class. +namespace test0 { + class Base { + public: int pub; static int spub; + protected: int prot; static int sprot; // expected-note 4 {{declared protected here}} + private: int priv; static int spriv; // expected-note 8 {{declared private here}} + }; + + class Test : public Base { + void test() { + pub++; + spub++; + prot++; + sprot++; + priv++; // expected-error {{private member}} + spriv++; // expected-error {{private member}} + + Base::pub++; + Base::spub++; + Base::prot++; + Base::sprot++; + Base::priv++; // expected-error {{private member}} + Base::spriv++; // expected-error {{private member}} + } + }; + + void test(Test *t) { + t->pub++; + t->spub++; + t->prot++; // expected-error {{protected member}} + t->sprot++; // expected-error {{protected member}} + t->priv++; // expected-error {{private member}} + t->spriv++; // expected-error {{private member}} + + t->Base::pub++; + t->Base::spub++; + t->Base::prot++; // expected-error {{protected member}} + t->Base::sprot++; // expected-error {{protected member}} + t->Base::priv++; // expected-error {{private member}} + t->Base::spriv++; // expected-error {{private member}} + } +} + +// C++0x [class.access.base]p1(b): +// If a class is declared to be a base class for another class using +// the protected access specifier, the public and protected members +// of the base class are accessible as protected members of the +// derived class. +namespace test1 { + class Base { // expected-note 6{{member is declared here}} + public: + int pub; // expected-note{{member is declared here}} + static int spub; // expected-note{{member is declared here}} + protected: int prot; static int sprot; // expected-note 4 {{declared protected here}} + private: int priv; static int spriv; // expected-note 8 {{declared private here}} + }; + + class Test : protected Base { // expected-note 6 {{declared protected here}} expected-note 8 {{constrained by protected inheritance here}} + void test() { + pub++; + spub++; + prot++; + sprot++; + priv++; // expected-error {{private member}} + spriv++; // expected-error {{private member}} + + Base::pub++; + Base::spub++; + Base::prot++; + Base::sprot++; + Base::priv++; // expected-error {{private member}} + Base::spriv++; // expected-error {{private member}} + } + }; + + void test(Test *t) { + t->pub++; // expected-error {{protected member}} expected-error {{protected base class}} + t->spub++; // expected-error {{protected member}} + t->prot++; // expected-error {{protected member}} expected-error {{protected base class}} + t->sprot++; // expected-error {{protected member}} + t->priv++; // expected-error {{private member}} expected-error {{protected base class}} + t->spriv++; // expected-error {{private member}} + + // Two possible errors here: one for Base, one for the member + t->Base::pub++; // expected-error {{protected member}} expected-error {{protected base class}} + t->Base::spub++; // expected-error {{protected member}} + t->Base::prot++; // expected-error 2 {{protected member}} expected-error {{protected base class}} + t->Base::sprot++; // expected-error 2 {{protected member}} + t->Base::priv++; // expected-error {{protected member}} expected-error {{private member}} expected-error {{protected base class}} + t->Base::spriv++; // expected-error {{protected member}} expected-error {{private member}} + } +} + +// C++0x [class.access.base]p1(b): +// If a class is declared to be a base class for another class using +// the private access specifier, the public and protected members of +// the base class are accessible as private members of the derived +// class. +namespace test2 { + class Base { // expected-note 6{{member is declared here}} + public: + int pub; // expected-note{{member is declared here}} + static int spub; // expected-note{{member is declared here}} + protected: + int prot; // expected-note {{declared protected here}} \ + // expected-note{{member is declared here}} + static int sprot; // expected-note {{declared protected here}} \ + // expected-note{{member is declared here}} + private: + int priv; // expected-note 4 {{declared private here}} + static int spriv; // expected-note 4 {{declared private here}} + }; + + class Test : private Base { // expected-note 6 {{declared private here}} \ + // expected-note 10 {{constrained by private inheritance here}} + void test() { + pub++; + spub++; + prot++; + sprot++; + priv++; // expected-error {{private member}} + spriv++; // expected-error {{private member}} + + Base::pub++; + Base::spub++; + Base::prot++; + Base::sprot++; + Base::priv++; // expected-error {{private member}} + Base::spriv++; // expected-error {{private member}} + } + }; + + void test(Test *t) { + t->pub++; // expected-error {{private member}} expected-error {{private base class}} + t->spub++; // expected-error {{private member}} + t->prot++; // expected-error {{private member}} expected-error {{private base class}} + t->sprot++; // expected-error {{private member}} + t->priv++; // expected-error {{private member}} expected-error {{private base class}} + t->spriv++; // expected-error {{private member}} + + t->Base::pub++; // expected-error {{private member}} expected-error {{private base class}} + t->Base::spub++; // expected-error {{private member}} + t->Base::prot++; // expected-error {{protected member}} expected-error {{private member}} expected-error {{private base class}} + t->Base::sprot++; // expected-error {{protected member}} expected-error {{private member}} + t->Base::priv++; // expected-error 2 {{private member}} expected-error {{private base class}} + t->Base::spriv++; // expected-error 2 {{private member}} + } +} diff --git a/clang/test/CXX/class.access/class.access.base/p5.cpp b/clang/test/CXX/class.access/class.access.base/p5.cpp new file mode 100644 index 0000000..255fbfc --- /dev/null +++ b/clang/test/CXX/class.access/class.access.base/p5.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -verify %s + +namespace test0 { + struct A { + static int x; + }; + struct B : A {}; + struct C : B {}; + + int test() { + return A::x + + B::x + + C::x; + } +} + +namespace test1 { + struct A { + private: static int x; // expected-note 5 {{declared private here}} + static int test() { return x; } + }; + struct B : public A { + static int test() { return x; } // expected-error {{private member}} + }; + struct C : private A { + static int test() { return x; } // expected-error {{private member}} + }; + + struct D { + public: static int x; // expected-note{{member is declared here}} + static int test() { return x; } + }; + struct E : private D { // expected-note{{constrained by private inheritance}} + static int test() { return x; } + }; + + int test() { + return A::x // expected-error {{private member}} + + B::x // expected-error {{private member}} + + C::x // expected-error {{private member}} + + D::x + + E::x; // expected-error {{private member}} + } +} + +namespace test2 { + class A { + protected: static int x; // expected-note{{member is declared here}} + }; + + class B : private A {}; // expected-note {{private inheritance}} + class C : private A { + int test(B *b) { + return b->x; // expected-error {{private member}} + } + }; +} + +namespace test3 { + class A { + protected: static int x; + }; + + class B : public A {}; + class C : private A { + int test(B *b) { + // x is accessible at C when named in A. + // A is an accessible base of B at C. + // Therefore this succeeds. + return b->x; + } + }; +} + +// TODO: flesh out these cases diff --git a/clang/test/CXX/class.access/class.access.dcl/p1.cpp b/clang/test/CXX/class.access/class.access.dcl/p1.cpp new file mode 100644 index 0000000..aab5fff --- /dev/null +++ b/clang/test/CXX/class.access/class.access.dcl/p1.cpp @@ -0,0 +1,199 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// This is just the test for [namespace.udecl]p4 with 'using' +// uniformly stripped out. + +// C++03 [namespace.udecl]p4: +// A using-declaration used as a member-declaration shall refer to a +// member of a base class of the class being defined, shall refer to +// a member of an anonymous union that is a member of a base class +// of the class being defined, or shall refer to an enumerator for +// an enumeration type that is a member of a base class of the class +// being defined. + +// There is no directly analogous paragraph in C++0x, and the feature +// works sufficiently differently there that it needs a separate test. + +namespace test0 { + namespace NonClass { + typedef int type; + struct hiding {}; + int hiding; + static union { double union_member; }; + enum tagname { enumerator }; + } + + class Test0 { + NonClass::type; // expected-error {{not a class}} expected-warning {{access declarations are deprecated}} + NonClass::hiding; // expected-error {{not a class}} expected-warning {{access declarations are deprecated}} + NonClass::union_member; // expected-error {{not a class}} expected-warning {{access declarations are deprecated}} + NonClass::enumerator; // expected-error {{not a class}} expected-warning {{access declarations are deprecated}} + }; +} + +struct Opaque0 {}; + +namespace test1 { + struct A { + typedef int type; + struct hiding {}; // expected-note {{previous use is here}} + Opaque0 hiding; + union { double union_member; }; + enum tagname { enumerator }; + }; + + struct B : A { + A::type; // expected-warning {{access declarations are deprecated}} + A::hiding; // expected-warning {{access declarations are deprecated}} + A::union_member; // expected-warning {{access declarations are deprecated}} + A::enumerator; // expected-warning {{access declarations are deprecated}} + A::tagname; // expected-warning {{access declarations are deprecated}} + + void test0() { + type t = 0; + } + + void test1() { + typedef struct A::hiding local; + struct hiding _ = local(); + } + + void test2() { + union hiding _; // expected-error {{tag type that does not match previous}} + } + + void test3() { + char array[sizeof(union_member) == sizeof(double) ? 1 : -1]; + } + + void test4() { + enum tagname _ = enumerator; + } + + void test5() { + Opaque0 _ = hiding; + } + }; +} + +namespace test2 { + struct A { + typedef int type; + struct hiding {}; // expected-note {{previous use is here}} + int hiding; + union { double union_member; }; + enum tagname { enumerator }; + }; + + template <class T> struct B : A { + A::type; // expected-warning {{access declarations are deprecated}} + A::hiding; // expected-warning {{access declarations are deprecated}} + A::union_member; // expected-warning {{access declarations are deprecated}} + A::enumerator; // expected-warning {{access declarations are deprecated}} + A::tagname; // expected-warning {{access declarations are deprecated}} + + void test0() { + type t = 0; + } + + void test1() { + typedef struct A::hiding local; + struct hiding _ = local(); + } + + void test2() { + union hiding _; // expected-error {{tag type that does not match previous}} + } + + void test3() { + char array[sizeof(union_member) == sizeof(double) ? 1 : -1]; + } + + void test4() { + enum tagname _ = enumerator; + } + + void test5() { + Opaque0 _ = hiding; + } + }; +} + +namespace test3 { + struct hiding {}; + + template <class T> struct A { + typedef int type; // expected-note {{target of using declaration}} + struct hiding {}; + Opaque0 hiding; + union { double union_member; }; + enum tagname { enumerator }; // expected-note {{target of using declaration}} + }; + + template <class T> struct B : A<T> { + A<T>::type; // expected-error {{dependent using declaration resolved to type without 'typename'}} // expected-warning {{access declarations are deprecated}} + A<T>::hiding; // expected-warning {{access declarations are deprecated}} + A<T>::union_member; // expected-warning {{access declarations are deprecated}} + A<T>::enumerator; // expected-warning {{access declarations are deprecated}} + A<T>::tagname; // expected-error {{dependent using declaration resolved to type without 'typename'}} // expected-warning {{access declarations are deprecated}} + + // FIXME: re-enable these when the various bugs involving tags are fixed +#if 0 + void test1() { + typedef struct A<T>::hiding local; + struct hiding _ = local(); + } + + void test2() { + typedef struct A<T>::hiding local; + union hiding _ = local(); + } +#endif + + void test3() { + char array[sizeof(union_member) == sizeof(double) ? 1 : -1]; + } + +#if 0 + void test4() { + enum tagname _ = enumerator; + } +#endif + + void test5() { + Opaque0 _ = hiding; + } + }; + + template struct B<int>; // expected-note {{in instantiation}} +} + +namespace test4 { + struct Base { + int foo(); + }; + + struct Unrelated { + int foo(); + }; + + struct Subclass : Base { + }; + + namespace InnerNS { + int foo(); + } + + // We should be able to diagnose these without instantiation. + template <class T> struct C : Base { + InnerNS::foo; // expected-error {{not a class}} expected-warning {{access declarations are deprecated}} + Base::bar; // expected-error {{no member named 'bar'}} expected-warning {{access declarations are deprecated}} + Unrelated::foo; // expected-error {{not a base class}} expected-warning {{access declarations are deprecated}} + C::foo; // legal in C++03 // expected-warning {{access declarations are deprecated}} + Subclass::foo; // legal in C++03 // expected-warning {{access declarations are deprecated}} + + int bar(); //expected-note {{target of using declaration}} + C::bar; // expected-error {{refers to its own class}} expected-warning {{access declarations are deprecated}} + }; +} + diff --git a/clang/test/CXX/class.access/class.access.nest/p1.cpp b/clang/test/CXX/class.access/class.access.nest/p1.cpp new file mode 100644 index 0000000..eceffcf --- /dev/null +++ b/clang/test/CXX/class.access/class.access.nest/p1.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Derived from GNU's std::string +namespace test0 { + class A { + struct B { + unsigned long length; + }; + struct C : B { + static const unsigned long max_length; + }; + }; + + const unsigned long A::C::max_length = sizeof(B); +} + +// Example from the standard. +namespace test1 { + class E { + int x; + class B {}; + + class I { + B b; + int y; // expected-note {{declared private here}} + void f(E* p, int i) { + p->x = i; + } + }; + + int g(I* p) { return p->y; } // expected-error {{'y' is a private member of 'test1::E::I'}} + }; +} diff --git a/clang/test/CXX/class.access/class.friend/p1.cpp b/clang/test/CXX/class.access/class.friend/p1.cpp new file mode 100644 index 0000000..68ff83f --- /dev/null +++ b/clang/test/CXX/class.access/class.friend/p1.cpp @@ -0,0 +1,356 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++'0x [class.friend] p1: +// A friend of a class is a function or class that is given permission to use +// the private and protected member names from the class. A class specifies +// its friends, if any, by way of friend declarations. Such declarations give +// special access rights to the friends, but they do not make the nominated +// friends members of the befriending class. + +struct S { static void f(); }; +S* g() { return 0; } + +struct X { + friend struct S; + friend S* g(); +}; + +void test1() { + S s; + g()->f(); + S::f(); + X::g(); // expected-error{{no member named 'g' in 'X'}} + X::S x_s; // expected-error{{no member named 'S' in 'X'}} + X x; + x.g(); // expected-error{{no member named 'g' in 'X'}} +} + +// Test that we recurse through namespaces to find already declared names, but +// new names are declared within the enclosing namespace. +namespace N { + struct X { + friend struct S; + friend S* g(); + + friend struct S2; + friend struct S2* g2(); + }; + + struct S2 { static void f2(); }; + S2* g2() { return 0; } + + void test() { + g()->f(); + S s; + S::f(); + X::g(); // expected-error{{no member named 'g' in 'N::X'}} + X::S x_s; // expected-error{{no member named 'S' in 'N::X'}} + X x; + x.g(); // expected-error{{no member named 'g' in 'N::X'}} + + g2(); + S2 s2; + ::g2(); // expected-error{{no member named 'g2' in the global namespace}} + ::S2 g_s2; // expected-error{{no member named 'S2' in the global namespace}} + X::g2(); // expected-error{{no member named 'g2' in 'N::X'}} + X::S2 x_s2; // expected-error{{no member named 'S2' in 'N::X'}} + x.g2(); // expected-error{{no member named 'g2' in 'N::X'}} + } +} + +namespace test0 { + class ClassFriend { + void test(); + }; + + class MemberFriend { + void test(); + }; + + void declared_test(); + + class Class { + static void member(); // expected-note 2 {{declared private here}} + + friend class ClassFriend; + friend class UndeclaredClassFriend; + + friend void undeclared_test(); + friend void declared_test(); + friend void MemberFriend::test(); + }; + + void declared_test() { + Class::member(); + } + + void undeclared_test() { + Class::member(); + } + + void unfriended_test() { + Class::member(); // expected-error {{'member' is a private member of 'test0::Class'}} + } + + void ClassFriend::test() { + Class::member(); + } + + void MemberFriend::test() { + Class::member(); + } + + class UndeclaredClassFriend { + void test() { + Class::member(); + } + }; + + class ClassNonFriend { + void test() { + Class::member(); // expected-error {{'member' is a private member of 'test0::Class'}} + } + }; +} + +// Make sure that friends have access to inherited protected members. +namespace test2 { + struct X; + + class ilist_half_node { + friend struct ilist_walker_bad; + X *Prev; + protected: + X *getPrev() { return Prev; } // expected-note{{member is declared here}} + }; + + class ilist_node : private ilist_half_node { // expected-note {{declared private here}} expected-note {{constrained by private inheritance here}} + friend struct ilist_walker; + X *Next; + X *getNext() { return Next; } // expected-note {{declared private here}} + }; + + struct X : ilist_node {}; + + struct ilist_walker { + static X *getPrev(X *N) { return N->getPrev(); } + static X *getNext(X *N) { return N->getNext(); } + }; + + struct ilist_walker_bad { + static X *getPrev(X *N) { return N->getPrev(); } // \ + // expected-error {{'getPrev' is a private member of 'test2::ilist_half_node'}} \ + // expected-error {{cannot cast 'test2::X' to its private base class 'test2::ilist_half_node'}} + + static X *getNext(X *N) { return N->getNext(); } // \ + // expected-error {{'getNext' is a private member of 'test2::ilist_node'}} + }; +} + +namespace test3 { + class A { protected: int x; }; // expected-note {{declared protected here}} + + class B : public A { + friend int foo(B*); + }; + + int foo(B *p) { + return p->x; + } + + int foo(const B *p) { + return p->x; // expected-error {{'x' is a protected member of 'test3::A'}} + } +} + +namespace test3a { + class A { protected: int x; }; + + class B : public A { + friend int foo(B*); + }; + + int foo(B * const p) { + return p->x; + } +} + +namespace test4 { + template <class T> class Holder { + T object; + friend bool operator==(Holder &a, Holder &b) { + return a.object == b.object; // expected-error {{invalid operands to binary expression}} + } + }; + + struct Inequal {}; + bool test() { + Holder<Inequal> a, b; + return a == b; // expected-note {{requested here}} + } +} + + +// PR6174 +namespace test5 { + namespace ns { + class A; + } + + class ns::A { + private: int x; + friend class B; + }; + + namespace ns { + class B { + int test(A *p) { return p->x; } + }; + } +} + +// PR6207 +namespace test6 { + struct A {}; + + struct B { + friend A::A(); + friend A::~A(); + friend A &A::operator=(const A&); + }; +} + +namespace test7 { + template <class T> struct X { + X(); + ~X(); + void foo(); + void bar(); + }; + + class A { + friend void X<int>::foo(); + friend X<int>::X(); + friend X<int>::X(const X&); + + private: + A(); // expected-note 2 {{declared private here}} + }; + + template<> void X<int>::foo() { + A a; + } + + template<> void X<int>::bar() { + A a; // expected-error {{calling a private constructor}} + } + + template<> X<int>::X() { + A a; + } + + template<> X<int>::~X() { + A a; // expected-error {{calling a private constructor}} + } +} + +// Return types, parameters and default arguments to friend functions. +namespace test8 { + class A { + typedef int I; // expected-note 4 {{declared private here}} + static const I x = 0; // expected-note {{implicitly declared private here}} + friend I f(I i); + template<typename T> friend I g(I i); + }; + + const A::I A::x; + A::I f(A::I i = A::x) {} + template<typename T> A::I g(A::I i) { + T t; + } + template A::I g<A::I>(A::I i); + + A::I f2(A::I i = A::x) {} // expected-error 3 {{is a private member of}} + template<typename T> A::I g2(A::I i) { // expected-error 2 {{is a private member of}} + T t; + } + template A::I g2<A::I>(A::I i); +} + +// PR6885 +namespace test9 { + class B { + friend class test9; + }; +} + +// PR7230 +namespace test10 { + extern "C" void f(void); + extern "C" void g(void); + + namespace NS { + class C { + void foo(void); // expected-note {{declared private here}} + friend void test10::f(void); + }; + static C* bar; + } + + void f(void) { + NS::bar->foo(); + } + + void g(void) { + 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; + } +} + +namespace PR9103 { + struct base { + protected: + static void foo(void) {} + }; + + struct cls: base { + friend void bar(void) { + base::foo(); + } + }; +} diff --git a/clang/test/CXX/class.access/class.friend/p11.cpp b/clang/test/CXX/class.access/class.friend/p11.cpp new file mode 100644 index 0000000..a05b2d2 --- /dev/null +++ b/clang/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/clang/test/CXX/class.access/class.friend/p2-cxx03.cpp b/clang/test/CXX/class.access/class.friend/p2-cxx03.cpp new file mode 100644 index 0000000..f8cabfd --- /dev/null +++ b/clang/test/CXX/class.access/class.friend/p2-cxx03.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> +class X0 { + friend T; // expected-warning{{non-class friend type 'T' is a C++11 extension}} +}; + +class X1 { }; +enum E1 { }; +X0<X1> x0a; +X0<X1 *> x0b; +X0<int> x0c; +X0<E1> x0d; + diff --git a/clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp b/clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp new file mode 100644 index 0000000..00fc0a3 --- /dev/null +++ b/clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +template<typename T> +class X0 { + friend T; +}; + +class Y1 { }; +enum E1 { }; +X0<Y1> x0a; +X0<Y1 *> x0b; +X0<int> x0c; +X0<E1> x0d; + +template<typename T> +class X1 { + friend typename T::type; // expected-error{{no type named 'type' in 'Y1'}} +}; + +struct Y2 { + struct type { }; +}; + +struct Y3 { + typedef int type; +}; + +X1<Y2> x1a; +X1<Y3> x1b; +X1<Y1> x1c; // expected-note{{in instantiation of template class 'X1<Y1>' requested here}} diff --git a/clang/test/CXX/class.access/class.friend/p6.cpp b/clang/test/CXX/class.access/class.friend/p6.cpp new file mode 100644 index 0000000..7f7d909 --- /dev/null +++ b/clang/test/CXX/class.access/class.friend/p6.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f1(); + +struct X { + void f2(); +}; + +struct Y { + friend void ::f1() { } // expected-error{{friend function definition cannot be qualified with '::'}} + friend void X::f2() { } // expected-error{{friend function definition cannot be qualified with 'X::'}} +}; + +void local() { + void f(); + + struct Local { + friend void f() { } // expected-error{{friend function cannot be defined in a local class}} + }; +} diff --git a/clang/test/CXX/class.access/class.protected/p1-cxx11.cpp b/clang/test/CXX/class.access/class.protected/p1-cxx11.cpp new file mode 100644 index 0000000..dc9b20d --- /dev/null +++ b/clang/test/CXX/class.access/class.protected/p1-cxx11.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR12497 +namespace test0 { + class A { + protected: + A() {} + A(const A &) {} + ~A() {} + A &operator=(const A &a) { return *this; } + }; + + class B : public A {}; + + void test() { + B b1; + B b2 = b1; + b1 = b2; + } +} diff --git a/clang/test/CXX/class.access/class.protected/p1.cpp b/clang/test/CXX/class.access/class.protected/p1.cpp new file mode 100644 index 0000000..c9491e1 --- /dev/null +++ b/clang/test/CXX/class.access/class.protected/p1.cpp @@ -0,0 +1,519 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test0 { + class A { + protected: int x; // expected-note 3 {{declared}} \ + // expected-note {{member is declared here}} + static int sx; // expected-note 3 {{declared}} \ + // expected-note {{member is declared here}} + }; + class B : public A { + }; + class C : protected A { // expected-note {{declared}} + }; + class D : private B { // expected-note 3 {{constrained}} + }; + + void test(A &a) { + (void) a.x; // expected-error {{'x' is a protected member}} + (void) a.sx; // expected-error {{'sx' is a protected member}} + } + void test(B &b) { + (void) b.x; // expected-error {{'x' is a protected member}} + (void) b.sx; // expected-error {{'sx' is a protected member}} + } + void test(C &c) { + (void) c.x; // expected-error {{'x' is a protected member}} expected-error {{protected base class}} + (void) c.sx; // expected-error {{'sx' is a protected member}} + } + void test(D &d) { + (void) d.x; // expected-error {{'x' is a private member}} expected-error {{private base class}} + (void) d.sx; // expected-error {{'sx' is a private member}} + } +} + +namespace test1 { + class A { + protected: int x; + static int sx; + static void test(A&); + }; + class B : public A { + static void test(B&); + }; + class C : protected A { + static void test(C&); + }; + class D : private B { + static void test(D&); + }; + + void A::test(A &a) { + (void) a.x; + (void) a.sx; + } + void B::test(B &b) { + (void) b.x; + (void) b.sx; + } + void C::test(C &c) { + (void) c.x; + (void) c.sx; + } + void D::test(D &d) { + (void) d.x; + (void) d.sx; + } +} + +namespace test2 { + class A { + protected: int x; // expected-note 3 {{can only access this member on an object of type}} + static int sx; + static void test(A&); + }; + class B : public A { + static void test(A&); + }; + class C : protected A { + static void test(A&); + }; + class D : private B { + static void test(A&); + }; + + void A::test(A &a) { + (void) a.x; + (void) a.sx; + } + void B::test(A &a) { + (void) a.x; // expected-error {{'x' is a protected member}} + (void) a.sx; + } + void C::test(A &a) { + (void) a.x; // expected-error {{'x' is a protected member}} + (void) a.sx; + } + void D::test(A &a) { + (void) a.x; // expected-error {{'x' is a protected member}} + (void) a.sx; + } +} + +namespace test3 { + class B; + class A { + protected: int x; //expected-note {{declared protected}} // expected-note {{can only access this member on an object of type}} + static int sx; + static void test(B&); + }; + class B : public A { + static void test(B&); + }; + class C : protected A { + static void test(B&); + }; + class D : private B { + static void test(B&); + }; + + void A::test(B &b) { + (void) b.x; + (void) b.sx; + } + void B::test(B &b) { + (void) b.x; + (void) b.sx; + } + void C::test(B &b) { + (void) b.x; // expected-error {{'x' is a protected member}} + (void) b.sx; + } + void D::test(B &b) { + (void) b.x; // expected-error {{'x' is a protected member}} + (void) b.sx; + } +} + +namespace test4 { + class C; + class A { + protected: int x; // expected-note 2{{declared protected here}} expected-note{{member is declared here}} + static int sx; // expected-note 3{{member is declared here}} + static void test(C&); + }; + class B : public A { + static void test(C&); + }; + class C : protected A { // expected-note 4 {{constrained}} expected-note 3 {{declared}} + static void test(C&); + }; + class D : private B { + static void test(C&); + }; + + void A::test(C &c) { + (void) c.x; // expected-error {{'x' is a protected member}} \ + // expected-error {{protected base class}} + (void) c.sx; // expected-error {{'sx' is a protected member}} + } + void B::test(C &c) { + (void) c.x; // expected-error {{'x' is a protected member}} \ + // expected-error {{protected base class}} + (void) c.sx; // expected-error {{'sx' is a protected member}} + } + void C::test(C &c) { + (void) c.x; + (void) c.sx; + } + void D::test(C &c) { + (void) c.x; // expected-error {{'x' is a protected member}} \ + // expected-error {{protected base class}} + (void) c.sx; // expected-error {{'sx' is a protected member}} + } +} + +namespace test5 { + class D; + class A { + protected: int x; // expected-note 3{{member is declared here}} + static int sx; // expected-note 3{{member is declared here}} + static void test(D&); + }; + class B : public A { + static void test(D&); + }; + class C : protected A { + static void test(D&); + }; + class D : private B { // expected-note 9 {{constrained}} + static void test(D&); + }; + + void A::test(D &d) { + (void) d.x; // expected-error {{'x' is a private member}} \ + // expected-error {{cannot cast}} + (void) d.sx; // expected-error {{'sx' is a private member}} + } + void B::test(D &d) { + (void) d.x; // expected-error {{'x' is a private member}} \ + // expected-error {{cannot cast}} + (void) d.sx; // expected-error {{'sx' is a private member}} + } + void C::test(D &d) { + (void) d.x; // expected-error {{'x' is a private member}} \ + // expected-error {{cannot cast}} + (void) d.sx; // expected-error {{'sx' is a private member}} + } + void D::test(D &d) { + (void) d.x; + (void) d.sx; + } +} + +namespace test6 { + class Static {}; + class A { + protected: + void foo(int); // expected-note 3 {{can only access this member on an object of type}} + void foo(long); + static void foo(Static); + + static void test(A&); + }; + class B : public A { + static void test(A&); + }; + class C : protected A { + static void test(A&); + }; + class D : private B { + static void test(A&); + }; + + void A::test(A &a) { + a.foo(10); + a.foo(Static()); + } + void B::test(A &a) { + a.foo(10); // expected-error {{'foo' is a protected member}} + a.foo(Static()); + } + void C::test(A &a) { + a.foo(10); // expected-error {{'foo' is a protected member}} + a.foo(Static()); + } + void D::test(A &a) { + a.foo(10); // expected-error {{'foo' is a protected member}} + a.foo(Static()); + } +} + +namespace test7 { + class Static {}; + class A { + protected: + void foo(int); // expected-note 3 {{must name member using the type of the current context}} + void foo(long); + static void foo(Static); + + static void test(); + }; + class B : public A { + static void test(); + }; + class C : protected A { + static void test(); + }; + class D : private B { + static void test(); + }; + + void A::test() { + void (A::*x)(int) = &A::foo; + void (*sx)(Static) = &A::foo; + } + void B::test() { + void (A::*x)(int) = &A::foo; // expected-error {{'foo' is a protected member}} + void (*sx)(Static) = &A::foo; + } + void C::test() { + void (A::*x)(int) = &A::foo; // expected-error {{'foo' is a protected member}} + void (*sx)(Static) = &A::foo; + } + void D::test() { + void (A::*x)(int) = &A::foo; // expected-error {{'foo' is a protected member}} + void (*sx)(Static) = &A::foo; + } +} + +namespace test8 { + class Static {}; + class A { + protected: + void foo(int); // expected-note 3 {{must name member using the type of the current context}} + void foo(long); + static void foo(Static); + + static void test(); + }; + class B : public A { + static void test(); + }; + class C : protected A { + static void test(); + }; + class D : private B { + static void test(); + }; + void call(void (A::*)(int)); + void calls(void (*)(Static)); + + void A::test() { + call(&A::foo); + calls(&A::foo); + } + void B::test() { + call(&A::foo); // expected-error {{'foo' is a protected member}} + calls(&A::foo); + } + void C::test() { + call(&A::foo); // expected-error {{'foo' is a protected member}} + calls(&A::foo); + } + void D::test() { + call(&A::foo); // expected-error {{'foo' is a protected member}} + calls(&A::foo); + } +} + +namespace test9 { + class A { // expected-note {{member is declared here}} + protected: int foo(); // expected-note 4 {{declared}} expected-note 2 {{can only access this member on an object of type}} expected-note {{member is declared here}} + }; + + class B : public A { // expected-note {{member is declared here}} + friend class D; + }; + + class C : protected B { // expected-note {{declared}} \ + // expected-note 9 {{constrained}} + }; + + class D : public A { + static void test(A &a) { + a.foo(); // expected-error {{'foo' is a protected member}} + a.A::foo(); // expected-error {{'foo' is a protected member}} + a.B::foo(); + a.C::foo(); // expected-error {{'foo' is a protected member}} + } + + static void test(B &b) { + b.foo(); + b.A::foo(); + b.B::foo(); + b.C::foo(); // expected-error {{'foo' is a protected member}} + } + + static void test(C &c) { + c.foo(); // expected-error {{'foo' is a protected member}} \ + // expected-error {{cannot cast}} + c.A::foo(); // expected-error {{'A' is a protected member}} \ + // expected-error {{cannot cast}} + c.B::foo(); // expected-error {{'B' is a protected member}} \ + // expected-error {{cannot cast}} + c.C::foo(); // expected-error {{'foo' is a protected member}} \ + // expected-error {{cannot cast}} + } + + static void test(D &d) { + d.foo(); + d.A::foo(); + d.B::foo(); + d.C::foo(); // expected-error {{'foo' is a protected member}} + } + }; +} + +namespace test10 { + template<typename T> class A { + protected: + int foo(); + int foo() const; + + ~A() { foo(); } + }; + + template class A<int>; +} + +// rdar://problem/8360285: class.protected friendship +namespace test11 { + class A { + protected: + int foo(); + }; + + class B : public A { + friend class C; + }; + + class C { + void test() { + B b; + b.A::foo(); + } + }; +} + +// This friendship is considered because a public member of A would be +// a private member of C. +namespace test12 { + class A { protected: int foo(); }; + class B : public virtual A {}; + class C : private B { friend void test(); }; + class D : private C, public virtual A {}; + + void test() { + D d; + d.A::foo(); + } +} + +// This friendship is not considered because a public member of A is +// inaccessible in C. +namespace test13 { + class A { protected: int foo(); }; // expected-note {{can only access this member on an object of type}} + class B : private virtual A {}; + class C : private B { friend void test(); }; + class D : public virtual A {}; + + void test() { + D d; + d.A::foo(); // expected-error {{protected member}} + } +} + +// PR8058 +namespace test14 { + class A { + protected: + template <class T> void temp(T t); // expected-note {{must name member using the type of the current context}} + + void nontemp(int); // expected-note {{must name member using the type of the current context}} + + template <class T> void ovl_temp(T t); // expected-note {{must name member using the type of the current context}} + void ovl_temp(float); + + void ovl_nontemp(int); // expected-note {{must name member using the type of the current context}} + void ovl_nontemp(float); + + template <class T> void ovl_withtemp(T); + void ovl_withtemp(int); // expected-note {{must name member using the type of the current context}} + }; + + class B : public A { + void use() { + void (A::*ptr)(int); + ptr = &A::temp; // expected-error {{protected member}} + ptr = &A::nontemp; // expected-error {{protected member}} + ptr = &A::ovl_temp; // expected-error {{protected member}} + ptr = &A::ovl_nontemp; // expected-error {{protected member}} + ptr = &A::ovl_withtemp; // expected-error {{protected member}} + } + }; +} + +namespace test15 { + class A { + protected: + A(); // expected-note 2 {{protected constructor can only be used to construct a base class subobject}} + A(const A &); // expected-note {{protected constructor can only be used to construct a base class subobject}} + ~A(); // expected-note 3 {{protected destructor can only be used to destroy a base class subobject}} + }; + + class B : public A { + // The uses here are fine. + B() {} + B(int i) : A() {} + ~B() {} + + // All these uses are bad. + + void test0() { + A a; // expected-error {{protected constructor}} expected-error {{protected destructor}} + } + + A *test1() { + return new A(); // expected-error {{protected constructor}} + } + + void test2(A *a) { + delete a; // expected-error {{protected destructor}} + } + + A test3(A *a) { + return *a; // expected-error {{protected constructor}} + } + + void test4(A *a) { + a->~A(); // expected-error {{protected member}} + } + }; +} + +namespace test16 { + class A { + protected: + ~A(); + }; + + class B : public virtual A { + public: + ~B() {} + }; + + class C : public B { + ~C() {} + }; +} diff --git a/clang/test/CXX/class.access/p4.cpp b/clang/test/CXX/class.access/p4.cpp new file mode 100644 index 0000000..5ad738b --- /dev/null +++ b/clang/test/CXX/class.access/p4.cpp @@ -0,0 +1,510 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s + +// C++0x [class.access]p4: + +// Access control is applied uniformly to all names, whether the +// names are referred to from declarations or expressions. In the +// case of overloaded function names, access control is applied to +// the function selected by overload resolution. + +class Public {} PublicInst; +class Protected {} ProtectedInst; +class Private {} PrivateInst; + +namespace test0 { + class A { + public: + void foo(Public&); + protected: + void foo(Protected&); // expected-note 2 {{declared protected here}} + private: + void foo(Private&); // expected-note 2 {{declared private here}} + }; + + void test(A *op) { + op->foo(PublicInst); + op->foo(ProtectedInst); // expected-error {{'foo' is a protected member}} + op->foo(PrivateInst); // expected-error {{'foo' is a private member}} + + void (A::*a)(Public&) = &A::foo; + void (A::*b)(Protected&) = &A::foo; // expected-error {{'foo' is a protected member}} + void (A::*c)(Private&) = &A::foo; // expected-error {{'foo' is a private member}} + } +} + +// Member operators. +namespace test1 { + class A { + public: + void operator+(Public&); + void operator[](Public&); + void operator()(Public&); + typedef void (*PublicSurrogate)(Public&); + operator PublicSurrogate() const; + protected: + void operator+(Protected&); // expected-note {{declared protected here}} + void operator[](Protected&); // expected-note {{declared protected here}} + void operator()(Protected&); // expected-note {{declared protected here}} + typedef void (*ProtectedSurrogate)(Protected&); + operator ProtectedSurrogate() const; // expected-note {{declared protected here}} + private: + void operator+(Private&); // expected-note {{declared private here}} + void operator[](Private&); // expected-note {{declared private here}} + void operator()(Private&); // expected-note {{declared private here}} + void operator-(); // expected-note {{declared private here}} + typedef void (*PrivateSurrogate)(Private&); + operator PrivateSurrogate() const; // expected-note {{declared private here}} + }; + void operator+(const A &, Public&); + void operator+(const A &, Protected&); + void operator+(const A &, Private&); + void operator-(const A &); + + void test(A &a, Public &pub, Protected &prot, Private &priv) { + a + pub; + a + prot; // expected-error {{'operator+' is a protected member}} + a + priv; // expected-error {{'operator+' is a private member}} + a[pub]; + a[prot]; // expected-error {{'operator[]' is a protected member}} + a[priv]; // expected-error {{'operator[]' is a private member}} + a(pub); + a(prot); // expected-error {{'operator()' is a protected member}} + a(priv); // expected-error {{'operator()' is a private member}} + -a; // expected-error {{'operator-' is a private member}} + + const A &ca = a; + ca + pub; + ca + prot; + ca + priv; + -ca; + // These are all surrogate calls + ca(pub); + ca(prot); // expected-error {{'operator void (*)(class Protected &)' is a protected member}} + ca(priv); // expected-error {{'operator void (*)(class Private &)' is a private member}} + } +} + +// Implicit constructor calls. +namespace test2 { + class A { + private: + A(); // expected-note 3 {{declared private here}} + + static A foo; + }; + + A a; // expected-error {{calling a private constructor}} + A A::foo; // okay + + class B : A { }; // expected-error {{base class 'test2::A' has private default constructor}} + B b; // expected-note{{implicit default constructor}} + + class C : virtual A { + public: + C(); + }; + + class D : C { }; // expected-error {{inherited virtual base class 'test2::A' has private default constructor}} + D d; // expected-note{{implicit default constructor}} +} + +// Implicit destructor calls. +namespace test3 { + class A { + private: + ~A(); // expected-note 2 {{declared private here}} + static A foo; + }; + + A a; // expected-error {{variable of type 'test3::A' has private destructor}} + A A::foo; + + void foo(A param) { // okay + A local; // expected-error {{variable of type 'test3::A' has private destructor}} + } + + template <unsigned N> class Base { ~Base(); }; // expected-note 14 {{declared private here}} + class Base2 : virtual Base<2> { ~Base2(); }; // expected-note 3 {{declared private here}} \ + // expected-error {{base class 'Base<2>' has private destructor}} + class Base3 : virtual Base<3> { public: ~Base3(); }; // expected-error {{base class 'Base<3>' has private destructor}} + + // These don't cause diagnostics because we don't need the destructor. + class Derived0 : Base<0> { ~Derived0(); }; + class Derived1 : Base<1> { }; + + class Derived2 : // expected-error {{inherited virtual base class 'Base<2>' has private destructor}} \ + // expected-error {{inherited virtual base class 'Base<3>' has private destructor}} + Base<0>, // expected-error {{base class 'Base<0>' has private destructor}} + virtual Base<1>, // expected-error {{base class 'Base<1>' has private destructor}} + Base2, // expected-error {{base class 'test3::Base2' has private destructor}} + virtual Base3 + { + ~Derived2() {} + }; + + class Derived3 : // expected-error 2 {{inherited virtual base class 'Base<2>' has private destructor}} \ + // expected-error 2 {{inherited virtual base class 'Base<3>' has private destructor}} \ + // expected-note 2{{implicit default constructor}} + Base<0>, // expected-error 2 {{base class 'Base<0>' has private destructor}} + virtual Base<1>, // expected-error 2 {{base class 'Base<1>' has private destructor}} + Base2, // expected-error 2 {{base class 'test3::Base2' has private destructor}} + virtual Base3 + {}; + Derived3 d3; // expected-note {{implicit default constructor}}\ + // expected-note{{implicit default destructor}}} +} + +// Conversion functions. +namespace test4 { + class Base { + private: + operator Private(); // expected-note 4 {{declared private here}} + public: + operator Public(); // expected-note 2{{member is declared here}} + }; + + class Derived1 : private Base { // expected-note 2 {{declared private here}} \ + // expected-note {{constrained by private inheritance}} + Private test1() { return *this; } // expected-error {{'operator Private' is a private member}} + Public test2() { return *this; } + }; + Private test1(Derived1 &d) { return d; } // expected-error {{'operator Private' is a private member}} \ + // expected-error {{cannot cast 'test4::Derived1' to its private base class}} + Public test2(Derived1 &d) { return d; } // expected-error {{cannot cast 'test4::Derived1' to its private base class}} \ + // expected-error {{'operator Public' is a private member}} + + + class Derived2 : public Base { + Private test1() { return *this; } // expected-error {{'operator Private' is a private member}} + Public test2() { return *this; } + }; + Private test1(Derived2 &d) { return d; } // expected-error {{'operator Private' is a private member}} + Public test2(Derived2 &d) { return d; } + + class Derived3 : private Base { // expected-note {{constrained by private inheritance here}} \ + // expected-note {{declared private here}} + public: + operator Private(); + }; + Private test1(Derived3 &d) { return d; } + Public test2(Derived3 &d) { return d; } // expected-error {{'operator Public' is a private member of 'test4::Base'}} \ + // expected-error {{cannot cast 'test4::Derived3' to its private base class}} + + class Derived4 : public Base { + public: + operator Private(); + }; + Private test1(Derived4 &d) { return d; } + Public test2(Derived4 &d) { return d; } +} + +// Implicit copy assignment operator uses. +namespace test5 { + class A { + void operator=(const A &); // expected-note 2 {{implicitly declared private here}} + }; + + class Test1 { A a; }; // expected-error {{private member}} + void test1() { + Test1 a; + a = Test1(); // expected-note{{implicit default copy}} + } + + class Test2 : A {}; // expected-error {{private member}} + void test2() { + Test2 a; + a = Test2(); // expected-note{{implicit default copy}} + } +} + +// Implicit copy constructor uses. +namespace test6 { + class A { + public: A(); + private: A(const A &); // expected-note 2 {{declared private here}} + }; + + class Test1 { A a; }; // expected-error {{field of type 'test6::A' has private copy constructor}} + void test1(const Test1 &t) { + Test1 a = t; // expected-note{{implicit default copy}} + } + + class Test2 : A {}; // expected-error {{base class 'test6::A' has private copy constructor}} + void test2(const Test2 &t) { + Test2 a = t; // expected-note{{implicit default copy}} + } +} + +// Redeclaration lookups are not accesses. +namespace test7 { + class A { + int private_member; + }; + class B : A { + int foo(int private_member) { + return 0; + } + }; +} + +// Ignored operator new and delete overloads are not +namespace test8 { + typedef __typeof__(sizeof(int)) size_t; + + class A { + void *operator new(size_t s); + void operator delete(void *p); + public: + void *operator new(size_t s, int n); + void operator delete(void *p, int n); + }; + + void test() { + new (2) A(); + } +} + +// Don't silently upgrade forbidden-access paths to private. +namespace test9 { + class A { + public: static int x; // expected-note {{member is declared here}} + }; + class B : private A { // expected-note {{constrained by private inheritance here}} + }; + class C : public B { + static int getX() { return x; } // expected-error {{'x' is a private member of 'test9::A'}} + }; +} + +namespace test10 { + class A { + enum { + value = 10 // expected-note {{declared private here}} + }; + friend class C; + }; + + class B { + enum { + value = A::value // expected-error {{'value' is a private member of 'test10::A'}} + }; + }; + + class C { + enum { + value = A::value + }; + }; +} + +namespace test11 { + class A { + protected: virtual ~A(); + }; + + class B : public A { + ~B(); + }; + + B::~B() {}; +} + +namespace test12 { + class A { + int x; + + void foo() { + class Local { + int foo(A *a) { + return a->x; + } + }; + } + }; +} + +namespace test13 { + struct A { + int x; + unsigned foo() const; + }; + + struct B : protected A { + using A::foo; + using A::x; + }; + + void test() { + A *d; + d->foo(); + (void) d->x; + } +} + +// Destructors for temporaries. +namespace test14 { + class A { + private: ~A(); // expected-note {{declared private here}} + }; + A foo(); + + void test() { + foo(); // expected-error {{temporary of type 'test14::A' has private destructor}} + } + + class X { + ~X(); // expected-note {{declared private here}} + }; + + struct Y1 { + operator X(); + }; + + void g() { + const X &xr = Y1(); // expected-error{{temporary of type 'test14::X' has private destructor}} + } +} + +// PR 7024 +namespace test15 { + template <class T> class A { + private: + int private_foo; // expected-note {{declared private here}} + static int private_sfoo; // expected-note {{declared private here}} + protected: + int protected_foo; // expected-note 3 {{declared protected here}} // expected-note {{can only access this member on an object of type 'test15::B<int>'}} + static int protected_sfoo; // expected-note 3 {{declared protected here}} + + int test1(A<int> &a) { + return a.private_foo; // expected-error {{private member}} + } + + int test2(A<int> &a) { + return a.private_sfoo; // expected-error {{private member}} + } + + int test3(A<int> &a) { + return a.protected_foo; // expected-error {{protected member}} + } + + int test4(A<int> &a) { + return a.protected_sfoo; // expected-error {{protected member}} + } + }; + + template class A<int>; + template class A<long>; // expected-note 4 {{in instantiation}} + + template <class T> class B : public A<T> { + // TODO: These first two accesses can be detected as ill-formed at + // definition time because they're member accesses and A<int> can't + // be a subclass of B<T> for any T. + + int test1(A<int> &a) { + return a.protected_foo; // expected-error 2 {{protected member}} + } + + int test2(A<int> &a) { + return a.protected_sfoo; // expected-error {{protected member}} + } + + int test3(B<int> &b) { + return b.protected_foo; // expected-error {{protected member}} + } + + int test4(B<int> &b) { + return b.protected_sfoo; // expected-error {{protected member}} + } + }; + + template class B<int>; // expected-note {{in instantiation}} + template class B<long>; // expected-note 4 {{in instantiation}} +} + +// PR7281 +namespace test16 { + class A { ~A(); }; // expected-note 2{{declared private here}} + void b() { throw A(); } // expected-error{{temporary of type 'test16::A' has private destructor}} \ + // expected-error{{exception object of type 'test16::A' has private destructor}} +} + +// rdar://problem/8146294 +namespace test17 { + class A { + template <typename T> class Inner { }; // expected-note {{declared private here}} + }; + + A::Inner<int> s; // expected-error {{'Inner' is a private member of 'test17::A'}} +} + +namespace test18 { + template <class T> class A {}; + class B : A<int> { + A<int> member; + }; + + // FIXME: this access to A should be forbidden (because C++ is dumb), + // but LookupResult can't express the necessary information to do + // the check, so we aggressively suppress access control. + class C : B { + 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; // expected-error{{non-friend class member 'Inner' cannot have a qualified name}} + }; + + 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/clang/test/CXX/class.access/p6.cpp b/clang/test/CXX/class.access/p6.cpp new file mode 100644 index 0000000..fbdc87b --- /dev/null +++ b/clang/test/CXX/class.access/p6.cpp @@ -0,0 +1,192 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [class.access]p6: +// All access controls in [class.access] affect the ability to +// access a class member name from a particular scope. For purposes +// of access control, the base-specifiers of a class and the +// definitions of class members that appear outside of the class +// definition are considered to be within the scope of that +// class. In particular, access controls apply as usual to member +// names accessed as part of a function return type, even though it +// is not possible to determine the access privileges of that use +// without first parsing the rest of the function +// declarator. Similarly, access control for implicit calls to the +// constructors, the conversion functions, or the destructor called +// to create and destroy a static data member is performed as if +// these calls appeared in the scope of the member's class. + +struct Public {}; struct Protected {}; struct Private {}; + +namespace test0 { + class A { + typedef int type; // expected-note {{declared private here}} + type foo(); + }; + + A::type foo() { } // expected-error {{'type' is a private member}} + A::type A::foo() { } +} + +// conversion decls +namespace test1 { + class A { + public: + A(); + operator Public (); + A(Public); + protected: + operator Protected (); // expected-note {{declared protected here}} + A(Protected); // expected-note {{declared protected here}} + private: + operator Private (); // expected-note {{declared private here}} + A(Private); // expected-note {{declared private here}} + }; + + void test() { + A a; + Public pub = a; + Protected prot = a; // expected-error {{'operator Protected' is a protected member}} + Private priv = a; // expected-error {{'operator Private' is a private member}} + A apub = pub; + A aprot = prot; // expected-error {{protected constructor}} + A apriv = priv; // expected-error {{private constructor}} + } +} + +// PR6967 +namespace test2 { + class A { + public: + template <class T> static void set(T &t, typename T::type v) { + t.value = v; + } + template <class T> static typename T::type get(const T &t) { + return t.value; + } + }; + + class B { + friend class A; + + private: + typedef int type; + type value; + }; + + int test() { + B b; + A::set(b, 0); + return A::get(b); + } +} + +namespace test3 { + class Green {}; class Blue {}; + + // We have to wrap this in a class because a partial specialization + // isn't actually in the context of the template. + struct Outer { + template <class T, class Nat> class A { + }; + }; + + template <class T> class Outer::A<T, typename T::nature> { + public: + static void foo(); + }; + + class B { + private: typedef Green nature; + friend class Outer; + }; + + void test() { + Outer::A<B, Green>::foo(); + Outer::A<B, Blue>::foo(); // expected-error {{no member named 'foo'}} + } +} + +namespace test4 { + template <class T> class A { + private: typedef int type; + template <class U> friend void foo(U &, typename U::type); + }; + + template <class U> void foo(U &, typename U::type) {} + + void test() { + A<int> a; + foo(a, 0); + } +} + +// PR7644 +namespace test5 { + class A { + enum Enum { E0, E1, E2 }; // expected-note 4 {{declared private here}} + template <Enum> void foo(); + template <Enum> class bar; + }; + + template <A::Enum en> void A::foo() {} + template <A::Enum en> class A::bar {}; + + template <A::Enum en> void foo() {} // expected-error {{'Enum' is a private member of 'test5::A'}} + template <A::Enum en> class bar {}; // expected-error {{'Enum' is a private member of 'test5::A'}} + + class B { + template <A::Enum en> void foo() {} // expected-error {{'Enum' is a private member of 'test5::A'}} + 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)]); + } +} + +// rdar://problem/10155256 +namespace test8 { + class A { + typedef void* (A::*UnspecifiedBoolType)() const; + operator UnspecifiedBoolType() const; // expected-note {{implicitly declared private here}} + }; + + void test(A &a) { + if (a) return; // expected-error {{'operator void *(class test8::A::*)(void) const' is a private member of 'test8::A'}} + } +} + +namespace test9 { + class A { + operator char*() const; // expected-note {{implicitly declared private here}} + }; + + void test(A &a) { + delete a; // expected-error {{'operator char *' is a private member of 'test9::A'}} + } +} diff --git a/clang/test/CXX/class.derived/class.abstract/p4.cpp b/clang/test/CXX/class.derived/class.abstract/p4.cpp new file mode 100644 index 0000000..b04de21 --- /dev/null +++ b/clang/test/CXX/class.derived/class.abstract/p4.cpp @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR6631 { + struct A { + virtual void f() = 0; + }; + + struct B : virtual A { }; + + struct C : virtual A { + virtual void f(); + }; + + struct D : public B, public C { + virtual void f(); + }; + + void f() { + (void)new D; // okay + } +} + +// Check cases where we have a virtual function that is pure in one +// subobject but not pure in another subobject. +namespace PartlyPure { + struct A { + virtual void f() = 0; // expected-note{{unimplemented pure virtual method}} + }; + + struct B : A { + virtual void f(); + }; + + struct C : virtual A { }; + + struct D : B, C { }; + + void f() { + (void) new D; // expected-error{{abstract class}} + } +} + +namespace NonPureAlongOnePath { + struct A { + virtual void f() = 0; + }; + + struct B : virtual A { + virtual void f(); + }; + + struct C : virtual A { }; + + struct D : B, C { }; + + void f() { + (void) new D; // okay + } +} + +namespace NonPureAlongOnePath2 { + struct Aprime { + virtual void f() = 0; + }; + + struct A : Aprime { + }; + + struct B : virtual A { + virtual void f(); + }; + + struct C : virtual A { }; + + struct D : B, C { }; + + void f() { + (void) new D; // okay + } +} diff --git a/clang/test/CXX/class.derived/class.abstract/p5.cpp b/clang/test/CXX/class.derived/class.abstract/p5.cpp new file mode 100644 index 0000000..cdff931 --- /dev/null +++ b/clang/test/CXX/class.derived/class.abstract/p5.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A { + virtual void f() = 0; // expected-note{{unimplemented pure virtual method}} +}; + +struct B : A { + virtual void f(); +}; + +struct C : B { + virtual void f() = 0; // expected-note 2{{unimplemented pure virtual method}} +}; + +struct D : C { +}; + +void test() { + (void)new A; // expected-error{{abstract class}} + (void)new B; + (void)new C; // expected-error{{abstract class}} + (void)new D; // expected-error{{abstract class}} +} diff --git a/clang/test/CXX/class.derived/class.member.lookup/p6.cpp b/clang/test/CXX/class.derived/class.member.lookup/p6.cpp new file mode 100644 index 0000000..7239881 --- /dev/null +++ b/clang/test/CXX/class.derived/class.member.lookup/p6.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class V { +public: + int f(); + int x; +}; + +class W { +public: + int g(); // expected-note{{member found by ambiguous name lookup}} + int y; // expected-note{{member found by ambiguous name lookup}} +}; + +class B : public virtual V, public W +{ +public: + int f(); + int x; + int g(); // expected-note{{member found by ambiguous name lookup}} + int y; // expected-note{{member found by ambiguous name lookup}} +}; + +class C : public virtual V, public W { }; + +class D : public B, public C { void glorp(); }; + +void D::glorp() { + x++; + f(); + y++; // expected-error{{member 'y' found in multiple base classes of different types}} + g(); // expected-error{{member 'g' found in multiple base classes of different types}} +} + +// PR6462 +struct BaseIO { BaseIO* rdbuf() { return 0; } }; +struct Pcommon : virtual BaseIO { int rdbuf() { return 0; } }; +struct P : virtual BaseIO, Pcommon {}; + +void f() { P p; p.rdbuf(); } diff --git a/clang/test/CXX/class.derived/class.member.lookup/p8.cpp b/clang/test/CXX/class.derived/class.member.lookup/p8.cpp new file mode 100644 index 0000000..4d4acc3 --- /dev/null +++ b/clang/test/CXX/class.derived/class.member.lookup/p8.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// FIXME: Access control checks + +namespace PR5820 { + // also <rdar://problem/7535045> + struct Base { + void Foo(); + int Member; + }; + + struct D1 : public Base {}; + struct D2 : public Base {}; + + struct Derived : public D1, public D2 { + void Inner(); + }; + + void Test() { + Derived d; + d.D1::Foo(); + d.D1::Member = 17; + } + + void Derived::Inner() { + D1::Foo(); + D1::Member = 42; + this->D1::Foo(); + this->D1::Member = 42; + } +} + +template<typename T> +struct BaseT { + void Foo(); // expected-note{{found by ambiguous name lookup}} + int Member; +}; + +template<typename T> struct Derived1T : BaseT<T> { }; +template<typename T> struct Derived2T : BaseT<T> { }; + +template<typename T> +struct DerivedT : public Derived1T<T>, public Derived2T<T> { + void Inner(); +}; + +template<typename T> +void DerivedT<T>::Inner() { + Derived1T<T>::Foo(); + Derived2T<T>::Member = 42; + this->Derived1T<T>::Foo(); + this->Derived2T<T>::Member = 42; + this->Foo(); // expected-error{{non-static member 'Foo' found in multiple base-class subobjects of type 'BaseT<int>'}} +} + +template<typename T> +void Test(DerivedT<T> d) { + d.template Derived1T<T>::Foo(); + d.template Derived2T<T>::Member = 17; + d.Inner(); // expected-note{{in instantiation}} +} + +template void Test(DerivedT<int>); diff --git a/clang/test/CXX/class.derived/class.member.lookup/p9.cpp b/clang/test/CXX/class.derived/class.member.lookup/p9.cpp new file mode 100644 index 0000000..ba7bd21 --- /dev/null +++ b/clang/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/clang/test/CXX/class.derived/class.virtual/p12.cpp b/clang/test/CXX/class.derived/class.virtual/p12.cpp new file mode 100644 index 0000000..208a0d1 --- /dev/null +++ b/clang/test/CXX/class.derived/class.virtual/p12.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -ast-print %s | FileCheck %s + +// CHECK: test12_A::foo() +struct test12_A { + virtual void foo(); + + void bar() { + test12_A::foo(); + } +}; + +// CHECK: xp->test24_B::wibble() +struct test24_B { + virtual void wibble(); +}; + +void foo(test24_B *xp) { + xp->test24_B::wibble(); +} diff --git a/clang/test/CXX/class.derived/class.virtual/p2.cpp b/clang/test/CXX/class.derived/class.virtual/p2.cpp new file mode 100644 index 0000000..64d93c8 --- /dev/null +++ b/clang/test/CXX/class.derived/class.virtual/p2.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A { + virtual void f() = 0; // expected-note 2{{overridden virtual function}} +}; + +struct Aprime : virtual A { + virtual void f(); +}; + +struct B : Aprime { + virtual void f(); // expected-note 3{{final overrider of 'A::f'}} +}; + +struct C : virtual A { + virtual void f(); // expected-note{{final overrider of 'A::f'}} +}; + +struct D : B, C { }; // expected-error{{virtual function 'A::f' has more than one final overrider in 'D'}} + +struct B2 : B { }; + +struct E : B, B2 { }; //expected-error{{virtual function 'A::f' has more than one final overrider in 'E'}} + +struct F : B, B2 { + virtual void f(); // okay +}; + +struct G : F { }; // okay + +struct H : G, A { }; // okay + +namespace MultipleSubobjects { + struct A { virtual void f(); }; + struct B : A { virtual void f(); }; + struct C : A { virtual void f(); }; + struct D : B, C { }; // okay +} diff --git a/clang/test/CXX/class.derived/class.virtual/p3-0x.cpp b/clang/test/CXX/class.derived/class.virtual/p3-0x.cpp new file mode 100644 index 0000000..c4a401b --- /dev/null +++ b/clang/test/CXX/class.derived/class.virtual/p3-0x.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -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/clang/test/CXX/class.derived/p1.cpp b/clang/test/CXX/class.derived/p1.cpp new file mode 100644 index 0000000..dc5cb2b --- /dev/null +++ b/clang/test/CXX/class.derived/p1.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++11 + +// base-clause: +// : base-specifier-list +// base-specifier-list: +// base-specifier ...[opt] +// base-specifier-list , base-specifier ...[opt] +// base-specifier: +// attribute-specifier-seq[opt] base-type-specifier +// attribute-specifier-seq[opt] virtual access-specifier[opt] base-type-specifier +// attribute-specifier-seq[opt] access-specifier virtual[opt] base-type-specifier +// class-or-decltype: +// nested-name-specifier[opt] class-name +// decltype-specifier +// base-type-specifier: +// class-or-decltype +// access-specifier: +// private +// protected +// public + +namespace PR11216 { + struct Base { }; + struct Derived : decltype(Base()) { }; + + int func(); + struct Derived2 : decltype(func()) { }; // expected-error {{base specifier must name a class}} + + template<typename T> + struct Derived3 : decltype(T().foo()) { }; + struct Foo { Base foo(); }; + Derived3<Foo> d; + + struct Derived4 : :: decltype(Base()) { }; // expected-error {{unexpected namespace scope prior to decltype}} + + struct Derived5 : PR11216:: decltype(Base()) { }; // expected-error {{unexpected namespace scope prior to decltype}} + + template<typename T> + struct Derived6 : typename T::foo { }; // expected-error {{'typename' is redundant; base classes are implicitly types}} +} diff --git a/clang/test/CXX/class.derived/p2.cpp b/clang/test/CXX/class.derived/p2.cpp new file mode 100644 index 0000000..7ef53d3 --- /dev/null +++ b/clang/test/CXX/class.derived/p2.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify + +// "During the lookup for a base class name, non-type names are ignored" +namespace PR5840 { + struct Base {}; + int Base = 10; + struct Derived : Base {}; +} diff --git a/clang/test/CXX/class/class.base/class.base.init/p5-0x.cpp b/clang/test/CXX/class/class.base/class.base.init/p5-0x.cpp new file mode 100644 index 0000000..e9aa6da --- /dev/null +++ b/clang/test/CXX/class/class.base/class.base.init/p5-0x.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// [class.base.init]p5 +// A ctor-initializer may initialize a variant member of the constructor’s +// class. If a ctor-initializer specifies more than one mem-initializer for the +// same member or for the same base class, the ctor-initializer is ill-formed. + +union E { + int a; + int b; + E() : a(1), // expected-note{{previous initialization is here}} + b(2) { // expected-error{{initializing multiple members of union}} + } +}; + +union F { + struct { + int a; + int b; + }; + int c; + F() : a(1), // expected-note{{previous initialization is here}} + b(2), + c(3) { // expected-error{{initializing multiple members of union}} + } +}; diff --git a/clang/test/CXX/class/class.bit/p2.cpp b/clang/test/CXX/class/class.bit/p2.cpp new file mode 100644 index 0000000..7962330 --- /dev/null +++ b/clang/test/CXX/class/class.bit/p2.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct A { +private: + int : 0; +}; + +A a = { }; +A a2 = { 1 }; // expected-error{{excess elements in struct initializer}} + +struct B { + const int : 0; +}; + +B b; + +void testB() { + B b2(b); + B b3(static_cast<B&&>(b2)); + b = b; + b = static_cast<B&&>(b); +} diff --git a/clang/test/CXX/class/class.friend/p1-ambiguous.cpp b/clang/test/CXX/class/class.friend/p1-ambiguous.cpp new file mode 100644 index 0000000..a9dca4f --- /dev/null +++ b/clang/test/CXX/class/class.friend/p1-ambiguous.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Make sure that friend declarations don't introduce ambiguous +// declarations. + +// Test case courtesy of Shantonu Sen. +// Bug 4784. + +class foo; + +extern "C" { + int c_func(foo *a); +}; +int cpp_func(foo *a); + +class foo { +public: + friend int c_func(foo *a); + friend int cpp_func(foo *a); + int caller(); +private: + int x; +}; + +int c_func(foo *a) { + return a->x; +} + +int cpp_func(foo *a) { + return a->x; +} + +int foo::caller() { + c_func(this); + cpp_func(this); + return 0; +} diff --git a/clang/test/CXX/class/class.friend/p1-cxx11.cpp b/clang/test/CXX/class/class.friend/p1-cxx11.cpp new file mode 100644 index 0000000..235f295 --- /dev/null +++ b/clang/test/CXX/class/class.friend/p1-cxx11.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +class A { + class AInner { + }; + + void a_member(); + friend void A::a_member(); // ok in c++11, ill-formed in c++98 + friend void a_member(); // ok in both, refers to non-member + friend class A::AInner; // ok in c++11, extension in c++98 + friend class AInner; // ok in both, refers to non-member +}; diff --git a/clang/test/CXX/class/class.friend/p1.cpp b/clang/test/CXX/class/class.friend/p1.cpp new file mode 100644 index 0000000..07b3a10 --- /dev/null +++ b/clang/test/CXX/class/class.friend/p1.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct Outer { + struct Inner { + int intfield; + }; +}; + +struct Base { + void base_member(); + + typedef int Int; + Int typedeffed_member(); +}; + +struct Derived : public Base { +}; + +int myglobal; + +void global_function(); +extern "C" { + void global_c_function(); +} + +class A { + class AInner { + }; + + friend class PreDeclared; + friend class Outer::Inner; + friend int Outer::Inner::intfield; // expected-error {{friends can only be classes or functions}} + friend int Outer::Inner::missing_field; //expected-error {{friends can only be classes or functions}} + friend int myoperation(float); // okay + friend int myglobal; // expected-error {{friends can only be classes or functions}} + + friend void global_function(); + friend void global_c_function(); + + friend class UndeclaredSoFar; + UndeclaredSoFar x; // expected-error {{unknown type name 'UndeclaredSoFar'}} + + void a_member(); + friend void A::a_member(); // expected-error {{friends cannot be members of the declaring class}} + friend void a_member(); // okay (because we ignore class scopes when looking up friends) + friend class A::AInner; // this is okay as an extension + friend class AInner; // okay, refers to ::AInner + + friend void Derived::missing_member(); // expected-error {{no function named 'missing_member' with type 'void ()' was found in the specified scope}} + + friend void Derived::base_member(); // expected-error {{no function named 'base_member' with type 'void ()' was found in the specified scope}} + + friend int Base::typedeffed_member(); // okay: should look through typedef + + // These test that the friend is properly not being treated as a + // member function. + 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}} \ + // expected-error{{non-member function cannot have 'const' qualifier}} + + typedef void ftypedef(); + friend ftypedef typedeffed_function; // okay (because it's not declared as a member) + + class facet; + friend class facet; // should not assert + class facet {}; +}; + +A::UndeclaredSoFar y; // expected-error {{no type named 'UndeclaredSoFar' in 'A'}} + +class PreDeclared; + +int myoperation(float f) { + return (int) f; +} diff --git a/clang/test/CXX/class/class.friend/p2.cpp b/clang/test/CXX/class/class.friend/p2.cpp new file mode 100644 index 0000000..fb3cd19 --- /dev/null +++ b/clang/test/CXX/class/class.friend/p2.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct B0; + +class A { + friend class B {}; // expected-error {{cannot define a type in a friend declaration}} + friend int; // expected-warning {{non-class friend type 'int' is a C++11 extension}} + friend B0; // expected-warning {{specify 'struct' to befriend 'B0'}} + friend class C; // okay +}; diff --git a/clang/test/CXX/class/class.friend/p6.cpp b/clang/test/CXX/class/class.friend/p6.cpp new file mode 100644 index 0000000..7d7a064 --- /dev/null +++ b/clang/test/CXX/class/class.friend/p6.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -Wc++11-compat -verify %s + +class A { + friend static class B; // expected-error {{'static' is invalid in friend declarations}} + friend extern class C; // expected-error {{'extern' is invalid in friend declarations}} + friend auto class D; // expected-warning {{incompatible with C++11}} expected-error {{'auto' is invalid in friend declarations}} + friend register class E; // expected-error {{'register' is invalid in friend declarations}} + friend mutable class F; // expected-error {{'mutable' is invalid in friend declarations}} + friend typedef class G; // expected-error {{'typedef' is invalid in friend declarations}} +}; diff --git a/clang/test/CXX/class/class.local/p1-0x.cpp b/clang/test/CXX/class/class.local/p1-0x.cpp new file mode 100644 index 0000000..49125f5 --- /dev/null +++ b/clang/test/CXX/class/class.local/p1-0x.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +void f() { + int x = 3; // expected-note{{'x' declared here}} + const int c = 2; + struct C { + int& x2 = x; // expected-error{{reference to local variable 'x' declared in enclosing function 'f'}} + int cc = c; + }; + (void)[]() mutable { + int x = 3; // expected-note{{'x' declared here}} + struct C { + int& x2 = x; // expected-error{{reference to local variable 'x' declared in enclosing lambda expression}} + }; + }; + C(); +} + diff --git a/clang/test/CXX/class/class.local/p1.cpp b/clang/test/CXX/class/class.local/p1.cpp new file mode 100644 index 0000000..62ade5c --- /dev/null +++ b/clang/test/CXX/class/class.local/p1.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int x; +void f() +{ + static int s; + int x; // expected-note{{'x' declared here}} + extern int g(); + + struct local { + int g() { return x; } // expected-error{{reference to local variable 'x' declared in enclosing function 'f'}} + int h() { return s; } + int k() { return :: x; } + int l() { return g(); } + }; +} + +local* p = 0; // expected-error{{unknown type name 'local'}} diff --git a/clang/test/CXX/class/class.local/p2.cpp b/clang/test/CXX/class/class.local/p2.cpp new file mode 100644 index 0000000..db4c90f --- /dev/null +++ b/clang/test/CXX/class/class.local/p2.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A { }; + +void f() { + struct B : private A {}; // expected-note{{declared private here}} + + B b; + + A *a = &b; // expected-error{{cannot cast 'B' to its private base class 'A'}} +} diff --git a/clang/test/CXX/class/class.local/p3.cpp b/clang/test/CXX/class/class.local/p3.cpp new file mode 100644 index 0000000..3753790 --- /dev/null +++ b/clang/test/CXX/class/class.local/p3.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f1() { + struct X { + struct Y; + }; + + struct X::Y { + void f() {} + }; +} + +void f2() { + struct X { + struct Y; + + struct Y { + void f() {} + }; + }; +} + +// A class nested within a local class is a local class. +void f3(int a) { // expected-note{{'a' declared here}} + struct X { + struct Y { + int f() { return a; } // expected-error{{reference to local variable 'a' declared in enclosing function 'f3'}} + }; + }; +} diff --git a/clang/test/CXX/class/class.local/p4.cpp b/clang/test/CXX/class/class.local/p4.cpp new file mode 100644 index 0000000..d780744 --- /dev/null +++ b/clang/test/CXX/class/class.local/p4.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f() { + struct X { + static int a; // expected-error {{static data member 'a' not allowed in local class 'X'}} + int b; + + static void f() { } + }; +} diff --git a/clang/test/CXX/class/class.mem/p1.cpp b/clang/test/CXX/class/class.mem/p1.cpp new file mode 100644 index 0000000..a41f1db --- /dev/null +++ b/clang/test/CXX/class/class.mem/p1.cpp @@ -0,0 +1,91 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct S +{ + static int v1; // expected-note{{previous declaration is here}} + int v1; //expected-error{{duplicate member 'v1'}} + int v; //expected-note 2{{previous definition is here}} \ + // expected-note{{previous declaration is here}} + static int v; //expected-error{{redefinition of 'v' as different kind of symbol}} + int v; //expected-error{{duplicate member 'v'}} + static int v; //expected-error{{redefinition of 'v' as different kind of symbol}} + enum EnumT { E = 10 }; + friend struct M; + struct X; //expected-note{{forward declaration of 'S::X'}} + friend struct X; +}; + +S::EnumT Evar = S::E; // ok +S::EnumT Evar2 = EnumT(); //expected-error{{use of undeclared identifier 'EnumT'}} +S::M m; //expected-error{{no type named 'M' in 'S'}} +S::X x; //expected-error{{variable has incomplete type 'S::X'}} + + +struct S2 +{ + static int v2; // expected-note{{previous declaration is here}} + static int v2; //expected-error{{duplicate member 'v2'}} +}; + +struct S3 +{ + static int v3; + struct S4 + { + static int v3; + }; +}; + +struct S4 +{ + static int v4; +}; + +int S4::v4; //expected-note{{previous definition is here}} +int S4::v4; //expected-error{{redefinition of 'v4'}} + +struct S5 +{ + static int v5; //expected-note{{previous definition is here}} + void v5() { } //expected-error{{redefinition of 'v5' as different kind of symbol}} + + void v6() { } //expected-note{{previous definition is here}} + static int v6; //expected-error{{redefinition of 'v6' as different kind of symbol}} + + void v7() { } + void v7(int) { } //expected-note{{previous definition is here}} + static int v7; //expected-error{{redefinition of 'v7' as different kind of symbol}} + + void v8(); + int v8(int); //expected-note{{previous declaration is here}} + int v8; //expected-error{{duplicate member 'v8'}} + + +}; + +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/clang/test/CXX/class/class.mem/p13.cpp b/clang/test/CXX/class/class.mem/p13.cpp new file mode 100644 index 0000000..8488584 --- /dev/null +++ b/clang/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/clang/test/CXX/class/class.mem/p14.cpp b/clang/test/CXX/class/class.mem/p14.cpp new file mode 100644 index 0000000..72b232e --- /dev/null +++ b/clang/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/clang/test/CXX/class/class.mem/p1b.cpp b/clang/test/CXX/class/class.mem/p1b.cpp new file mode 100644 index 0000000..3e8c985 --- /dev/null +++ b/clang/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); + + // CHECK: 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/clang/test/CXX/class/class.mem/p2.cpp b/clang/test/CXX/class/class.mem/p2.cpp new file mode 100644 index 0000000..4aa4a5c --- /dev/null +++ b/clang/test/CXX/class/class.mem/p2.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// C++11 [class.mem]p2: +// A class is considered a completely-defined object type (or +// complete type) at the closing } of the class-specifier. Within +// the class member-specification, the class is regarded as complete +// within function bodies, default arguments, +// exception-specifications, and brace-or-equal-initializers for +// non-static data members (including such things in nested classes). +// Otherwise it is regarded as incomplete within its own class +// member-specification. + +namespace test0 { + struct A { // expected-note {{definition of 'test0::A' is not complete until the closing '}'}} + A x; // expected-error {{field has incomplete type 'test0::A'}} + }; +} + +namespace test1 { + template <class T> struct A { + A<int> x; // expected-error {{implicit instantiation of template 'test1::A<int>' within its own definition}} + }; +} + +namespace test2 { + template <class T> struct A; + template <> struct A<int> {}; + template <class T> struct A { + A<int> x; + }; +} + +namespace test3 { + struct A { + struct B { + void f() throw(A); + void g() throw(B); + }; + + void f() throw(A); + void g() throw(B); + }; + + template<typename T> + struct A2 { + struct B { + void f1() throw(A2); + void f2() throw(A2<T>); + void g() throw(B); + }; + + void f1() throw(A2); + void f2() throw(A2<T>); + void g() throw(B); + }; + + template struct A2<int>; +} diff --git a/clang/test/CXX/class/class.mem/p5-0x.cpp b/clang/test/CXX/class/class.mem/p5-0x.cpp new file mode 100644 index 0000000..6061c4c --- /dev/null +++ b/clang/test/CXX/class/class.mem/p5-0x.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +int f(); + +struct S +{ + int a = f(); // ok + int b = g(); // expected-error {{use of undeclared identifier 'g'}} +}; diff --git a/clang/test/CXX/class/class.mem/p8-0x.cpp b/clang/test/CXX/class/class.mem/p8-0x.cpp new file mode 100644 index 0000000..d2c3dc3 --- /dev/null +++ b/clang/test/CXX/class/class.mem/p8-0x.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +struct Base1 { + virtual void g(); +}; + +struct A : Base1 { + 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 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/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp b/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp new file mode 100644 index 0000000..9116e71 --- /dev/null +++ b/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp @@ -0,0 +1,98 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// [class.mfct.non-static]p3: +// When an id-expression (5.1) that is not part of a class member +// access syntax (5.2.5) and not used to form a pointer to member +// (5.3.1) is used in the body of a non-static member function of +// class X, if name lookup (3.4.1) resolves the name in the +// id-expression to a non-static non-type member of some class C, +// the id-expression is transformed into a class member access +// expression (5.2.5) using (*this) (9.3.2) as the +// postfix-expression to the left of the . operator. [ Note: if C is +// not X or a base class of X, the class member access expression is +// ill-formed. --end note] Similarly during name lookup, when an +// unqualified-id (5.1) used in the definition of a member function +// for class X resolves to a static member, an enumerator or a +// nested type of class X or of a base class of X, the +// unqualified-id is transformed into a qualified-id (5.1) in which +// the nested-name-specifier names the class of the member function. + +namespace test0 { + class A { + int data_member; + int instance_method(); + static int static_method(); + + bool test() { + return data_member + instance_method() < static_method(); + } + }; +} + +namespace test1 { + struct Opaque1 {}; struct Opaque2 {}; struct Opaque3 {}; + + struct A { + void foo(Opaque1); // expected-note {{candidate}} + void foo(Opaque2); // expected-note {{candidate}} + }; + + struct B : A { + void test(); + }; + + struct C1 : A { }; + struct C2 : B { }; + + void B::test() { + A::foo(Opaque1()); + A::foo(Opaque2()); + A::foo(Opaque3()); // expected-error {{no matching member function}} + + C1::foo(Opaque1()); // expected-error {{call to non-static member function without an object argument}} + C2::foo(Opaque1()); // expected-error {{call to non-static member function without an object argument}} + } +} + +namespace test2 { + struct Unrelated { + void foo(); + }; + + template <class T> struct B; + template <class T> struct C; + + template <class T> struct A { + void foo(); + + void test0() { + Unrelated::foo(); // expected-error {{call to non-static member function without an object argument}} + } + + void test1() { + B<T>::foo(); + } + + static void test2() { + B<T>::foo(); // expected-error {{call to non-static member function without an object argument}} + } + + void test3() { + C<T>::foo(); // expected-error {{no member named 'foo'}} + } + }; + + template <class T> struct B : A<T> { + }; + + template <class T> struct C { + }; + + int test() { + A<int> a; + a.test0(); // no instantiation note here, decl is ill-formed + a.test1(); + a.test2(); // expected-note {{in instantiation}} + a.test3(); // expected-note {{in instantiation}} + } +} diff --git a/clang/test/CXX/class/class.nest/p1-cxx0x.cpp b/clang/test/CXX/class/class.nest/p1-cxx0x.cpp new file mode 100644 index 0000000..b7a1a48 --- /dev/null +++ b/clang/test/CXX/class/class.nest/p1-cxx0x.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -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/clang/test/CXX/class/class.nest/p1.cpp b/clang/test/CXX/class/class.nest/p1.cpp new file mode 100644 index 0000000..b0341da --- /dev/null +++ b/clang/test/CXX/class/class.nest/p1.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class Outer { + int x; + static int sx; + int f(); + + // C++11 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 non-static 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/clang/test/CXX/class/class.nest/p3.cpp b/clang/test/CXX/class/class.nest/p3.cpp new file mode 100644 index 0000000..c4c4ca7 --- /dev/null +++ b/clang/test/CXX/class/class.nest/p3.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [class.nest] p3: +// If class X is defined in a namespace scope, a nested class Y may be +// declared in class X and later defined in the definition of class X or be +// later defined in a namespace scope enclosing the definition of class X. + +namespace example { + class E { + class I1; + class I2; + class I1 { }; + }; + class E::I2 { }; +} + +// Don't insert out-of-line inner class definitions into the namespace scope. +namespace PR6107 { + struct S1 { }; + struct S2 { + struct S1; + }; + struct S2::S1 { }; + S1 s1; +} diff --git a/clang/test/CXX/class/class.nested.type/p1.cpp b/clang/test/CXX/class/class.nested.type/p1.cpp new file mode 100644 index 0000000..4a04a44 --- /dev/null +++ b/clang/test/CXX/class/class.nested.type/p1.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class X { +public: + typedef int I; + class Y { }; + I a; +}; + +I b; // expected-error{{unknown type name 'I'}} +Y c; // expected-error{{unknown type name 'Y'}} +X::Y d; +X::I e; diff --git a/clang/test/CXX/class/class.static/class.static.data/p3.cpp b/clang/test/CXX/class/class.static/class.static.data/p3.cpp new file mode 100644 index 0000000..117997e --- /dev/null +++ b/clang/test/CXX/class/class.static/class.static.data/p3.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct NonLit { // expected-note 3{{no constexpr constructors}} + NonLit(); +}; + +struct S { + static constexpr int a = 0; + static constexpr int b; // expected-error {{declaration of constexpr static data member 'b' requires an initializer}} + + static constexpr int c = 0; + static const int d; + static const int d2 = 0; + + static constexpr double e = 0.0; // ok + static const double f = 0.0; // expected-warning {{extension}} expected-note {{use 'constexpr' specifier}} + static char *const g = 0; // expected-error {{requires 'constexpr' specifier}} + static const NonLit h = NonLit(); // expected-error {{must be initialized out of line}} +}; + +constexpr int S::a; +constexpr int S::b = 0; + +const int S::c; +constexpr int S::d = 0; +constexpr int S::d2; + +template<typename T> +struct U { + static constexpr int a = 0; + static constexpr int b; // expected-error {{declaration of constexpr static data member 'b' requires an initializer}} + static constexpr NonLit h = NonLit(); // expected-error {{cannot have non-literal type 'const NonLit'}} + static constexpr T c = T(); // expected-error {{cannot have non-literal type}} + static const T d; +}; + +template<typename T> constexpr T U<T>::d = T(); // expected-error {{non-literal type 'const NonLit'}} + +U<int> u1; +U<NonLit> u2; // expected-note {{here}} + +static_assert(U<int>::a == 0, ""); + +constexpr int outofline = (U<NonLit>::d, 0); // expected-note {{here}} expected-warning {{unused}} diff --git a/clang/test/CXX/class/class.static/class.static.data/p4.cpp b/clang/test/CXX/class/class.static/class.static.data/p4.cpp new file mode 100644 index 0000000..2b1eca7 --- /dev/null +++ b/clang/test/CXX/class/class.static/class.static.data/p4.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct InClassInitializerOnly { + static const int i = 0; +}; +int const InClassInitializerOnly::i; + +struct OutOfClassInitializerOnly { + static const int i; +}; +int const OutOfClassInitializerOnly::i = 0; + +struct InClassInitializerAndOutOfClassCopyInitializer { + static const int i = 0; // expected-note{{previous definition is here}} +}; +int const InClassInitializerAndOutOfClassCopyInitializer::i = 0; // expected-error{{redefinition of 'i'}} + +struct InClassInitializerAndOutOfClassDirectInitializer { + static const int i = 0; // expected-note{{previous definition is here}} +}; +int const InClassInitializerAndOutOfClassDirectInitializer::i(0); // expected-error{{redefinition of 'i'}} + + + +int main() { } + diff --git a/clang/test/CXX/class/class.union/p1.cpp b/clang/test/CXX/class/class.union/p1.cpp new file mode 100644 index 0000000..f344ae5 --- /dev/null +++ b/clang/test/CXX/class/class.union/p1.cpp @@ -0,0 +1,125 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void abort() __attribute__((noreturn)); + +class Okay { + int a_; +}; + +class Virtual { + virtual void foo() { abort(); } // expected-note 4 {{because type 'Virtual' has a virtual member function}} +}; + +class VirtualBase : virtual Okay { // expected-note 4 {{because type 'VirtualBase' has a virtual base class}} +}; + +class Ctor { + Ctor() { abort(); } // expected-note 4 {{because type 'Ctor' has a user-declared constructor}} +}; +class Ctor2 { + Ctor2(); // expected-note 3 {{because type 'Ctor2' has a user-declared constructor}} +}; +class CtorTmpl { + template<typename T> CtorTmpl(); // expected-note {{because type 'CtorTmpl' has a user-declared constructor}} +}; + +class CopyCtor { + CopyCtor(CopyCtor &cc) { abort(); } // expected-note 4 {{because type 'CopyCtor' has a user-declared copy constructor}} +}; + +// FIXME: this should eventually trigger on the operator's declaration line +class CopyAssign { // expected-note 4 {{because type 'CopyAssign' has a user-declared copy assignment operator}} + CopyAssign& operator=(CopyAssign& CA) { abort(); } +}; + +class Dtor { + ~Dtor() { abort(); } // expected-note 4 {{because type 'Dtor' has a user-declared destructor}} +}; + +union U1 { + Virtual v; // expected-error {{union member 'v' has a non-trivial copy constructor}} + VirtualBase vbase; // expected-error {{union member 'vbase' has a non-trivial copy constructor}} + Ctor ctor; // expected-error {{union member 'ctor' has a non-trivial constructor}} + Ctor2 ctor2; // expected-error {{union member 'ctor2' has a non-trivial constructor}} + CtorTmpl ctortmpl; // expected-error {{union member 'ctortmpl' has a non-trivial constructor}} + CopyCtor copyctor; // expected-error {{union member 'copyctor' has a non-trivial copy constructor}} + CopyAssign copyassign; // expected-error {{union member 'copyassign' has a non-trivial copy assignment operator}} + Dtor dtor; // expected-error {{union member 'dtor' has a non-trivial destructor}} + Okay okay; +}; + +union U2 { + struct { + Virtual v; // expected-note {{because type 'U2::<anonymous struct}} + } m1; // expected-error {{union member 'm1' has a non-trivial copy constructor}} + struct { + VirtualBase vbase; // expected-note {{because type 'U2::<anonymous struct}} + } m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}} + struct { + Ctor ctor; // expected-note {{because type 'U2::<anonymous struct}} + } m3; // expected-error {{union member 'm3' has a non-trivial constructor}} + struct { + Ctor2 ctor2; // expected-note {{because type 'U2::<anonymous struct}} + } m3a; // expected-error {{union member 'm3a' has a non-trivial constructor}} + struct { + CopyCtor copyctor; // expected-note {{because type 'U2::<anonymous struct}} + } m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}} + struct { + CopyAssign copyassign; // expected-note {{because type 'U2::<anonymous struct}} + } m5; // expected-error {{union member 'm5' has a non-trivial copy assignment operator}} + struct { + Dtor dtor; // expected-note {{because type 'U2::<anonymous struct}} + } m6; // expected-error {{union member 'm6' has a non-trivial destructor}} + struct { + Okay okay; + } m7; +}; + +union U3 { + struct s1 : Virtual { // expected-note {{because type 'U3::s1' has a base class with a non-trivial copy constructor}} + } m1; // expected-error {{union member 'm1' has a non-trivial copy constructor}} + struct s2 : VirtualBase { // expected-note {{because type 'U3::s2' has a base class with a non-trivial copy constructor}} + } m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}} + struct s3 : Ctor { // expected-note {{because type 'U3::s3' has a base class with a non-trivial constructor}} + } m3; // expected-error {{union member 'm3' has a non-trivial constructor}} + struct s3a : Ctor2 { // expected-note {{because type 'U3::s3a' has a base class with a non-trivial constructor}} + } m3a; // expected-error {{union member 'm3a' has a non-trivial constructor}} + struct s4 : CopyCtor { // expected-note {{because type 'U3::s4' has a base class with a non-trivial copy constructor}} + } m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}} + struct s5 : CopyAssign { // expected-note {{because type 'U3::s5' has a base class with a non-trivial copy assignment operator}} + } m5; // expected-error {{union member 'm5' has a non-trivial copy assignment operator}} + struct s6 : Dtor { // expected-note {{because type 'U3::s6' has a base class with a non-trivial destructor}} + } m6; // expected-error {{union member 'm6' has a non-trivial destructor}} + struct s7 : Okay { + } m7; +}; + +union U4 { + static int i1; // expected-warning {{static data member 'i1' in union is a C++11 extension}} +}; +int U4::i1 = 10; + +union U5 { + int& i1; // expected-error {{union member 'i1' has reference type 'int &'}} +}; + +template <class A, class B> struct Either { + bool tag; + union { // expected-note 6 {{in instantiation of member class}} + A a; + B b; // expected-error 6 {{non-trivial}} + }; + + Either(const A& a) : tag(true), a(a) {} + Either(const B& b) : tag(false), b(b) {} +}; + +void fred() { + Either<int,Virtual> virt(0); // expected-note {{in instantiation of template}} + Either<int,VirtualBase> vbase(0); // expected-note {{in instantiation of template}} + Either<int,Ctor> ctor(0); // expected-note {{in instantiation of template}} + Either<int,CopyCtor> copyctor(0); // expected-note {{in instantiation of template}} + Either<int,CopyAssign> copyassign(0); // expected-note {{in instantiation of template}} + Either<int,Dtor> dtor(0); // expected-note {{in instantiation of template}} + Either<int,Okay> okay(0); +} diff --git a/clang/test/CXX/class/class.union/p2-0x.cpp b/clang/test/CXX/class/class.union/p2-0x.cpp new file mode 100644 index 0000000..b5c4109 --- /dev/null +++ b/clang/test/CXX/class/class.union/p2-0x.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +// Unlike in C++98, C++11 allows unions to have static data members. + +union U1 { + static constexpr int k1 = 0; + static const int k2 = k1; + static int k3 = k2; // expected-error {{non-const static data member must be initialized out of line}} + static constexpr double k4 = k2; + static const double k5 = k4; // expected-warning {{GNU extension}} expected-note {{use 'constexpr'}} + int n[k1 + 3]; +}; + +constexpr int U1::k1; +constexpr int U1::k2; +int U1::k3; + +const double U1::k4; +const double U1::k5; + +template<typename T> +union U2 { + static const int k1; + static double k2; + T t; +}; +template<typename T> constexpr int U2<T>::k1 = sizeof(U2<T>); +template<typename T> double U2<T>::k2 = 5.3; + +static_assert(U2<int>::k1 == sizeof(int), ""); +static_assert(U2<char>::k1 == sizeof(char), ""); + +union U3 { + static const int k; + U3() : k(0) {} // expected-error {{does not name a non-static data member}} +}; + +struct S { + union { + static const int n; // expected-error {{static members cannot be declared in an anonymous union}} + int a; + int b; + }; +}; +static union { + static const int k; // expected-error {{static members cannot be declared in an anonymous union}} + int n; +}; diff --git a/clang/test/CXX/class/p1-0x.cpp b/clang/test/CXX/class/p1-0x.cpp new file mode 100644 index 0000000..be5fdff --- /dev/null +++ b/clang/test/CXX/class/p1-0x.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +namespace Test1 { + +class A final { }; + +} diff --git a/clang/test/CXX/class/p2-0x.cpp b/clang/test/CXX/class/p2-0x.cpp new file mode 100644 index 0000000..dbb01e5 --- /dev/null +++ b/clang/test/CXX/class/p2-0x.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +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/clang/test/CXX/class/p6-0x.cpp b/clang/test/CXX/class/p6-0x.cpp new file mode 100644 index 0000000..f2cf482 --- /dev/null +++ b/clang/test/CXX/class/p6-0x.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +class Trivial { int n; void f(); }; +class NonTrivial1 { NonTrivial1(const NonTrivial1 &); }; +class NonTrivial2 { NonTrivial2(NonTrivial2 &&); }; +class NonTrivial3 { NonTrivial3 operator=(const NonTrivial3 &); }; +class NonTrivial4 { NonTrivial4 operator=(NonTrivial4 &&); }; +class NonTrivial5 { ~NonTrivial5(); }; + +static_assert(__is_trivial(Trivial), "Trivial is not trivial"); +static_assert(!__is_trivial(NonTrivial1), "NonTrivial1 is trivial"); +static_assert(!__is_trivial(NonTrivial2), "NonTrivial2 is trivial"); +static_assert(!__is_trivial(NonTrivial3), "NonTrivial3 is trivial"); +static_assert(!__is_trivial(NonTrivial4), "NonTrivial4 is trivial"); +static_assert(!__is_trivial(NonTrivial5), "NonTrivial5 is trivial"); + +struct Trivial2 { + Trivial2() = default; + Trivial2(const Trivial2 &) = default; + Trivial2(Trivial2 &&) = default; + Trivial2 &operator=(const Trivial2 &) = default; + Trivial2 &operator=(Trivial2 &) = default; + ~Trivial2() = default; +}; + +class NonTrivial6 { ~NonTrivial6(); }; + +NonTrivial6::~NonTrivial6() = default; + +static_assert(!__is_trivial(NonTrivial6), "NonTrivial6 is trivial"); diff --git a/clang/test/CXX/conv/conv.mem/p4.cpp b/clang/test/CXX/conv/conv.mem/p4.cpp new file mode 100644 index 0000000..e0748d8 --- /dev/null +++ b/clang/test/CXX/conv/conv.mem/p4.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct Base { + int data; + int method(); +}; +int (Base::*data_ptr) = &Base::data; +int (Base::*method_ptr)() = &Base::method; + +namespace test0 { + struct Derived : Base {}; + void test() { + int (Derived::*d) = data_ptr; + int (Derived::*m)() = method_ptr; + } +} + +// Can't be inaccessible. +namespace test1 { + struct Derived : private Base {}; // expected-note 2 {{declared private here}} + void test() { + int (Derived::*d) = data_ptr; // expected-error {{cannot cast private base class 'Base' to 'test1::Derived'}} + int (Derived::*m)() = method_ptr; // expected-error {{cannot cast private base class 'Base' to 'test1::Derived'}} + } +}; + +// Can't be ambiguous. +namespace test2 { + struct A : Base {}; + struct B : Base {}; + struct Derived : A, B {}; + void test() { + int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test2::Derived':}} + int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test2::Derived':}} + } +} + +// Can't be virtual. +namespace test3 { + struct Derived : virtual Base {}; + void test() { + int (Derived::*d) = data_ptr; // expected-error {{conversion from pointer to member of class 'Base' to pointer to member of class 'test3::Derived' via virtual base 'Base' is not allowed}} + int (Derived::*m)() = method_ptr; // expected-error {{conversion from pointer to member of class 'Base' to pointer to member of class 'test3::Derived' via virtual base 'Base' is not allowed}} + } +} + +// Can't be virtual even if there's a non-virtual path. +namespace test4 { + struct A : Base {}; + struct Derived : Base, virtual A {}; + void test() { + int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test4::Derived':}} + int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test4::Derived':}} + } +} + +// PR6254: don't get thrown off by a virtual base. +namespace test5 { + struct A {}; + struct Derived : Base, virtual A {}; + void test() { + int (Derived::*d) = data_ptr; + int (Derived::*m)() = method_ptr; + } +} diff --git a/clang/test/CXX/conv/conv.prom/p2.cpp b/clang/test/CXX/conv/conv.prom/p2.cpp new file mode 100644 index 0000000..8d75419 --- /dev/null +++ b/clang/test/CXX/conv/conv.prom/p2.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x -ffreestanding %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x -fshort-wchar -ffreestanding %s + +#include <stdint.h> + +// In theory, the promoted types vary by platform; however, in reality they +// are quite consistent across all platforms where clang runs. + +extern int promoted_wchar; +extern decltype(+L'a') promoted_wchar; + +extern int promoted_char16; +extern decltype(+u'a') promoted_char16; + +extern unsigned promoted_char32; +extern decltype(+U'a') promoted_char32; diff --git a/clang/test/CXX/conv/conv.prom/p4.cpp b/clang/test/CXX/conv/conv.prom/p4.cpp new file mode 100644 index 0000000..02a91cd --- /dev/null +++ b/clang/test/CXX/conv/conv.prom/p4.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +enum X : short { A, B }; +extern decltype(+A) x; +extern int x; + +enum Y : long { C, D }; +extern decltype(+C) y; +extern long y; diff --git a/clang/test/CXX/conv/conv.ptr/p2.cpp b/clang/test/CXX/conv/conv.ptr/p2.cpp new file mode 100644 index 0000000..8808d20 --- /dev/null +++ b/clang/test/CXX/conv/conv.ptr/p2.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace pr7801 { + extern void* x[]; + void* dummy[] = { &x }; +} diff --git a/clang/test/CXX/conv/conv.qual/pr6089.cpp b/clang/test/CXX/conv/conv.qual/pr6089.cpp new file mode 100644 index 0000000..ae75ec4 --- /dev/null +++ b/clang/test/CXX/conv/conv.qual/pr6089.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +bool is_char_ptr( const char* ); + +template< class T > + long is_char_ptr( T /* r */ ); + +// Note: the const here does not lead to a qualification conversion +template< class T > + void make_range( T* const r, bool ); + +template< class T > + void make_range( T& r, long ); + +void first_finder( const char*& Search ) +{ + make_range( Search, is_char_ptr(Search) ); +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp new file mode 100644 index 0000000..069ca0a --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp @@ -0,0 +1,93 @@ +// 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 +// a friend declaration in a non-local class first declares a class or +// function the friend class or function is a member of the innermost +// enclosing namespace. + +namespace N { + struct S0 { + friend struct F0; + friend void f0(int); + struct F0 member_func(); + }; + struct F0 { }; + F0 f0() { return S0().member_func(); } +} +N::F0 f0_var = N::f0(); + +// Ensure we can handle attaching friend declarations to an enclosing namespace +// with multiple contexts. +namespace N { struct S1 { struct IS1; }; } +namespace N { + struct S1::IS1 { + friend struct F1; + friend void f1(int); + struct F1 member_func(); + }; + struct F1 { }; + F1 f1() { return S1::IS1().member_func(); } +} +N::F1 f1_var = N::f1(); + +// The name of the friend is not found by unqualified lookup (3.4.1) or by +// qualified lookup (3.4.3) until a matching declaration is provided in that +// namespace scope (either before or after the class definition granting +// friendship). If a friend function is called, its name may be found by the +// name lookup that considers functions from namespaces and classes +// associated with the types of the function arguments (3.4.2). If the name +// in a friend declaration is neither qualified nor a template-id and the +// declaration is a function or an elaborated-type-specifier, the lookup to +// determine whether the entity has been previously declared shall not +// consider any scopes outside the innermost enclosing namespace. + +template<typename T> struct X0 { }; +struct X1 { }; + +struct Y { + template<typename T> union X0; + template<typename T> friend union X0; + + union X1; + friend union X1; +}; + +namespace N { + namespace M { + template<typename T> class X; + } +} + +namespace N3 { + class Y { + template<typename T> friend class N::M::X; + }; +} + +// 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/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp new file mode 100644 index 0000000..b4ec585 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.unnamed/p1.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -emit-llvm-only -verify %s + +// This lame little test was ripped straight from the standard. +namespace { + int i; // expected-note {{candidate}} +} +void test0() { i++; } + +namespace A { + namespace { + int i; // expected-note {{candidate}} + int j; + } + void test1() { i++; } +} + +using namespace A; + +void test2() { + i++; // expected-error {{reference to 'i' is ambiguous}} + A::i++; + j++; +} + + +// Test that all anonymous namespaces in a translation unit are +// considered the same context. +namespace { + class Test3 {}; // expected-note {{previous definition}} +} +namespace { + class Test3 {}; // expected-error {{redefinition of 'Test3'}} +} + +namespace test4 { + namespace { + class Test4 {}; // expected-note {{previous definition}} + } + namespace { + class Test4 {}; // expected-error {{redefinition of 'Test4'}} + } +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p1.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p1.cpp new file mode 100644 index 0000000..6ffa873 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p1.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -pedantic %s + +// Intentionally compiled as C++03 to test the extension warning. + +namespace a {} // original +namespace a {} // ext +inline namespace b {} // inline original expected-warning {{inline namespaces are}} +inline namespace b {} // inline ext expected-warning {{inline namespaces are}} +inline namespace {} // inline unnamed expected-warning {{inline namespaces are}} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p2.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p2.cpp new file mode 100644 index 0000000..411c16c --- /dev/null +++ b/clang/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/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp new file mode 100644 index 0000000..98d12f9 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +namespace NIL {} // expected-note {{previous definition}} +inline namespace NIL {} // expected-error {{cannot be reopened as inline}} +inline namespace IL {} // expected-note {{previous definition}} +namespace IL {} // expected-warning{{inline namespace cannot be re-opened as a non-inline namespace}} + +namespace {} // expected-note {{previous definition}} +inline namespace {} // expected-error {{cannot be reopened as inline}} +namespace X { + inline namespace {} // expected-note {{previous definition}} + namespace {} // expected-error {{cannot be reopened as non-inline}} +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p8.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p8.cpp new file mode 100644 index 0000000..3bc4856 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/p8.cpp @@ -0,0 +1,118 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// Fun things you can do with inline namespaces: + +inline namespace X { + void f1(); + + inline namespace Y { + void f2(); + + template <typename T> class C {}; + } + + // Specialize and partially specialize somewhere else. + template <> class C<int> {}; + template <typename T> class C<T*> {}; +} + +// Qualified and unqualified lookup as if member of enclosing NS. +void foo1() { + f1(); + ::f1(); + X::f1(); + Y::f1(); // expected-error {{no member named 'f1' in namespace 'X::Y'}} + + f2(); + ::f2(); + X::f2(); + Y::f2(); +} + +template <> class C<float> {}; +template <typename T> class C<T&> {}; + +template class C<double>; + + +// As well as all the fun with ADL. + +namespace ADL { + struct Outer {}; + + inline namespace IL { + struct Inner {}; + + void fo(Outer); + } + + void fi(Inner); + + inline namespace IL2 { + void fi2(Inner); + } +} + +void foo2() { + ADL::Outer o; + ADL::Inner i; + fo(o); + fi(i); + fi2(i); +} + +// Let's not forget overload sets. +struct Distinct {}; +inline namespace Over { + void over(Distinct); +} +void over(int); + +void foo3() { + Distinct d; + ::over(d); +} + +// Don't forget to do correct lookup for redeclarations. +namespace redecl { inline namespace n1 { + + template <class Tp> class allocator; + + template <> + class allocator<void> + { + public: + typedef const void* const_pointer; + }; + + template <class Tp> + class allocator + { + public: + typedef Tp& reference; + + void allocate(allocator<void>::const_pointer = 0); + }; + +} } + +// Normal redeclarations (not for explicit instantiations or +// specializations) are distinct in an inline namespace vs. not in an +// inline namespace. +namespace redecl2 { + inline namespace n1 { + void f(int) { } + struct X1 { }; + template<typename T> void f(T) { } + template<typename T> struct X2 { }; + int i = 71; + enum E { e }; + } + + void f(int) { } + struct X1 { }; + template<typename T> void f(T) { } + template<typename T> struct X2 { }; + int i = 71; + enum E { e }; +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp new file mode 100644 index 0000000..bf30ee7 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// We have to avoid ADL for this test. + +template <unsigned N> class test {}; + +class foo {}; // expected-note {{candidate}} +test<0> foo(foo); // expected-note {{candidate}} + +namespace Test0 { + class foo { int x; }; + test<1> foo(class foo); + + namespace A { + test<2> foo(class ::foo); // expected-note {{candidate}} \ + // expected-note{{passing argument to parameter here}} + + void test0() { + using ::foo; + + class foo a; + test<0> _ = (foo)(a); + } + + void test1() { + using Test0::foo; + + class foo a; + test<1> _ = (foo)(a); + }; + + void test2() { + class ::foo a; + + // Argument-dependent lookup is ambiguous between B:: and ::. + test<0> _0 = foo(a); // expected-error {{call to 'foo' is ambiguous}} + + // But basic unqualified lookup is not. + test<2> _1 = (foo)(a); + + class Test0::foo b; + test<2> _2 = (foo)(b); // expected-error {{no viable conversion from 'class Test0::foo' to 'class ::foo'}} + } + } +} + +namespace Test1 { + namespace A { + class a {}; + } + + namespace B { + typedef class {} b; + } + + namespace C { + int c(); // expected-note {{target of using declaration}} + } + + namespace D { + using typename A::a; + using typename B::b; + using typename C::c; // expected-error {{'typename' keyword used on a non-type}} + + a _1 = A::a(); + b _2 = B::b(); + } +} + +namespace test2 { + class A { + protected: + operator int(); + operator bool(); + }; + + class B : private A { + protected: + using A::operator int; // expected-note {{declared protected here}} + public: + using A::operator bool; + }; + + int test() { + bool b = B(); + return B(); // expected-error {{'operator int' is a protected member of 'test2::B'}} + } +} + +namespace test3 { + class A { + public: + ~A(); + }; + + class B { + friend class C; + private: + operator A*(); + }; + + class C : public B { + public: + using B::operator A*; + }; + + void test() { + delete C(); + } +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp new file mode 100644 index 0000000..546c4a4 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test0 { + namespace ns0 { + class tag; + int tag(); + } + + namespace ns1 { + using ns0::tag; + } + + namespace ns2 { + using ns0::tag; + } + + using ns1::tag; + using ns2::tag; +} + +// PR 5752 +namespace test1 { + namespace ns { + void foo(); + } + + using ns::foo; + void foo(int); + + namespace ns { + using test1::foo; + } +} + diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp new file mode 100644 index 0000000..c7966ce --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p11.cpp @@ -0,0 +1,91 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++03 [namespace.udecl]p11: +// If a function declaration in namespace scope or block scope has +// the same name and the same parameter types as a function +// introduced by a using-declaration, the program is +// ill-formed. [Note: two using-declarations may introduce functions +// with the same name and the same parameter types. If, for a call +// to an unqualified function name, function overload resolution +// selects the functions introduced by such using-declarations, the +// function call is ill-formed. + +namespace test0 { + namespace ns { void foo(); } // expected-note {{target of using declaration}} + int foo(void); // expected-note {{conflicting declaration}} + using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} +} + +namespace test1 { + namespace ns { void foo(); } // expected-note {{target of using declaration}} + using ns::foo; //expected-note {{using declaration}} + int foo(void); // expected-error {{declaration conflicts with target of using declaration already in scope}} +} + +namespace test2 { + namespace ns { void foo(); } // expected-note 2 {{target of using declaration}} + void test0() { + int foo(void); // expected-note {{conflicting declaration}} + using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} + } + + void test1() { + using ns::foo; //expected-note {{using declaration}} + int foo(void); // expected-error {{declaration conflicts with target of using declaration already in scope}} + } +} + +namespace test3 { + namespace ns { void foo(); } // expected-note 2 {{target of using declaration}} + class Test0 { + void test() { + int foo(void); // expected-note {{conflicting declaration}} + using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} + } + }; + + class Test1 { + void test() { + using ns::foo; //expected-note {{using declaration}} + int foo(void); // expected-error {{declaration conflicts with target of using declaration already in scope}} + } + }; +} + +namespace test4 { + namespace ns { void foo(); } // expected-note 2 {{target of using declaration}} + template <typename> class Test0 { + void test() { + int foo(void); // expected-note {{conflicting declaration}} + using ns::foo; // expected-error {{target of using declaration conflicts with declaration already in scope}} + } + }; + + template <typename> class Test1 { + void test() { + using ns::foo; //expected-note {{using declaration}} + int foo(void); // expected-error {{declaration conflicts with target of using declaration already in scope}} + } + }; +} + +// FIXME: we should be able to diagnose both of these, but we can't. +namespace test5 { + namespace ns { void foo(int); } + template <typename T> class Test0 { + void test() { + int foo(T); + using ns::foo; + } + }; + + template <typename T> class Test1 { + void test() { + using ns::foo; + int foo(T); + } + }; + + template class Test0<int>; + template class Test1<int>; +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp new file mode 100644 index 0000000..cc28bf6 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp @@ -0,0 +1,163 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++03 [namespace.udecl]p12: +// When a using-declaration brings names from a base class into a +// derived class scope, member functions in the derived class +// override and/or hide member functions with the same name and +// parameter types in a base class (rather than conflicting). + +template <unsigned n> struct Opaque {}; +template <unsigned n> void expect(Opaque<n> _) {} + +// PR5727 +// This just shouldn't crash. +namespace test0 { + template<typename> struct RefPtr { }; + template<typename> struct PtrHash { + static void f() { } + }; + template<typename T> struct PtrHash<RefPtr<T> > : PtrHash<T*> { + using PtrHash<T*>::f; + static void f() { f(); } + }; +} + +// Simple hiding. +namespace test1 { + struct Base { + Opaque<0> foo(Opaque<0>); + Opaque<0> foo(Opaque<1>); + Opaque<0> foo(Opaque<2>); + }; + + // using before decls + struct Test0 : Base { + using Base::foo; + Opaque<1> foo(Opaque<1>); + Opaque<1> foo(Opaque<3>); + + void test0() { Opaque<0> _ = foo(Opaque<0>()); } + void test1() { Opaque<1> _ = foo(Opaque<1>()); } + void test2() { Opaque<0> _ = foo(Opaque<2>()); } + void test3() { Opaque<1> _ = foo(Opaque<3>()); } + }; + + // using after decls + struct Test1 : Base { + Opaque<1> foo(Opaque<1>); + Opaque<1> foo(Opaque<3>); + using Base::foo; + + void test0() { Opaque<0> _ = foo(Opaque<0>()); } + void test1() { Opaque<1> _ = foo(Opaque<1>()); } + void test2() { Opaque<0> _ = foo(Opaque<2>()); } + void test3() { Opaque<1> _ = foo(Opaque<3>()); } + }; + + // using between decls + struct Test2 : Base { + Opaque<1> foo(Opaque<0>); + using Base::foo; + Opaque<1> foo(Opaque<2>); + Opaque<1> foo(Opaque<3>); + + void test0() { Opaque<1> _ = foo(Opaque<0>()); } + void test1() { Opaque<0> _ = foo(Opaque<1>()); } + void test2() { Opaque<1> _ = foo(Opaque<2>()); } + void test3() { Opaque<1> _ = foo(Opaque<3>()); } + }; +} + +// Crazy dependent hiding. +namespace test2 { + struct Base { + void foo(int); + }; + + template <typename T> struct Derived1 : Base { + using Base::foo; + void foo(T); + + void testUnresolved(int i) { foo(i); } + }; + + void test0(int i) { + Derived1<int> d1; + d1.foo(i); + d1.testUnresolved(i); + } + + // Same thing, except with the order of members reversed. + template <typename T> struct Derived2 : Base { + void foo(T); + using Base::foo; + + void testUnresolved(int i) { foo(i); } + }; + + void test1(int i) { + Derived2<int> d2; + d2.foo(i); + d2.testUnresolved(i); + } +} + +// Hiding of member templates. +namespace test3 { + struct Base { + template <class T> Opaque<0> foo() { return Opaque<0>(); } + template <int n> Opaque<1> foo() { return Opaque<1>(); } + }; + + struct Derived1 : Base { + using Base::foo; + template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'n'}} + }; + + struct Derived2 : Base { + template <int n> Opaque<2> foo() { return Opaque<2>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'n'}} + using Base::foo; + }; + + struct Derived3 : Base { + using Base::foo; + template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'T'}} + }; + + struct Derived4 : Base { + template <class T> Opaque<3> foo() { return Opaque<3>(); } // expected-note {{invalid explicitly-specified argument for template parameter 'T'}} + using Base::foo; + }; + + void test() { + expect<0>(Base().foo<int>()); + expect<1>(Base().foo<0>()); + expect<0>(Derived1().foo<int>()); // expected-error {{no matching member function for call to 'foo'}} + expect<2>(Derived1().foo<0>()); + expect<0>(Derived2().foo<int>()); // expected-error {{no matching member function for call to 'foo'}} + expect<2>(Derived2().foo<0>()); + expect<3>(Derived3().foo<int>()); + expect<1>(Derived3().foo<0>()); // expected-error {{no matching member function for call to 'foo'}} + expect<3>(Derived4().foo<int>()); + expect<1>(Derived4().foo<0>()); // expected-error {{no matching member function for call to 'foo'}} + } +} + +// PR7384: access control for member templates. +namespace test4 { + class Base { + protected: + template<typename T> void foo(T); + template<typename T> void bar(T); // expected-note {{declared protected here}} + }; + + struct Derived : Base { + using Base::foo; + }; + + void test() { + Derived d; + d.foo<int>(3); + d.bar<int>(3); // expected-error {{'bar' is a protected member}} + } +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp new file mode 100644 index 0000000..dd44bfc --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p13.cpp @@ -0,0 +1,76 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++03 [namespace.udecl]p3: +// For the purpose of overload resolution, the functions which are +// introduced by a using-declaration into a derived class will be +// treated as though they were members of the derived class. In +// particular, the implicit this parameter shall be treated as if it +// were a pointer to the derived class rather than to the base +// class. This has no effect on the type of the function, and in all +// other respects the function remains a member of the base class. + +namespace test0 { + struct Opaque0 {}; + struct Opaque1 {}; + + struct Base { + Opaque0 test0(int*); + Opaque0 test1(const int*); + Opaque0 test2(int*); + Opaque0 test3(int*) const; + }; + + struct Derived : Base { + using Base::test0; + Opaque1 test0(const int*); + + using Base::test1; + Opaque1 test1(int*); + + using Base::test2; + Opaque1 test2(int*) const; + + using Base::test3; + Opaque1 test3(int*); + }; + + void test0() { + Opaque0 a = Derived().test0((int*) 0); + Opaque1 b = Derived().test0((const int*) 0); + } + + void test1() { + Opaque1 a = Derived().test1((int*) 0); + Opaque0 b = Derived().test1((const int*) 0); + } + + void test2() { + Opaque0 a = ((Derived*) 0)->test2((int*) 0); + Opaque1 b = ((const Derived*) 0)->test2((int*) 0); + } + + void test3() { + Opaque1 a = ((Derived*) 0)->test3((int*) 0); + Opaque0 b = ((const Derived*) 0)->test3((int*) 0); + } +} + +// Typedef redeclaration. +namespace rdar8018262 { + typedef void (*fp)(); + + namespace N { + typedef void (*fp)(); + } + + using N::fp; + + fp fp_1; +} + +// Things to test: +// member operators +// conversion operators +// call operators +// call-surrogate conversion operators +// everything, but in dependent contexts diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp new file mode 100644 index 0000000..f61437e --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +// C++0x N2914. + +struct B { + void f(char); + void g(char); + enum E { e }; + union { int x; }; +}; + +class C { + int g(); +}; + +class D2 : public B { + using B::f; + using B::e; + using B::x; + using C::g; // expected-error{{using declaration refers into 'C::', which is not a base class of 'D2'}} +}; + +namespace test1 { + struct Base { + int foo(); + }; + + struct Unrelated { + int foo(); + }; + + struct Subclass : Base { + }; + + namespace InnerNS { + int foo(); + } + + // We should be able to diagnose these without instantiation. + template <class T> struct C : Base { + using InnerNS::foo; // expected-error {{not a class}} + using Base::bar; // expected-error {{no member named 'bar'}} + using Unrelated::foo; // expected-error {{not a base class}} + using C::foo; // expected-error {{refers to its own class}} + using Subclass::foo; // expected-error {{not a base class}} + }; +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp new file mode 100644 index 0000000..a43d9e0 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp @@ -0,0 +1,213 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++03 [namespace.udecl]p4: +// A using-declaration used as a member-declaration shall refer to a +// member of a base class of the class being defined, shall refer to +// a member of an anonymous union that is a member of a base class +// of the class being defined, or shall refer to an enumerator for +// an enumeration type that is a member of a base class of the class +// being defined. + +// There is no directly analogous paragraph in C++0x, and the feature +// works sufficiently differently there that it needs a separate test. + +namespace test0 { + namespace NonClass { + typedef int type; + struct hiding {}; + int hiding; + static union { double union_member; }; + enum tagname { enumerator }; + } + + class Test0 { + using NonClass::type; // expected-error {{not a class}} + using NonClass::hiding; // expected-error {{not a class}} + using NonClass::union_member; // expected-error {{not a class}} + using NonClass::enumerator; // expected-error {{not a class}} + }; +} + +struct Opaque0 {}; + +namespace test1 { + struct A { + typedef int type; + struct hiding {}; // expected-note {{previous use is here}} + Opaque0 hiding; + union { double union_member; }; + enum tagname { enumerator }; + }; + + struct B : A { + using A::type; + using A::hiding; + using A::union_member; + using A::enumerator; + using A::tagname; + + void test0() { + type t = 0; + } + + void test1() { + typedef struct A::hiding local; + struct hiding _ = local(); + } + + void test2() { + union hiding _; // expected-error {{tag type that does not match previous}} + } + + void test3() { + char array[sizeof(union_member) == sizeof(double) ? 1 : -1]; + } + + void test4() { + enum tagname _ = enumerator; + } + + void test5() { + Opaque0 _ = hiding; + } + }; +} + +namespace test2 { + struct A { + typedef int type; + struct hiding {}; // expected-note {{previous use is here}} + int hiding; + union { double union_member; }; + enum tagname { enumerator }; + }; + + template <class T> struct B : A { + using A::type; + using A::hiding; + using A::union_member; + using A::enumerator; + using A::tagname; + + void test0() { + type t = 0; + } + + void test1() { + typedef struct A::hiding local; + struct hiding _ = local(); + } + + void test2() { + union hiding _; // expected-error {{tag type that does not match previous}} + } + + void test3() { + char array[sizeof(union_member) == sizeof(double) ? 1 : -1]; + } + + void test4() { + enum tagname _ = enumerator; + } + + void test5() { + Opaque0 _ = hiding; + } + }; +} + +namespace test3 { + struct hiding {}; + + template <class T> struct A { + typedef int type; // expected-note {{target of using declaration}} + struct hiding {}; + Opaque0 hiding; // expected-note {{target of using declaration}} + union { double union_member; }; // expected-note {{target of using declaration}} + enum tagname { enumerator }; // expected-note 2 {{target of using declaration}} + }; + + template <class T> struct B : A<T> { + using A<T>::type; // expected-error {{dependent using declaration resolved to type without 'typename'}} + using A<T>::hiding; + using A<T>::union_member; + using A<T>::enumerator; + using A<T>::tagname; // expected-error {{dependent using declaration resolved to type without 'typename'}} + + // FIXME: re-enable these when the various bugs involving tags are fixed +#if 0 + void test1() { + typedef struct A<T>::hiding local; + struct hiding _ = local(); + } + + void test2() { + typedef struct A<T>::hiding local; + union hiding _ = local(); + } +#endif + + void test3() { + char array[sizeof(union_member) == sizeof(double) ? 1 : -1]; + } + +#if 0 + void test4() { + enum tagname _ = enumerator; + } +#endif + + void test5() { + Opaque0 _ = hiding; + } + }; + + template struct B<int>; // expected-note {{in instantiation}} + + template <class T> struct C : A<T> { + using typename A<T>::type; + using typename A<T>::hiding; // expected-note {{declared here}} \ + // expected-error {{'typename' keyword used on a non-type}} + using typename A<T>::union_member; // expected-error {{'typename' keyword used on a non-type}} + using typename A<T>::enumerator; // expected-error {{'typename' keyword used on a non-type}} + + void test6() { + type t = 0; + } + + void test7() { + Opaque0 _ = hiding; // expected-error {{does not refer to a value}} + } + }; + + template struct C<int>; // expected-note {{in instantiation}} +} + +namespace test4 { + struct Base { + int foo(); + }; + + struct Unrelated { + int foo(); + }; + + struct Subclass : Base { + }; + + namespace InnerNS { + int foo(); + } + + // We should be able to diagnose these without instantiation. + template <class T> struct C : Base { + using InnerNS::foo; // expected-error {{not a class}} + using Base::bar; // expected-error {{no member named 'bar'}} + using Unrelated::foo; // expected-error {{not a base class}} + using C::foo; // legal in C++03 + using Subclass::foo; // legal in C++03 + + int bar(); //expected-note {{target of using declaration}} + using C::bar; // expected-error {{refers to its own class}} + }; +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp new file mode 100644 index 0000000..edaa975 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// C++0x N2914. + +struct A { + template<class T> void f(T); + template<class T> struct X { }; +}; + +struct B : A { + using A::f<double>; // expected-error{{using declaration can not refer to a template specialization}} + using A::X<int>; // expected-error{{using declaration can not refer to a template specialization}} +}; diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp new file mode 100644 index 0000000..c4b8849 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// C++0x N2914. + +namespace A { + namespace B { } +} + +using A::B; // expected-error{{using declaration can not refer to namespace}} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp new file mode 100644 index 0000000..78b5a41 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// C++0x N2914. + +struct X { + int i; + static int a; +}; + +using X::i; // expected-error{{using declaration can not refer to class member}} +using X::s; // expected-error{{using declaration can not refer to class member}} + +void f() { + using X::i; // expected-error{{using declaration can not refer to class member}} + using X::s; // expected-error{{using declaration can not refer to class member}} +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8.cpp new file mode 100644 index 0000000..4660971 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8.cpp @@ -0,0 +1,98 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct Opaque0 {}; +struct Opaque1 {}; + +// Redeclarations are okay in a namespace. +namespace test0 { + namespace ns { + void foo(Opaque0); // expected-note 2 {{candidate function}} + } + + using ns::foo; + using ns::foo; + + void test0() { + foo(Opaque1()); // expected-error {{no matching function for call}} + } + + namespace ns { + void foo(Opaque1); + } + + void test1() { + foo(Opaque1()); // expected-error {{no matching function for call}} + } + + using ns::foo; + + void test2() { + foo(Opaque1()); + } + + using ns::foo; +} + +// Make sure we handle transparent contexts the same way. +namespace test1 { + namespace ns { + void foo(Opaque0); // expected-note 2 {{candidate function}} + } + + extern "C++" { + using ns::foo; + } + + void test0() { + foo(Opaque1()); // expected-error {{no matching function for call}} + } + + namespace ns { + void foo(Opaque1); + } + + void test1() { + foo(Opaque1()); // expected-error {{no matching function for call}} + } + + extern "C++" { + using ns::foo; + } + + void test2() { + foo(Opaque1()); + } +} + +// Make sure we detect invalid redeclarations that can't be detected +// until template instantiation. +namespace test2 { + template <class T> struct Base { + typedef Base type; + void foo(); + }; + + template <class T> struct Derived : Base<T> { + // These are invalid redeclarations, detectable only after + // instantiation. + using Base<T>::foo; // expected-note {{previous using decl}} + using Base<T>::type::foo; //expected-error {{redeclaration of using decl}} + }; + + template struct Derived<int>; // expected-note {{in instantiation of template class}} +} + +// Redeclarations are okay in a function. +namespace test3 { + namespace N { + int f(int); + typedef int type; + } + + void g() { + using N::f; + using N::f; + using N::type; + using N::type; + } +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p1.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p1.cpp new file mode 100644 index 0000000..20a19ab --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p1.cpp @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// (this actually occurs before paragraph 1) +namespace test0 { + namespace A {} + class B { + using namespace A; // expected-error {{'using namespace' is not allowed in classes}} + }; +} + + +struct opaque0 {}; +struct opaque1 {}; + +// Test that names appear as if in deepest common ancestor. +namespace test1 { + namespace A { + namespace B { + opaque0 foo(); // expected-note {{candidate}} + } + } + + namespace C { + opaque1 foo(); // expected-note {{candidate}} + + opaque1 test() { + using namespace A::B; + return foo(); // C::foo + } + } + + opaque1 test() { + using namespace A::B; + using namespace C; + return foo(); // expected-error {{call to 'foo' is ambiguous}} + } +} + +// Same thing, but with the directives in namespaces. +namespace test2 { + namespace A { + namespace B { + opaque0 foo(); // expected-note {{candidate}} + } + } + + namespace C { + opaque1 foo(); // expected-note {{candidate}} + + namespace test { + using namespace A::B; + + opaque1 test() { + return foo(); // C::foo + } + } + } + + namespace test { + using namespace A::B; + using namespace C; + + opaque1 test() { + return foo(); // expected-error {{call to 'foo' is ambiguous}} + } + } +} + +// Transitivity. +namespace test3 { + namespace A { + namespace B { + opaque0 foo(); + } + } + namespace C { + using namespace A; + } + + opaque0 test0() { + using namespace C; + using namespace B; + return foo(); + } + + namespace D { + using namespace C; + } + namespace A { + opaque1 foo(); + } + + opaque1 test1() { + using namespace D; + return foo(); + } +} + +// Transitivity acts like synthetic using directives. +namespace test4 { + namespace A { + namespace B { + opaque0 foo(); // expected-note {{candidate}} + } + } + + namespace C { + using namespace A::B; + } + + opaque1 foo(); // expected-note {{candidate}} + + namespace A { + namespace D { + using namespace C; + } + + opaque0 test() { + using namespace D; + return foo(); + } + } + + opaque0 test() { + using namespace A::D; + return foo(); // expected-error {{call to 'foo' is ambiguous}} + } +} + +// Bug: using directives should be followed when parsing default +// arguments in scoped declarations. +class test5 { + int inc(int x); +}; +namespace Test5 { + int default_x = 0; +} +using namespace Test5; +int test5::inc(int x = default_x) { + return x+1; +} diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p6.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p6.cpp new file mode 100644 index 0000000..4cb91cd --- /dev/null +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p6.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// <rdar://problem/8296180> +typedef int pid_t; +namespace ns { + typedef int pid_t; +} +using namespace ns; +pid_t x; + +struct A { }; +namespace ns { + typedef ::A A; +} +A a; diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp new file mode 100644 index 0000000..f9702ba --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p6.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +namespace std_example { + +int p[10]; +void f() { + int x = 42, y[5]; + // FIXME: Produce a better diagnostic for this case. + int(p[[x] { return x; }()]); // expected-error {{expected ']'}} + y[[] { return 2; }()] = 2; // expected-error {{consecutive left square brackets}} +} + +} diff --git a/clang/test/CXX/dcl.dcl/dcl.enum/p5.cpp b/clang/test/CXX/dcl.dcl/dcl.enum/p5.cpp new file mode 100644 index 0000000..f260624 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.enum/p5.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -verify %s +template<typename T> int force_same(T, T); + +// C++ [dcl.enum]p5: +// [...] If the underlying type is not fixed, the type of each enumerator is +// the type of its initializing value: +// - If an initializer is specified for an enumerator, the initializing +// value has the same type as the expression. +enum Bullet1 { + Bullet1Val1 = 'a', + Bullet1Val2 = 10u, + Bullet1Val1IsChar = sizeof(force_same(Bullet1Val1, char(0))), + Bullet1Val2IsUnsigned = sizeof(force_same(Bullet1Val2, unsigned(0))) +}; + +// - If no initializer is specified for the first enumerator, the +// initializing value has an unspecified integral type. +enum Bullet2 { + Bullet2Val, + Bullet2ValIsInt = sizeof(force_same(Bullet2Val, int(0))) +}; + +// - Otherwise the type of the initializing value is the same as the type +// of the initializing value of the preceding enumerator unless the +// incremented value is not representable in that type, in which case the +// type is an unspecified integral type sufficient to contain the +// incremented value. If no such type exists, the program is ill-formed. +enum Bullet3a { + Bullet3aVal1 = 17, + Bullet3aVal2, + Bullet3aVal2IsInt = sizeof(force_same(Bullet3aVal2, int(0))), + Bullet3aVal3 = 2147483647, + Bullet3aVal3IsInt = sizeof(force_same(Bullet3aVal3, int(0))), + Bullet3aVal4, + Bullet3aVal4IsUnsigned = sizeof(force_same(Bullet3aVal4, 0ul)) +}; + +enum Bullet3b { + Bullet3bVal1 = 17u, + Bullet3bVal2, + Bullet3bVal2IsInt = sizeof(force_same(Bullet3bVal2, 0u)), + Bullet3bVal3 = 2147483647u, + Bullet3bVal3IsInt = sizeof(force_same(Bullet3bVal3, 0u)), + Bullet3bVal4, + Bullet3bVal4IsUnsigned = sizeof(force_same(Bullet3bVal4, 0ul)) +}; + +enum Bullet3c { + Bullet3cVal1 = 0xFFFFFFFFFFFFFFFEull, + Bullet3cVal2, + Bullet3cVal3 // expected-warning{{not representable}} +}; + +// Following the closing brace of an enum-specifier, each enumerator has the +// type of its enumeration. +int array0[sizeof(force_same(Bullet3bVal3, Bullet3b(0)))? 1 : -1]; diff --git a/clang/test/CXX/dcl.dcl/dcl.link/p7.cpp b/clang/test/CXX/dcl.dcl/dcl.link/p7.cpp new file mode 100644 index 0000000..bd9ff3c --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.link/p7.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +struct X { }; + +// CHECK: @x1 = global %struct.X zeroinitializer +// CHECK: @x4 = global %struct.X zeroinitializer +// CHECK: @x2 = external global %struct.X +// CHECK: @x3 = external global %struct.X +extern "C" { + + + X x1; +} + +extern "C" X x2; + +extern X x3; + +X x4; + +X& get(int i) { + if (i == 1) + return x1; + else if (i == 2) + return x2; + else if (i == 3) + return x3; + else + return x4; +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp new file mode 100644 index 0000000..6820fc6 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -0,0 +1,123 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct notlit { // expected-note {{not literal because}} + notlit() {} +}; +struct notlit2 { + notlit2() {} +}; + +// valid declarations +constexpr int i1 = 0; +constexpr int f1() { return 0; } +struct s1 { + constexpr static int mi1 = 0; + const static int mi2; +}; +constexpr int s1::mi2 = 0; + +// invalid declarations +// not a definition of an object +constexpr extern int i2; // expected-error {{constexpr variable declaration must be a definition}} +// not a literal type +constexpr notlit nl1; // expected-error {{constexpr variable cannot have non-literal type 'const notlit'}} +// function parameters +void f2(constexpr int i) {} // expected-error {{function parameter cannot be constexpr}} +// non-static member +struct s2 { + constexpr int mi1; // expected-error {{non-static data member cannot be constexpr}} + static constexpr int mi2; // expected-error {{requires an initializer}} +}; +// typedef +typedef constexpr int CI; // expected-error {{typedef cannot be constexpr}} +// tag +constexpr class C1 {}; // expected-error {{class cannot be marked constexpr}} +constexpr struct S1 {}; // expected-error {{struct cannot be marked constexpr}} +constexpr union U1 {}; // expected-error {{union cannot be marked constexpr}} +constexpr enum E1 {}; // expected-error {{enum cannot be marked constexpr}} +template <typename T> constexpr class TC1 {}; // expected-error {{class cannot be marked constexpr}} +template <typename T> constexpr struct TS1 {}; // expected-error {{struct cannot be marked constexpr}} +template <typename T> constexpr union TU1 {}; // expected-error {{union cannot be marked constexpr}} +class C2 {} constexpr; // expected-error {{class cannot be marked constexpr}} +struct S2 {} constexpr; // expected-error {{struct cannot be marked constexpr}} +union U2 {} constexpr; // expected-error {{union cannot be marked constexpr}} +enum E2 {} constexpr; // expected-error {{enum cannot be marked constexpr}} +constexpr class C3 {} c3 = C3(); +constexpr struct S3 {} s3 = S3(); +constexpr union U3 {} u3 = {}; +constexpr enum E3 { V3 } e3 = V3; +class C4 {} constexpr c4 = C4(); +struct S4 {} constexpr s4 = S4(); +union U4 {} constexpr u4 = {}; +enum E4 { V4 } constexpr e4 = V4; +constexpr int; // expected-error {{constexpr can only be used in variable and function declarations}} +// redeclaration mismatch +constexpr int f3(); // expected-note {{previous declaration is here}} +int f3(); // expected-error {{non-constexpr declaration of 'f3' follows constexpr declaration}} +int f4(); // expected-note {{previous declaration is here}} +constexpr int f4(); // expected-error {{constexpr declaration of 'f4' follows non-constexpr declaration}} +template<typename T> constexpr T f5(T); +template<typename T> constexpr T f5(T); // expected-note {{previous}} +template<typename T> T f5(T); // expected-error {{non-constexpr declaration of 'f5' follows constexpr declaration}} +template<typename T> T f6(T); // expected-note {{here}} +template<typename T> constexpr T f6(T); // expected-error {{constexpr declaration of 'f6' follows non-constexpr declaration}} +// destructor +struct ConstexprDtor { + constexpr ~ConstexprDtor() = default; // expected-error {{destructor cannot be marked constexpr}} +}; + +// template stuff +template <typename T> constexpr T ft(T t) { return t; } +template <typename T> T gt(T t) { return t; } +struct S { + template<typename T> constexpr T f(); + template<typename T> T g() const; +}; + +// explicit specialization can differ in constepxr +template <> notlit ft(notlit nl) { return nl; } +template <> char ft(char c) { return c; } // expected-note {{previous}} +template <> constexpr char ft(char nl); // expected-error {{constexpr declaration of 'ft<char>' follows non-constexpr declaration}} +template <> constexpr int gt(int nl) { return nl; } +template <> notlit S::f() const { return notlit(); } +template <> constexpr int S::g() { return 0; } // expected-note {{previous}} +template <> int S::g() const; // expected-error {{non-constexpr declaration of 'g<int>' follows constexpr declaration}} +// specializations can drop the 'constexpr' but not the implied 'const'. +template <> char S::g() { return 0; } // expected-error {{no function template matches}} +template <> double S::g() const { return 0; } // ok + +constexpr int i3 = ft(1); + +void test() { + // ignore constexpr when instantiating with non-literal + notlit2 nl2; + (void)ft(nl2); +} + +// Examples from the standard: +constexpr int square(int x); // expected-note {{declared here}} +constexpr int bufsz = 1024; + +constexpr struct pixel { // expected-error {{struct cannot be marked constexpr}} + int x; + int y; + constexpr pixel(int); +}; + +constexpr pixel::pixel(int a) + : x(square(a)), y(square(a)) // expected-note {{undefined function 'square' cannot be used in a constant expression}} + { } + +constexpr pixel small(2); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'pixel(2)'}} + +constexpr int square(int x) { + return x * x; +} + +constexpr pixel large(4); + +int next(constexpr int x) { // expected-error {{function parameter cannot be constexpr}} + return x + 1; +} + +extern constexpr int memsz; // expected-error {{constexpr variable declaration must be a definition}} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p2.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p2.cpp new file mode 100644 index 0000000..001a086 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p2.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - | FileCheck %s + +// constexpr functions and constexpr constructors are implicitly inline. +struct S { + constexpr S(int n); + constexpr int g(); + int n; +}; + +constexpr S::S(int n) : n(n) {} + +constexpr S f(S s) { + return s.n * 2; +} + +constexpr int S::g() { + return f(*this).n; +} + +// CHECK: define linkonce_odr {{.*}} @_Z1f1S( +// CHECK: define linkonce_odr {{.*}} @_ZN1SC1Ei( +// CHECK: define linkonce_odr {{.*}} @_ZNK1S1gEv( + +int g() { + return f(42).g(); +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp new file mode 100644 index 0000000..cafdd63 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp @@ -0,0 +1,139 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +namespace N { + typedef char C; +} + +namespace M { + typedef double D; +} + +struct NonLiteral { // expected-note 2{{no constexpr constructors}} + NonLiteral() {} + NonLiteral(int) {} +}; +struct Literal { + constexpr Literal() {} + operator int() const { return 0; } +}; + +struct S { + virtual int ImplicitlyVirtual() const = 0; // expected-note {{overridden virtual function}} +}; +struct SS : S { + int ImplicitlyVirtual() const; +}; + +// The definition of a constexpr function shall satisfy the following +// constraints: +struct T : SS, NonLiteral { // expected-note {{base class 'NonLiteral' of non-literal type}} + constexpr T(); + constexpr int f(); // expected-error {{non-literal type 'T' cannot have constexpr members}} + + // - it shall not be virtual; + virtual constexpr int ExplicitlyVirtual() { return 0; } // expected-error {{virtual function cannot be constexpr}} + + constexpr int ImplicitlyVirtual() { return 0; } // expected-error {{virtual function cannot be constexpr}} + + // - its return type shall be a literal type; + constexpr NonLiteral NonLiteralReturn() { return {}; } // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}} + constexpr void VoidReturn() { return; } // expected-error {{constexpr function's return type 'void' is not a literal type}} + constexpr ~T(); // expected-error {{destructor cannot be marked constexpr}} + typedef NonLiteral F(); + constexpr F NonLiteralReturn2; // ok until definition + + // - each of its parameter types shall be a literal type; + constexpr int NonLiteralParam(NonLiteral) { return 0; } // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} + typedef int G(NonLiteral); + constexpr G NonLiteralParam2; // ok until definition + + // - its function-body shall be = delete, = default, + constexpr int Deleted() = delete; + // It's not possible for the function-body to legally be "= default" here. + // Other than constructors, only the copy- and move-assignment operators and + // destructor can be defaulted. Destructors can't be constexpr since they + // don't have a literal return type. Defaulted assignment operators can't be + // constexpr since they can't be const. + constexpr T &operator=(const T&) = default; // expected-error {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} +}; +struct U { + constexpr U SelfReturn(); + constexpr int SelfParam(U); +}; + +struct V : virtual U { // expected-note {{here}} + constexpr int F() { return 0; } // expected-error {{constexpr member function not allowed in struct with virtual base class}} +}; + +// or a compound-statememt that contains only +constexpr int AllowedStmts() { + // - null statements + ; + + // - static_assert-declarations + static_assert(true, "the impossible happened!"); + + // - typedef declarations and alias-declarations that do not define classes + // or enumerations + typedef int I; + typedef struct S T; + using J = int; + using K = int[sizeof(I) + sizeof(J)]; + // Note, the standard requires we reject this. + struct U; + + // - using-declarations + using N::C; + + // - using-directives + using namespace N; + + // - and exactly one return statement + return sizeof(K) + sizeof(C) + sizeof(K); +} +constexpr int ForStmt() { + for (int n = 0; n < 10; ++n) // expected-error {{statement not allowed in constexpr function}} + return 0; +} +constexpr int VarDecl() { + constexpr int a = 0; // expected-error {{variables cannot be declared in a constexpr function}} + return 0; +} +constexpr int FuncDecl() { + constexpr int ForwardDecl(int); // expected-error {{statement not allowed in constexpr function}} + return ForwardDecl(42); +} +constexpr int ClassDecl1() { + typedef struct { } S1; // expected-error {{types cannot be defined in a constexpr function}} + return 0; +} +constexpr int ClassDecl2() { + using S2 = struct { }; // expected-error {{types cannot be defined in a constexpr function}} + return 0; +} +constexpr int ClassDecl3() { + struct S3 { }; // expected-error {{types cannot be defined in a constexpr function}} + return 0; +} +constexpr int NoReturn() {} // expected-error {{no return statement in constexpr function}} +constexpr int MultiReturn() { + return 0; // expected-note {{return statement}} + return 0; // expected-error {{multiple return statements in constexpr function}} +} + +// - every constructor call and implicit conversion used in initializing the +// return value shall be one of those allowed in a constant expression. +// +// We implement the proposed resolution of DR1364 and ignore this bullet. +// However, we implement the spirit of the check as part of the p5 checking that +// a constexpr function must be able to produce a constant expression. +namespace DR1364 { + constexpr int f(int k) { + return k; // ok, even though lvalue-to-rvalue conversion of a function + // parameter is not allowed in a constant expression. + } + int kGlobal; // expected-note {{here}} + constexpr int f() { // expected-error {{constexpr function never produces a constant expression}} + return kGlobal; // expected-note {{read of non-const}} + } +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp new file mode 100644 index 0000000..65573c7 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp @@ -0,0 +1,249 @@ +// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions %s + +namespace N { + typedef char C; +} + +namespace M { + typedef double D; +} + +struct NonLiteral { // expected-note 2{{no constexpr constructors}} + NonLiteral() {} + NonLiteral(int) {} +}; +struct Literal { + constexpr Literal() {} + explicit Literal(int); // expected-note 2 {{here}} + operator int() const { return 0; } +}; + +// In the definition of a constexpr constructor, each of the parameter types +// shall be a literal type. +struct S { + constexpr S(int, N::C) {} + constexpr S(int, NonLiteral, N::C) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}} + constexpr S(int, NonLiteral = 42) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}} + + // In addition, either its function-body shall be = delete or = default + constexpr S() = default; + constexpr S(Literal) = delete; +}; + +// or it shall satisfy the following constraints: + +// - the class shall not have any virtual base classes; +struct T : virtual S { // expected-note {{here}} + constexpr T() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}} +}; +namespace IndirectVBase { + struct A {}; + struct B : virtual A {}; // expected-note {{here}} + class C : public B { + public: + constexpr C() {} // expected-error {{constexpr constructor not allowed in class with virtual base class}} + }; +} + +// - its function-body shall not be a function-try-block; +struct U { + constexpr U() + try // expected-error {{function try block not allowed in constexpr constructor}} + : u() { + } catch (...) { + throw; + } + int u; +}; + +// - the compound-statememt of its function-body shall contain only +struct V { + constexpr V() { + // - null statements, + ; + + // - static_assert-declarations, + static_assert(true, "the impossible happened!"); + + // - typedef declarations and alias-declarations that do not define classes + // or enumerations, + typedef int I; + typedef struct S T; + using J = int; + using K = int[sizeof(I) + sizeof(J)]; + // Note, the standard requires we reject this. + struct U; + + // - using-declarations, + using N::C; + + // - and using-directives; + using namespace N; + } + + constexpr V(int(&)[1]) { + for (int n = 0; n < 10; ++n) // expected-error {{statement not allowed in constexpr constructor}} + /**/; + } + constexpr V(int(&)[2]) { + constexpr int a = 0; // expected-error {{variables cannot be declared in a constexpr constructor}} + } + constexpr V(int(&)[3]) { + constexpr int ForwardDecl(int); // expected-error {{statement not allowed in constexpr constructor}} + } + constexpr V(int(&)[4]) { + typedef struct { } S1; // expected-error {{types cannot be defined in a constexpr constructor}} + } + constexpr V(int(&)[5]) { + using S2 = struct { }; // expected-error {{types cannot be defined in a constexpr constructor}} + } + constexpr V(int(&)[6]) { + struct S3 { }; // expected-error {{types cannot be defined in a constexpr constructor}} + } + constexpr V(int(&)[7]) { + return; // expected-error {{statement not allowed in constexpr constructor}} + } +}; + +// - every non-static data member and base class sub-object shall be initialized +struct W { + int n; // expected-note {{member not initialized by constructor}} + constexpr W() {} // expected-error {{constexpr constructor must initialize all members}} +}; +struct AnonMembers { + int a; // expected-note {{member not initialized by constructor}} + union { // expected-note 2{{member not initialized by constructor}} + char b; + struct { + double c; + long d; // expected-note {{member not initialized by constructor}} + }; + union { + char e; + void *f; + }; + }; + struct { // expected-note {{member not initialized by constructor}} + long long g; + struct { + int h; // expected-note {{member not initialized by constructor}} + double i; // expected-note {{member not initialized by constructor}} + }; + union { // expected-note 2{{member not initialized by constructor}} + char *j; + AnonMembers *k; + }; + }; + + constexpr AnonMembers(int(&)[1]) : a(), b(), g(), h(), i(), j() {} // ok + // missing d, i, j/k union + constexpr AnonMembers(int(&)[2]) : a(), c(), g(), h() {} // expected-error {{constexpr constructor must initialize all members}} + constexpr AnonMembers(int(&)[3]) : a(), e(), g(), h(), i(), k() {} // ok + // missing h, j/k union + constexpr AnonMembers(int(&)[4]) : a(), c(), d(), g(), i() {} // expected-error {{constexpr constructor must initialize all members}} + // missing b/c/d/e/f union + constexpr AnonMembers(int(&)[5]) : a(), g(), h(), i(), k() {} // expected-error {{constexpr constructor must initialize all members}} + // missing a, b/c/d/e/f union, g/h/i/j/k struct + constexpr AnonMembers(int(&)[6]) {} // expected-error {{constexpr constructor must initialize all members}} +}; + +union Empty { + constexpr Empty() {} // ok +} constexpr empty1; + +struct EmptyVariant { + union {}; + struct {}; + constexpr EmptyVariant() {} // ok +} constexpr empty2; + +template<typename T> using Int = int; +template<typename T> +struct TemplateInit { + T a; + int b; // desired-note {{not initialized}} + Int<T> c; // desired-note {{not initialized}} + struct { + T d; + int e; // desired-note {{not initialized}} + Int<T> f; // desired-note {{not initialized}} + }; + struct { + Literal l; + Literal m; + Literal n[3]; + }; + union { // desired-note {{not initialized}} + T g; + T h; + }; + // FIXME: This is ill-formed (no diagnostic required). We should diagnose it. + constexpr TemplateInit() {} // desired-error {{must initialize all members}} +}; +template<typename T> struct TemplateInit2 { + Literal l; + constexpr TemplateInit2() {} // ok +}; + +template<typename T> struct weak_ptr { + constexpr weak_ptr() : p(0) {} + T *p; +}; +template<typename T> struct enable_shared_from_this { + weak_ptr<T> weak_this; + constexpr enable_shared_from_this() {} // ok +}; +constexpr int f(enable_shared_from_this<int>); + +// - every constructor involved in initializing non-static data members and base +// class sub-objects shall be a constexpr constructor. +struct ConstexprBaseMemberCtors : Literal { + Literal l; + + constexpr ConstexprBaseMemberCtors() : Literal(), l() {} // ok + constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor never produces a constant expression}} + Literal(0), // expected-note {{non-constexpr constructor}} + l() {} + constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor never produces a constant expression}} + l(0) // expected-note {{non-constexpr constructor}} + {} +}; + +// - every assignment-expression that is an initializer-caluse appearing +// directly or indirectly within a brace-or-equal-initializer for a non-static +// data member that is not named by a mem-initializer-id shall be a constant +// expression; and +// +// Note, we deliberately do not implement this bullet, so that we can allow the +// following example. (See N3308). +struct X { + int a = 0; + int b = 2 * a + 1; // ok, not a constant expression. + + constexpr X() {} + constexpr X(int c) : a(c) {} // ok, b initialized by 2 * c + 1 +}; + +// - every implicit conversion used in converting a constructor argument to the +// corresponding parameter type and converting a full-expression to the +// corresponding member type shall be one of those allowed in a constant +// expression. +// +// We implement the proposed resolution of DR1364 and ignore this bullet. +// However, we implement the intent of this wording as part of the p5 check that +// the function must be able to produce a constant expression. +int kGlobal; // expected-note {{here}} +struct Z { + constexpr Z(int a) : n(a) {} + constexpr Z() : n(kGlobal) {} // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}} + int n; +}; + + +namespace StdExample { + struct Length { + explicit constexpr Length(int i = 0) : val(i) { } + private: + int val; + }; +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp new file mode 100644 index 0000000..fd17d35 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp @@ -0,0 +1,112 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fcxx-exceptions %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fcxx-exceptions -Wno-invalid-constexpr %s + +namespace StdExample { + +constexpr int f(void *) { return 0; } +constexpr int f(...) { return 1; } +constexpr int g1() { return f(0); } +constexpr int g2(int n) { return f(n); } +constexpr int g3(int n) { return f(n*0); } + +namespace N { + constexpr int c = 5; + constexpr int h() { return c; } +} +constexpr int c = 0; +constexpr int g4() { return N::h(); } + +static_assert(f(0) == 0, ""); +static_assert(f('0') == 1, ""); +static_assert(g1() == 0, ""); +static_assert(g2(0) == 1, ""); +static_assert(g2(1) == 1, ""); +static_assert(g3(0) == 1, ""); +static_assert(g3(1) == 1, ""); +static_assert(N::h() == 5, ""); +static_assert(g4() == 5, ""); + + +constexpr int f(bool b) + { return b ? throw 0 : 0; } // ok +constexpr int f() { return throw 0, 0; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{subexpression}} + +struct B { + constexpr B(int x) : i(0) { } + int i; +}; + +int global; // expected-note {{declared here}} + +struct D : B { + constexpr D() : B(global) { } // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}} +}; + +} + +namespace PotentialConstant { + +constexpr int Comma(int n) { return // expected-error {{constexpr function never produces a constant expression}} + (void)(n * 2), + throw 0, // expected-note {{subexpression}} + 0; +} + +int ng; // expected-note 6{{here}} +constexpr int BinaryOp1(int n) { return n + ng; } // expected-error {{never produces}} expected-note {{read}} +constexpr int BinaryOp2(int n) { return ng + n; } // expected-error {{never produces}} expected-note {{read}} + +double dg; // expected-note 2{{here}} +constexpr double BinaryOp1(double d) { return d + dg; } // expected-error {{never produces}} expected-note {{read}} +constexpr double BinaryOp2(double d) { return dg + d; } // expected-error {{never produces}} expected-note {{read}} + +constexpr int Add(int a, int b, int c) { return a + b + c; } +constexpr int FunctionArgs(int a) { return Add(a, ng, a); } // expected-error {{never produces}} expected-note {{read}} + +struct S { int a; int b; int c[2]; }; +constexpr S InitList(int a) { return { a, ng }; }; // expected-error {{never produces}} expected-note {{read}} +constexpr S InitList1a(int a) { return S{ a, ng }; }; // expected-error {{never produces}} expected-note {{read}} +constexpr S InitList2(int a) { return { a, a, { ng } }; }; // expected-error {{never produces}} expected-note {{read}} +constexpr S InitList3(int a) { return a ? S{ a, a } : S{ a, ng }; }; // ok + +constexpr int LogicalAnd1(int n) { return n && (throw, 0); } // ok +constexpr int LogicalAnd2(int n) { return 1 && (throw, 0); } // expected-error {{never produces}} expected-note {{subexpression}} + +constexpr int LogicalOr1(int n) { return n || (throw, 0); } // ok +constexpr int LogicalOr2(int n) { return 0 || (throw, 0); } // expected-error {{never produces}} expected-note {{subexpression}} + +constexpr int Conditional1(bool b, int n) { return b ? n : ng; } // ok +constexpr int Conditional2(bool b, int n) { return b ? n * ng : n + ng; } // expected-error {{never produces}} expected-note {{both arms of conditional operator are unable to produce a constant expression}} + +// __builtin_constant_p ? : is magical, and is always a potential constant. +constexpr bool BcpCall(int n) { + return __builtin_constant_p((int*)n != &n) ? (int*)n != &n : (int*)n != &n; +} +static_assert(BcpCall(0), ""); + +// DR1311: A function template which can produce a constant expression, but +// for which a particular specialization cannot, is ok. +template<typename T> constexpr T cmin(T a, T b) { + return a < b ? a : b; +} +int n = cmin(3, 5); // ok + +struct X { + constexpr X() {} + bool operator<(X); // not constexpr +}; + +X x = cmin(X(), X()); // ok, not constexpr + +// Same with other temploids. +template<typename T> +struct Y { + constexpr Y() {} + constexpr int get() { return T(); } +}; +struct Z { operator int(); }; + +int y1 = Y<int>().get(); // ok +int y2 = Y<Z>().get(); // ok + +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp new file mode 100644 index 0000000..1a6dc9e --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +namespace N { + typedef char C; +} + +namespace M { + typedef double D; +} + +struct NonLiteral { + NonLiteral() {} + NonLiteral(int) {} // expected-note 2{{here}} + operator int() const { return 0; } +}; +struct Literal { + constexpr Literal() {} + operator int() const { return 0; } +}; + +struct S { + virtual int ImplicitlyVirtual() const; +}; +struct T {}; + +template<typename T> struct ImplicitVirtualFromDependentBase : T { + constexpr int ImplicitlyVirtual() { return 0; } +}; + +constexpr int a = ImplicitVirtualFromDependentBase<S>().ImplicitlyVirtual(); // expected-error {{constant expression}} expected-note {{cannot evaluate virtual function call}} +constexpr int b = ImplicitVirtualFromDependentBase<T>().ImplicitlyVirtual(); // ok +constexpr int c = ImplicitVirtualFromDependentBase<S>().ImplicitVirtualFromDependentBase<S>::ImplicitlyVirtual(); + +template<typename R> struct ConstexprMember { + constexpr R F() { return 0; } +}; +constexpr int d = ConstexprMember<int>().F(); // ok +constexpr int e = ConstexprMember<NonLiteral>().F(); // expected-error {{constant expression}} + +template<typename ...P> struct ConstexprCtor { + constexpr ConstexprCtor(P...) {} +}; +constexpr ConstexprCtor<> f1() { return {}; } // ok +constexpr ConstexprCtor<int> f2() { return 0; } // ok +constexpr ConstexprCtor<NonLiteral> f3() { return { 0 }; } // expected-error {{never produces a constant expression}} expected-note {{non-constexpr constructor 'NonLiteral}} +constexpr ConstexprCtor<int, NonLiteral> f4() { return { 0, 0 }; } // expected-error {{never produces a constant expression}} expected-note {{non-constexpr constructor 'NonLiteral}} + +struct VirtBase : virtual S {}; // expected-note {{here}} + +namespace TemplateVBase { + template<typename T> struct T1 : virtual Literal { // expected-note {{here}} + constexpr T1() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}} + }; + + template<typename T> struct T2 : virtual T { + // FIXME: This is ill-formed (no diagnostic required). + // We should diagnose it now rather than waiting until instantiation. + constexpr T2() {} + }; + constexpr T2<Literal> g2() { return {}; } + + template<typename T> class T3 : public T { // expected-note {{class with virtual base class is not a literal type}} + public: + constexpr T3() {} + }; + constexpr T3<Literal> g3() { return {}; } // ok + constexpr T3<VirtBase> g4() { return {}; } // expected-error {{not a literal type}} +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp new file mode 100644 index 0000000..c4935b3 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct S { + constexpr int f(); + constexpr int g() const; + static constexpr int Sf(); +}; + +void f(const S &s) { + s.f(); + s.g(); + + int (*f)() = &S::Sf; + int (S::*g)() const = &S::g; +} + +namespace std_example { + + class debug_flag { // expected-note {{not an aggregate and has no constexpr constructors}} + public: + explicit debug_flag(bool); + constexpr bool is_on(); // expected-error {{non-literal type 'std_example::debug_flag' cannot have constexpr members}} + private: + bool flag; + }; + + constexpr int bar(int x, int y) // expected-note {{here}} + { return x + y + x*y; } + int bar(int x, int y) // expected-error {{non-constexpr declaration of 'bar' follows constexpr declaration}} + { return x * 2 + 3 * y; } + +} + +// The constexpr specifier is allowed for static member functions of non-literal types. +class NonLiteralClass { + NonLiteralClass(bool); + static constexpr bool isDebugFlag(); +}; diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp new file mode 100644 index 0000000..2412a14 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// A constexpr specifier used in an object declaration declares the object as +// const. +constexpr int a = 0; +extern const int a; + +int i; // expected-note 2{{here}} +constexpr int *b = &i; +extern int *const b; + +constexpr int &c = i; +extern int &c; + +constexpr int (*d)(int) = 0; +extern int (*const d)(int); + +// A variable declaration which uses the constexpr specifier shall have an +// initializer and shall be initialized by a constant expression. +constexpr int ni1; // expected-error {{default initialization of an object of const type 'const int'}} +constexpr struct C { C(); } ni2; // expected-error {{cannot have non-literal type 'const struct C'}} expected-note 3{{has no constexpr constructors}} +constexpr double &ni3; // expected-error {{declaration of reference variable 'ni3' requires an initializer}} + +constexpr int nc1 = i; // expected-error {{constexpr variable 'nc1' must be initialized by a constant expression}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}} +constexpr C nc2 = C(); // expected-error {{cannot have non-literal type 'const C'}} +int &f(); // expected-note {{declared here}} +constexpr int &nc3 = f(); // expected-error {{constexpr variable 'nc3' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f' cannot be used in a constant expression}} +constexpr int nc4(i); // expected-error {{constexpr variable 'nc4' must be initialized by a constant expression}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}} +constexpr C nc5((C())); // expected-error {{cannot have non-literal type 'const C'}} +int &f(); // expected-note {{here}} +constexpr int &nc6(f()); // expected-error {{constexpr variable 'nc6' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f'}} + +struct pixel { + int x, y; +}; +constexpr pixel ur = { 1294, 1024 }; // ok +constexpr pixel origin; // expected-error {{default initialization of an object of const type 'const pixel' requires a user-provided default constructor}} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp new file mode 100644 index 0000000..d7b9eff --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -verify %s + +void f0a(void) { + inline void f1(); // expected-error {{inline declaration of 'f1' not allowed in block scope}} +} + +void f0b(void) { + void f1(); +} + +// FIXME: Add test for "If the inline specifier is used in a friend declaration, +// that declaration shall be a definition or the function shall have previously +// been declared inline. diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp new file mode 100644 index 0000000..07eec1e --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p4.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -verify %s +// XFAIL: * + +void f0() { +} + +inline void f0(); // expected-error {{function definition cannot precede inline declaration}} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp new file mode 100644 index 0000000..ee870d9 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +class A { +public: + explicit A(); + + explicit operator int(); // expected-warning {{explicit conversion functions are a C++11 extension}} + + explicit void f0(); // expected-error {{'explicit' can only be applied to a constructor or conversion function}} + + operator bool(); +}; + +explicit A::A() { } // expected-error {{'explicit' can only be specified inside the class definition}} +explicit A::operator bool() { return false; } // expected-warning {{explicit conversion functions are a C++11 extension}}\ + // expected-error {{'explicit' can only be specified inside the class definition}} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp new file mode 100644 index 0000000..cbb439e --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// A storage-class-specifier shall not be specified in an explicit +// specialization (14.7.3) or an explicit instantiation (14.7.2) +// directive. +template<typename T> void f(T) {} +template<typename T> static void g(T) {} + + +template<> static void f<int>(int); // expected-error{{explicit specialization has extraneous, inconsistent storage class 'static'}} +template static void f<float>(float); // expected-error{{explicit instantiation cannot have a storage class}} + +template<> void f<double>(double); +template void f<long>(long); + +template<> static void g<int>(int); // expected-warning{{explicit specialization cannot have a storage class}} +template static void g<float>(float); // expected-error{{explicit instantiation cannot have a storage class}} + +template<> void g<double>(double); +template void g<long>(long); + +template<typename T> +struct X { + static int value; +}; + +template<typename T> +int X<T>::value = 17; + +template static int X<int>::value; // expected-error{{explicit instantiation cannot have a storage class}} + +template<> static int X<float>::value; // expected-error{{'static' can only be specified inside the class definition}} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p10.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p10.cpp new file mode 100644 index 0000000..fd86276 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p10.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -verify %s +// XFAIL: * + +typedef const int T0; +typedef int& T1; + +struct s0 { + mutable const int f0; // expected-error{{'mutable' and 'const' cannot be mixed}} + mutable T0 f1; // expected-error{{'mutable' and 'const' cannot be mixed}} + mutable int &f2; // expected-error{{'mutable' cannot be applied to references}} + mutable T1 f3; // expected-error{{'mutable' cannot be applied to references}} + mutable struct s1 {}; // expected-error{{'mutable' cannot be applied to non-data members}} + mutable void im0(); // expected-error{{'mutable' cannot be applied to functions}} +}; diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p2.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p2.cpp new file mode 100644 index 0000000..44cc5a7 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p2.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-compat %s + +// The auto or register specifiers can be applied only to names of objects +// declared in a block (6.3) or to function parameters (8.4). + +auto int ao; // expected-error {{illegal storage class on file-scoped variable}} +auto void af(); // expected-error {{illegal storage class on function}} + +register int ro; // expected-error {{illegal storage class on file-scoped variable}} +register void rf(); // expected-error {{illegal storage class on function}} + +struct S { + auto int ao; // expected-error {{storage class specified for a member declaration}} + auto void af(); // expected-error {{storage class specified for a member declaration}} + + register int ro; // expected-error {{storage class specified for a member declaration}} + register void rf(); // expected-error {{storage class specified for a member declaration}} +}; + +void foo(auto int ap, register int rp) { + auto int abo; + auto void abf(); // expected-error {{illegal storage class on function}} + + register int rbo; + register void rbf(); // expected-error {{illegal storage class on function}} +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp new file mode 100644 index 0000000..491ab17 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -verify %s + +struct S; // expected-note 2{{forward declaration of 'S'}} +extern S a; +extern S f(); // expected-note {{'f' declared here}} +extern void g(S a); + +void h() { + g(a); // expected-error {{argument type 'S' is incomplete}} + f(); // expected-error {{calling 'f' with incomplete return type 'S'}} +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2.cpp new file mode 100644 index 0000000..a385aa9 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s -std=c++11 + +struct S { + virtual ~S(); + + void g() throw (auto(*)()->int); + + // Note, this is not permitted: conversion-declarator cannot have a trailing return type. + // FIXME: don't issue the second diagnostic for this. + operator auto(*)()->int(); // expected-error{{'auto' not allowed here}} expected-error {{C++ requires a type specifier}} +}; + +typedef auto Fun(int a) -> decltype(a + a); +typedef auto (*PFun)(int a) -> decltype(a + a); + +void g(auto (*f)() -> int) { + try { } + catch (auto (&f)() -> int) { } + catch (auto (*const f[10])() -> int) { } +} + +namespace std { + class type_info; +} + +template<typename T> struct U {}; + +void j() { + (void)typeid(auto(*)()->void); + (void)sizeof(auto(*)()->void); + (void)__alignof(auto(*)()->void); + + U<auto(*)()->void> v; + + int n; + (void)static_cast<auto(*)()->void>(&j); + auto p = reinterpret_cast<auto(*)()->int>(&j); + (void)const_cast<auto(**)()->int>(&p); + (void)(auto(*)()->void)(&j); +} + +template <auto (*f)() -> void = &j> class C { }; +struct F : auto(*)()->int {}; // expected-error{{expected class name}} +template<typename T = auto(*)()->int> struct G { }; + +int g(); +auto (*h)() -> auto = &g; // expected-error{{'auto' not allowed in function return type}} +auto (*i)() = &g; // ok; auto deduced as int. +auto (*k)() -> int = i; // ok; no deduction. diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp new file mode 100644 index 0000000..1daf02f --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++11-extensions -Wc++11-compat +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}} + if (auto d = d) {} // expected-error {{variable 'd' declared with 'auto' type cannot appear in its own initializer}} + auto e = ({ auto f = e; 0; }); // expected-error {{variable 'e' declared with 'auto' type cannot appear in its own initializer}} +} + +void g() { + auto a; // expected-error{{declaration of variable 'a' with type 'auto' requires an initializer}} + + auto *b; // expected-error{{declaration of variable 'b' with type 'auto *' requires an initializer}} + + if (auto b) {} // expected-error {{must have an initializer}} + for (;auto b;) {} // expected-error {{must have an initializer}} + while (auto b) {} // expected-error {{must have an initializer}} + if (auto b = true) { (void)b; } +} + +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 < b; ++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; + // In C++98: 'auto' storage class specifier is redundant and incompatible with C++0x + // In C++0x: 'auto' storage class specifier is not permitted in C++0x, and will not be supported in future releases + auto int r; // expected-warning {{'auto' storage class specifier}} + + same<__typeof(x), int> xHasTypeInt; + same<__typeof(v), const int*> vHasTypeConstIntPtr; + same<__typeof(u), const int> uHasTypeConstInt; + same<__typeof(y), double> yHasTypeDouble; +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp new file mode 100644 index 0000000..e566d2a --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++11-extensions + +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); + + int arr[] = {1, 2, 3}; + for (auto i : arr) { + } +} + +class X { + static const auto n = 'x'; + + auto m = 0; // expected-error {{'auto' not allowed in non-static class member}} +}; + +struct S { + static const auto a; // expected-error {{declaration of variable 'a' with type 'auto const' requires an initializer}} + static const auto b = 0; + static const int c; +}; +const int S::b; +const auto S::c = 0; diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp new file mode 100644 index 0000000..71f57dc --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s -std=c++11 + +struct S { + virtual ~S(); + + auto a; // expected-error{{'auto' not allowed in non-static struct member}} + auto *b; // expected-error{{'auto' not allowed in non-static struct member}} + const auto c; // expected-error{{'auto' not allowed in non-static struct member}} + + void f() throw (auto); // expected-error{{'auto' not allowed here}} + + friend auto; // expected-error{{'auto' not allowed in non-static struct member}} + + operator auto(); // expected-error{{'auto' not allowed here}} +}; + +// PR 9278: auto is not allowed in typedefs, except with a trailing return type. +typedef auto *AutoPtr; // expected-error{{'auto' not allowed in typedef}} +typedef auto (*PFun)(int a); // expected-error{{'auto' not allowed in typedef}} +typedef auto Fun(int a) -> decltype(a + a); + +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}} +} + +void i(const auto a) { // expected-error{{'auto' not allowed in function prototype}} +} + +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}} + + U<auto> v; // expected-error{{'auto' not allowed in template argument}} + + int n; + (void)dynamic_cast<auto&>(n); // 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 in template argument}} + +using A = auto; // expected-error{{'auto' not allowed in type alias}} + +// FIXME: don't issue the second diagnostic for this error. +auto k() -> auto; // expected-error{{'auto' not allowed in function return type}} unexpected-error{{without trailing return type}} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp new file mode 100644 index 0000000..d327efc --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++11-extensions + +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; + const auto **fail2(p); // expected-error {{variable 'fail2' with type 'auto const **' has incompatible initializer of type 'int **'}} +} + +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; + } +}; + +namespace PR10939 { + struct X { + int method(int); + int method(float); + }; + + template<typename T> T g(T); + + void f(X *x) { + auto value = x->method; // expected-error {{reference to non-static member function must be called}} + if (value) { } + + auto funcptr = &g<int>; + int (*funcptr2)(int) = funcptr; + } +} + +// if the initializer is a braced-init-list, deduce auto as std::initializer_list<T>: +// see SemaCXX/cxx0x-initializer-stdinitializerlist.cpp diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp new file mode 100644 index 0000000..9c1d397 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++98 -Wno-c++11-extensions +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, +#if __has_feature(cxx_trailing_return) + (*b)() -> void, +#endif + c = 0; + auto d = 0, // expected-error {{'auto' deduced as 'int' in declaration of 'd' and deduced as 'double' in declaration of 'f'}} +#if __has_feature(cxx_trailing_return) + (*e)() -> void, +#endif + f = 0.0; +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp new file mode 100644 index 0000000..0271041 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct A { typedef int type; }; +template<typename T> using X = A; // expected-note {{declared here}} +struct X<int>* p2; // expected-error {{elaborated type refers to a type alias template}} + + +template<typename T> using Id = T; // expected-note {{declared here}} +template<template<typename> class F> +struct Y { + struct F<int> i; // expected-error {{elaborated type refers to a type alias template}} + typename F<A>::type j; // ok + + // FIXME: don't produce the diagnostic both for the definition and the instantiation. + template<typename T> using U = F<char>; // expected-note 2{{declared here}} + struct Y<F>::template U<char> k; // expected-error 2{{elaborated type refers to a type alias template}} + typename Y<F>::template U<char> l; // ok +}; +template struct Y<Id>; // expected-note {{requested here}} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp new file mode 100644 index 0000000..8d58498 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class A {}; // expected-note 4 {{previous use is here}} +enum E {}; + +void a1(struct A); +void a2(class A); +void a3(union A); // expected-error {{use of 'A' with tag type that does not match previous declaration}} +void a4(enum A); // expected-error {{use of 'A' with tag type that does not match previous declaration}} + +class A1 { + friend struct A; + friend class A; + friend union A; // expected-error {{use of 'A' with tag type that does not match previous declaration}} + + friend enum A; // expected-error {{use of 'A' with tag type that does not match previous declaration}} + friend enum E; // expected-warning {{cannot be a friend}} +}; + +template <class T> struct B { // expected-note {{previous use is here}} + class Member {}; // expected-note 2 {{previous use is here}} +}; + +template <> class B<int> { + // no type Member +}; + +template <> struct B<A> { + union Member { // expected-note 4 {{previous use is here}} + void* a; + }; +}; + +void b1(struct B<float>); +void b2(class B<float>); +void b3(union B<float>); // expected-error {{use of 'B<float>' with tag type that does not match previous declaration}} +//void b4(enum B<float>); // this just doesn't parse; you can't template an enum directly + +void c1(struct B<float>::Member); +void c2(class B<float>::Member); +void c3(union B<float>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} +void c4(enum B<float>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} + +void d1(struct B<int>::Member); // expected-error {{no struct named 'Member' in 'B<int>'}} +void d2(class B<int>::Member); // expected-error {{no class named 'Member' in 'B<int>'}} +void d3(union B<int>::Member); // expected-error {{no union named 'Member' in 'B<int>'}} +void d4(enum B<int>::Member); // expected-error {{no enum named 'Member' in 'B<int>'}} + +void e1(struct B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} +void e2(class B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} +void e3(union B<A>::Member); +void e4(enum B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} + +template <class T> struct C { + void foo(class B<T>::Member); // expected-error{{no class named 'Member' in 'B<int>'}} \ + // expected-error{{use of 'Member' with tag type that does not match previous declaration}} +}; + +C<float> f1; +C<int> f2; // expected-note {{in instantiation of template class}} +C<A> f3; // expected-note {{in instantiation of template class}} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp new file mode 100644 index 0000000..53227ea --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p4-cxx0x.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -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; +}; + +const int&& foo(); +int i; +struct A { double x; }; +const A* a = new A(); + +static_assert(is_same<decltype(foo()), const int&&>::value, ""); +static_assert(is_same<decltype(i), int>::value, ""); +static_assert(is_same<decltype(a->x), double>::value, ""); +static_assert(is_same<decltype((a->x)), const double&>::value, ""); +static_assert(is_same<decltype(static_cast<int&&>(i)), int&&>::value, ""); + +int f0(int); // expected-note{{possible target}} +float f0(float); // expected-note{{possible target}} + +decltype(f0) f0_a; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp new file mode 100644 index 0000000..2bd5d23 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.simple/p5-cxx0x.cpp @@ -0,0 +1,108 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +namespace std_example { + +template<class T> struct A { ~A() = delete; }; // expected-note {{deleted here}} +template<class T> auto h() -> A<T>; +template<class T> auto i(T) -> T; +template<class T> auto f(T) -> decltype(i(h<T>())); // #1 +template<class T> auto f(T) -> void; // #2 +auto g() -> void { + f(42); // ok, calls #2, since #1 is not viable. +} +template<class T> auto q(T) -> decltype((h<T>())); +void r() { + // Deduction against q succeeds, but results in a temporary which can't be + // destroyed. + q(42); // expected-error {{attempt to use a deleted function}} +} + +} + +class PD { + friend struct A; + ~PD(); // expected-note 4{{here}} +public: + typedef int n; +}; +struct DD { + ~DD() = delete; // expected-note 2{{here}} + typedef int n; +}; + +struct A { + decltype(PD()) s; // ok + decltype(PD())::n n; // ok + decltype(DD()) *p = new decltype(DD()); // ok +}; + +// Two errors here: one for the decltype, one for the variable. +decltype(PD(), PD()) pd1; // expected-error 2{{private destructor}} +decltype(DD(), DD()) dd1; // expected-error 2{{deleted function}} + +decltype(((13, ((DD())))))::n dd_parens; // ok +decltype(((((42)), PD())))::n pd_parens_comma; // ok + +// Ensure parens aren't stripped from a decltype node. +extern decltype(PD()) pd_ref; // ok +decltype((pd_ref)) pd_ref3 = pd_ref; // ok, PD & +decltype(pd_ref) pd_ref2 = pd_ref; // expected-error {{private destructor}} + +namespace libcxx_example { + struct nat { + nat() = delete; + nat(const nat&) = delete; + nat &operator=(const nat&) = delete; + ~nat() = delete; + }; + struct any { + any(...); + }; + + 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> T declval(); + + void swap(int &a, int &b); + nat swap(any, any); + + template<typename T> struct swappable { + typedef decltype(swap(declval<T&>(), declval<T&>())) type; + static const bool value = !is_same<type, nat>::value; + constexpr operator bool() { return value; } + }; + + static_assert(swappable<int>(), ""); + static_assert(!swappable<const int>(), ""); +} + +namespace RequireCompleteType { + template<int N, bool OK> struct S { + static_assert(OK, "boom!"); // expected-error 2{{boom!}} + }; + + template<typename T> T make(); + template<int N, bool OK> S<N, OK> make(); + void consume(...); + + decltype(make<0, false>()) *p1; // ok + decltype((make<1, false>())) *p2; // ok + + // A complete type is required here in order to detect an overloaded 'operator,'. + decltype(123, make<2, false>()) *p3; // expected-note {{here}} + + decltype(consume(make<3, false>())) *p4; // expected-note {{here}} + + decltype(make<decltype(make<4, false>())>()) *p5; // ok +} + +namespace Overload { + DD operator+(PD &a, PD &b); + decltype(PD()) *pd_ptr; + decltype(*pd_ptr + *pd_ptr) *dd_ptr; // ok + + decltype(0, *pd_ptr) pd_ref2 = pd_ref; // ok + DD operator,(int a, PD b); + decltype(0, *pd_ptr) *dd_ptr2; // expected-error {{private destructor}} +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp new file mode 100644 index 0000000..0b518bb --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -fcxx-exceptions + +using X = struct { // ok +}; +template<typename T> using Y = struct { // expected-error {{can not be defined in a type alias template}} +}; + +class K { + virtual ~K(); + operator struct S {} (); // expected-error{{'K::S' can not be defined in a type specifier}} +}; + +struct A {}; + +void f() { + int arr[3] = {1,2,3}; + + for (struct S { S(int) {} } s : arr) { // expected-error {{types may not be defined in a for range declaration}} + } + + new struct T {}; // expected-error {{'T' can not be defined in a type specifier}} + new struct A {}; // expected-error {{'A' can not be defined in a type specifier}} + + try {} catch (struct U {}) {} // expected-error {{'U' can not be defined in a type specifier}} + + (void)(struct V { V(int); })0; // expected-error {{'V' can not be defined in a type specifier}} + + (void)dynamic_cast<struct W {}*>((K*)0); // expected-error {{'W' can not be defined in a type specifier}} + (void)static_cast<struct X {}*>(0); // expected-error {{'X' can not be defined in a type specifier}} + (void)reinterpret_cast<struct Y {}*>(0); // expected-error {{'Y' can not be defined in a type specifier}} + (void)const_cast<struct Z {}*>((const Z*)0); // expected-error {{'Z' can not be defined in a type specifier}} +} + +void g() throw (struct Ex {}) { // expected-error {{'Ex' can not be defined in a type specifier}} +} + +int alignas(struct Aa {}) x; // expected-error {{'Aa' can not be defined in a type specifier}} + +int a = sizeof(struct So {}); // expected-error {{'So' can not be defined in a type specifier}} +int b = alignof(struct Ao {}); // expected-error {{'Ao' can not be defined in a type specifier}} + +namespace std { struct type_info; } +const std::type_info &ti = typeid(struct Ti {}); // expected-error {{'Ti' can not be defined in a type specifier}} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp new file mode 100644 index 0000000..b06eb01 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp @@ -0,0 +1,160 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +namespace RedeclAliasTypedef { + typedef int T; + using T = int; + using T = int; + typedef T T; + using T = T; + typedef int T; +} + +namespace IllegalTypeIds { + using A = void(int n = 0); // expected-error {{default arguments can only be specified for parameters in a function declaration}} + using B = inline void(int n); // expected-error {{type name does not allow function specifier}} + using C = virtual void(int n); // expected-error {{type name does not allow function specifier}} + using D = explicit void(int n); // expected-error {{type name does not allow function specifier}} + using E = void(int n) throw(); // expected-error {{exception specifications are not allowed in type aliases}} + using F = void(*)(int n) &&; // expected-error {{pointer to function type cannot have '&&' qualifier}} + using G = __thread void(int n); // expected-error {{type name does not allow storage class to be specified}} + using H = constexpr int; // expected-error {{type name does not allow constexpr specifier}} + + using Y = void(int n); // ok + using Z = void(int n) &&; // ok +} + +namespace IllegalSyntax { + using ::T = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} + using operator int = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} + using typename U = void; // expected-error {{name defined in alias declaration must be an identifier}} + using typename ::V = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} + using typename ::operator bool = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} +} + +namespace VariableLengthArrays { + using T = int[42]; // ok + + int n = 32; + using T = int[n]; // expected-error {{variable length array declaration not allowed at file scope}} + + const int m = 42; + using U = int[m]; // expected-note {{previous definition}} + using U = int[42]; // ok + using U = int; // expected-error {{type alias redefinition with different types ('int' vs 'int [42]')}} + + void f() { + int n = 42; + goto foo; // expected-error {{goto into protected scope}} + using T = int[n]; // expected-note {{bypasses initialization of VLA type alias}} + foo: ; + } +} + +namespace RedeclFunc { + int f(int, char**); + using T = int; + T f(int, char **); // ok +} + +namespace LookupFilter { + namespace N { struct S; } + using namespace N; + using S = S*; // ok +} + +namespace InFunctions { + template<typename...T> void f0() { + using U = T*; // expected-error {{declaration type contains unexpanded parameter pack 'T'}} + U u; + } + template void f0<int, char>(); + + void f1() { + using T = int; + } + void f2() { + using T = int[-1]; // expected-error {{array size is negative}} + } + + template<typename...T> void f3() { // expected-note {{template parameter is declared here}} + using T = int; // expected-error {{declaration of 'T' shadows template parameter}} + } +} + +namespace ClassNameRedecl { + class C0 { + // FIXME: this diagnostic is pretty poor + using C0 = int; // expected-error {{name defined in alias declaration must be an identifier}} + }; + class C1 { + // FIXME: this diagnostic is pretty poor + using C1 = C1; // expected-error {{name defined in alias declaration must be an identifier}} + }; + class C2 { + using C0 = C1; // ok + }; + template<typename...T> class C3 { + using f = T; // expected-error {{declaration type contains unexpanded parameter pack 'T'}} + }; + template<typename T> class C4 { // expected-note {{template parameter is declared here}} + using T = int; // expected-error {{declaration of 'T' shadows template parameter}} + }; + class C5 { + class c; // expected-note {{previous definition}} + using c = int; // expected-error {{typedef redefinition with different types}} + class d; + using d = d; // ok + }; + class C6 { + class c { using C6 = int; }; // ok + }; +} + +class CtorDtorName { + using X = CtorDtorName; + X(); // expected-error {{expected member name}} + ~X(); // expected-error {{destructor cannot be declared using a type alias}} +}; + +namespace TagName { + using S = struct { int n; }; + using T = class { int n; }; + using U = enum { a, b, c }; + using V = struct V { int n; }; +} + +namespace CWG1044 { + // FIXME: this diagnostic isn't ideal. one diagnostic is enough. + using T = T; // expected-error {{type name requires a specifier}} \ + expected-error {{expected ';' after alias declaration}} +} + +namespace StdExample { + template<typename T, typename U> struct pair; + + using handler_t = void (*)(int); + extern handler_t ignore; + extern void (*ignore)(int); + // FIXME: we know we're parsing a type here; don't recover as if we were + // using operator*. + using cell = pair<void*, cell*>; // expected-error {{use of undeclared identifier 'cell'}} \ + expected-error {{expected expression}} +} + +namespace Access { + class C0 { + using U = int; // expected-note {{declared private here}} + }; + C0::U v; // expected-error {{'U' is a private member}} + class C1 { + public: + using U = int; + }; + C1::U w; // ok +} + +namespace VoidArg { + using V = void; + V f(int); // ok + V g(V); // expected-error {{empty parameter list defined with a type alias of 'void' not allowed}} +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p3.cpp new file mode 100644 index 0000000..28f49d0 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p3.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -verify %s + +typedef struct s { int x; } s; +typedef int I; +typedef int I2; +typedef I2 I; // expected-note {{previous definition is here}} + +typedef char I; // expected-error {{typedef redefinition with different types}} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp new file mode 100644 index 0000000..c16ba20 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p4.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify %s + +struct S { + typedef struct A {} A; // expected-note {{previous definition is here}} + typedef struct B B; + typedef A A; // expected-error {{redefinition of 'A'}} + + struct C { }; + typedef struct C OtherC; + typedef OtherC C; + + typedef struct D { } D2; + typedef D2 D; +}; + diff --git a/clang/test/CXX/dcl.dcl/p4-0x.cpp b/clang/test/CXX/dcl.dcl/p4-0x.cpp new file mode 100644 index 0000000..31d4912 --- /dev/null +++ b/clang/test/CXX/dcl.dcl/p4-0x.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only %s + +struct S { + constexpr S(bool b) : b(b) {} + constexpr explicit operator bool() { return b; } + bool b; +}; +struct T { + constexpr operator int() { return 1; } +}; +struct U { + constexpr operator int() { return 1; } // expected-note {{candidate}} + constexpr operator long() { return 0; } // expected-note {{candidate}} +}; + +static_assert(S(true), ""); +static_assert(S(false), "not so fast"); // expected-error {{not so fast}} +static_assert(T(), ""); +static_assert(U(), ""); // expected-error {{ambiguous}} + +static_assert(false, L"\x14hi" "!" R"x(")x"); // expected-error {{static_assert failed L"\024hi!\""}} diff --git a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp new file mode 100644 index 0000000..06dd1bb --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// An explicitly-defaulted function may be declared constexpr only if it would +// have been implicitly declared as constexpr. +struct S1 { + constexpr S1() = default; // expected-error {{defaulted definition of default constructor is not constexpr}} + constexpr S1(const S1&) = default; + constexpr S1(S1&&) = default; + constexpr S1 &operator=(const S1&) = default; // expected-error {{explicitly-defaulted copy assignment operator may not have}} + constexpr S1 &operator=(S1&&) = default; // expected-error {{explicitly-defaulted move assignment operator may not have}} + constexpr ~S1() = default; // expected-error {{destructor cannot be marked constexpr}} + int n; +}; +struct NoCopyMove { + constexpr NoCopyMove() {} + NoCopyMove(const NoCopyMove&); + NoCopyMove(NoCopyMove&&); +}; +struct S2 { + constexpr S2() = default; + constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor is not constexpr}} + constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor is not constexpr}} + NoCopyMove ncm; +}; + +// If a function is explicitly defaulted on its first declaration +// -- it is implicitly considered to be constexpr if the implicit declaration +// would be +struct S3 { + S3() = default; // expected-note {{here}} + S3(const S3&) = default; + S3(S3&&) = default; + constexpr S3(int n) : n(n) {} + int n; +}; +constexpr S3 s3a = S3(0); +constexpr S3 s3b = s3a; +constexpr S3 s3c = S3(); +constexpr S3 s3d; // expected-error {{constant expression}} expected-note {{non-constexpr constructor}} + +struct S4 { + S4() = default; + S4(const S4&) = default; // expected-note {{here}} + S4(S4&&) = default; // expected-note {{here}} + NoCopyMove ncm; +}; +constexpr S4 s4a; // ok +constexpr S4 s4b = S4(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor}} +constexpr S4 s4c = s4a; // expected-error {{constant expression}} expected-note {{non-constexpr constructor}} + +struct S5 { + constexpr S5(); + int n = 1, m = n + 3; +}; +constexpr S5::S5() = default; +static_assert(S5().m == 4, ""); diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp new file mode 100644 index 0000000..7764980 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp @@ -0,0 +1,78 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// An aggregate is an array or a class... +struct Aggr { +private: + static const int n; + void f(); +protected: + struct Inner { int m; }; +public: + bool &br; // expected-note {{default constructor of 'Aggr' is implicitly deleted because field 'br' of reference type 'bool &' would not be initialized}} +}; +bool b; +Aggr ag = { b }; + +// with no user-provided constructors, ... +struct NonAggr1a { // expected-note 2 {{candidate constructor}} + NonAggr1a(int, int); // expected-note {{candidate constructor}} + int k; +}; +// In C++0x, 'user-provided' is only defined for special member functions, so +// this type is considered to be an aggregate. This is considered to be +// a language defect. +NonAggr1a na1a = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr1a'}} + +struct NonAggr1b { + NonAggr1b(const NonAggr1b &); // expected-note {{candidate constructor}} + int k; +}; +NonAggr1b na1b = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr1b'}} + +// no brace-or-equal-initializers for non-static data members, ... +struct NonAggr2 { // expected-note 3 {{candidate constructor}} + int m = { 123 }; +}; +NonAggr2 na2 = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr2'}} + +// no private... +struct NonAggr3 { // expected-note 3 {{candidate constructor}} +private: + int n; +}; +NonAggr3 na3 = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr3'}} + +// or protected non-static data members, ... +struct NonAggr4 { // expected-note 3 {{candidate constructor}} +protected: + int n; +}; +NonAggr4 na4 = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr4'}} + +// no base classes, ... +struct NonAggr5 : Aggr { // expected-note 3 {{candidate constructor}} +}; +NonAggr5 na5 = { b }; // expected-error {{no matching constructor for initialization of 'NonAggr5'}} +template<typename...BaseList> +struct MaybeAggr5a : BaseList... {}; // expected-note {{default constructor of 'MaybeAggr5a<Aggr>' is implicitly deleted because base class 'Aggr' has a deleted default constructor}} +MaybeAggr5a<> ma5a0 = {}; // ok +MaybeAggr5a<Aggr> ma5a1 = {}; // expected-error {{call to implicitly-deleted default constructor of 'MaybeAggr5a<Aggr>'}} + +// and no virtual functions. +struct NonAggr6 { // expected-note 3 {{candidate constructor}} + virtual void f(); + int n; +}; +NonAggr6 na6 = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr6'}} + +struct DefaultedAggr { + int n; + + DefaultedAggr() = default; + DefaultedAggr(const DefaultedAggr &) = default; + DefaultedAggr(DefaultedAggr &&) = default; + DefaultedAggr &operator=(const DefaultedAggr &) = default; + DefaultedAggr &operator=(DefaultedAggr &) = default; + ~DefaultedAggr() = default; +}; +DefaultedAggr da = { 42 } ; diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p4.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p4.cpp new file mode 100644 index 0000000..1041571 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p4.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -pedantic -Werror %s +int a1[] = { 1, 3, 5 }; +void f() { + int a2[] = { 1, 3, 5 }; +} +template <typename T> +void tf() { + T t; + // Element type may be dependent + T a3[] = { 1, 3, 5 }; + // As might be the initializer list, value + int a5[] = { sizeof(T) }; + // or even type. + int a6[] = { t.get() }; +} + +// Allowed by GNU extension +int a4[] = {}; // expected-error {{zero size arrays}} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp new file mode 100644 index 0000000..b30e0ec --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +void f0() { + int &ir = { 17 }; // expected-error{{reference to type 'int' cannot bind to an initializer list}} +} + +namespace PR12453 { + template<typename T> + void f(int i) { + T x{i}; // expected-error{{non-constant-expression cannot be narrowed from type 'int' to 'float' in initializer list}} \ + // expected-note{{override this message by inserting an explicit cast}} + T y{i}; // expected-error{{non-constant-expression cannot be narrowed from type 'int' to 'float' in initializer list}} \ + // expected-note{{override this message by inserting an explicit cast}} + } + + template void f<float>(int); // expected-note{{in instantiation of function template specialization 'PR12453::f<float>' requested here}} +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp new file mode 100644 index 0000000..0bea4ed --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -Wc++11-compat -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s + +// Verify that the appropriate fixits are emitted for narrowing conversions in +// initializer lists. + +typedef short int16_t; + +void fixits() { + int x = 999; + struct {char c;} c2 = {x}; + // CHECK: warning:{{.*}} cannot be narrowed + // CHECK: fix-it:{{.*}}:26}:"static_cast<char>(" + // CHECK: fix-it:{{.*}}:27}:")" + struct {int16_t i;} i16 = {70000}; + // CHECK: warning:{{.*}} cannot be narrowed + // CHECK: fix-it:{{.*}}:30}:"static_cast<int16_t>(" + // CHECK: fix-it:{{.*}}:35}:")" +} + +template<typename T> +void maybe_shrink_int(T t) { + struct {T t;} t2 = {700}; +} + +void test_template() { + maybe_shrink_int((char)3); + // CHECK: warning:{{.*}} cannot be narrowed + // CHECK: note:{{.*}} in instantiation + // CHECK: note:{{.*}} override + // FIXME: This should be static_cast<T>. + // CHECK: fix-it:{{.*}}"static_cast<char>(" + // CHECK: fix-it:{{.*}}")" +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp new file mode 100644 index 0000000..db20ea6 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x.cpp @@ -0,0 +1,209 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -triple x86_64-apple-macosx10.6.7 -verify %s + +// Verify that narrowing conversions in initializer lists cause errors in C++0x +// mode. + +void std_example() { + int x = 999; // x is not a constant expression + const int y = 999; + const int z = 99; + char c1 = x; // OK, though it might narrow (in this case, it does narrow) + char c2{x}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + char c3{y}; // expected-error {{ cannot be narrowed }} expected-note {{override}} expected-warning {{changes value}} + char c4{z}; // OK: no narrowing needed + unsigned char uc1 = {5}; // OK: no narrowing needed + unsigned char uc2 = {-1}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + unsigned int ui1 = {-1}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + signed int si1 = + { (unsigned int)-1 }; // expected-error {{ cannot be narrowed }} expected-note {{override}} + int ii = {2.0}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + float f1 { x }; // expected-error {{ cannot be narrowed }} expected-note {{override}} + float f2 { 7 }; // OK: 7 can be exactly represented as a float + int f(int); + int a[] = + { 2, f(2), f(2.0) }; // OK: the double-to-int conversion is not at the top level +} + +// Test each rule individually. + +template<typename T> +struct Agg { + T t; +}; + +template<typename T> +struct Convert { + constexpr Convert(T v) : v(v) {} + constexpr operator T() const { return v; } + T v; +}; +template<typename T> Convert<T> ConvertVar(); + +// C++0x [dcl.init.list]p7: A narrowing conversion is an implicit conversion +// +// * from a floating-point type to an integer type, or + +void float_to_int() { + Agg<char> a1 = {1.0F}; // expected-error {{type 'float' cannot be narrowed to 'char'}} expected-note {{override}} + Agg<char> a2 = {1.0}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + Agg<char> a3 = {1.0L}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + + float f = 1.0; + double d = 1.0; + long double ld = 1.0; + Agg<char> a4 = {f}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + Agg<char> a5 = {d}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + Agg<char> a6 = {ld}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + + Agg<char> ce1 = { Convert<float>(1.0) }; // expected-error {{type 'float' cannot be narrowed to 'char'}} expected-note {{override}} + Agg<char> ce2 = { ConvertVar<double>() }; // expected-error {{type 'double' cannot be narrowed to 'char'}} expected-note {{override}} +} + +// * from long double to double or float, or from double to float, except where +// the source is a constant expression and the actual value after conversion +// is within the range of values that can be represented (even if it cannot be +// represented exactly), or + +void shrink_float() { + // These aren't constant expressions. + float f = 1.0; + double d = 1.0; + long double ld = 1.0; + + // Variables. + Agg<float> f1 = {f}; // OK (no-op) + Agg<float> f2 = {d}; // expected-error {{non-constant-expression cannot be narrowed from type 'double' to 'float'}} expected-note {{override}} + Agg<float> f3 = {ld}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + // Exact constants. + Agg<float> f4 = {1.0}; // OK (double constant represented exactly) + Agg<float> f5 = {1.0L}; // OK (long double constant represented exactly) + // Inexact but in-range constants. + Agg<float> f6 = {0.1}; // OK (double constant in range but rounded) + Agg<float> f7 = {0.1L}; // OK (long double constant in range but rounded) + // Out of range constants. + Agg<float> f8 = {1E50}; // expected-error {{constant expression evaluates to 1.000000e+50 which cannot be narrowed to type 'float'}} expected-note {{override}} + Agg<float> f9 = {1E50L}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + // More complex constant expression. + constexpr long double e40 = 1E40L, e30 = 1E30L, e39 = 1E39L; + Agg<float> f10 = {e40 - 5 * e39 + e30 - 5 * e39}; // OK + + // Variables. + Agg<double> d1 = {f}; // OK (widening) + Agg<double> d2 = {d}; // OK (no-op) + Agg<double> d3 = {ld}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + // Exact constant. + Agg<double> d4 = {1.0L}; // OK (long double constant represented exactly) + // Inexact but in-range constant. + Agg<double> d5 = {0.1L}; // OK (long double constant in range but rounded) + // Out of range constant. + Agg<double> d6 = {1E315L}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + // More complex constant expression. + constexpr long double e315 = 1E315L, e305 = 1E305L, e314 = 1E314L; + Agg<double> d7 = {e315 - 5 * e314 + e305 - 5 * e314}; // OK + + Agg<float> ce1 = { Convert<double>(1e300) }; // expected-error {{constant expression evaluates to 1.000000e+300 which cannot be narrowed to type 'float'}} expected-note {{override}} + Agg<double> ce2 = { ConvertVar<long double>() }; // expected-error {{non-constant-expression cannot be narrowed from type 'long double' to 'double'}} expected-note {{override}} +} + +// * from an integer type or unscoped enumeration type to a floating-point type, +// except where the source is a constant expression and the actual value after +// conversion will fit into the target type and will produce the original +// value when converted back to the original type, or +void int_to_float() { + // Not a constant expression. + char c = 1; + + // Variables. Yes, even though all char's will fit into any floating type. + Agg<float> f1 = {c}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + Agg<double> f2 = {c}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + Agg<long double> f3 = {c}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + + // Constants. + Agg<float> f4 = {12345678}; // OK (exactly fits in a float) + Agg<float> f5 = {123456789}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + + Agg<float> ce1 = { Convert<int>(123456789) }; // expected-error {{constant expression evaluates to 123456789 which cannot be narrowed to type 'float'}} expected-note {{override}} + Agg<double> ce2 = { ConvertVar<long long>() }; // expected-error {{non-constant-expression cannot be narrowed from type 'long long' to 'double'}} expected-note {{override}} +} + +// * from an integer type or unscoped enumeration type to an integer type that +// cannot represent all the values of the original type, except where the +// source is a constant expression and the actual value after conversion will +// fit into the target type and will produce the original value when converted +// back to the original type. +void shrink_int() { + // Not a constant expression. + short s = 1; + unsigned short us = 1; + Agg<char> c1 = {s}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + Agg<unsigned short> s1 = {s}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + Agg<short> s2 = {us}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + + // "that cannot represent all the values of the original type" means that the + // validity of the program depends on the relative sizes of integral types. + // This test compiles with -m64, so sizeof(int)<sizeof(long)==sizeof(long + // long). + long l1 = 1; + Agg<int> i1 = {l1}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + long long ll = 1; + Agg<long> l2 = {ll}; // OK + + // Constants. + Agg<char> c2 = {127}; // OK + Agg<char> c3 = {300}; // expected-error {{ cannot be narrowed }} expected-note {{override}} expected-warning {{changes value}} + + Agg<int> i2 = {0x7FFFFFFFU}; // OK + Agg<int> i3 = {0x80000000U}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + Agg<unsigned int> i4 = {-0x80000000L}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + + // Bool is also an integer type, but conversions to it are a different AST + // node. + Agg<bool> b1 = {0}; // OK + Agg<bool> b2 = {1}; // OK + Agg<bool> b3 = {-1}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + + // Conversions from pointers to booleans aren't narrowing conversions. + Agg<bool> b = {&b1}; // OK + + Agg<short> ce1 = { Convert<int>(100000) }; // expected-error {{constant expression evaluates to 100000 which cannot be narrowed to type 'short'}} expected-note {{override}} expected-warning {{changes value from 100000 to -31072}} + Agg<char> ce2 = { ConvertVar<short>() }; // expected-error {{non-constant-expression cannot be narrowed from type 'short' to 'char'}} expected-note {{override}} +} + +// Be sure that type- and value-dependent expressions in templates get the error +// too. + +template<int I, typename T> +void maybe_shrink_int(T t) { + Agg<short> s1 = {t}; // expected-error {{ cannot be narrowed }} expected-note {{override}} + Agg<short> s2 = {I}; // expected-error {{ cannot be narrowed }} expected-note {{override}} expected-warning {{changes value}} + Agg<T> t2 = {700}; // expected-error {{ cannot be narrowed }} expected-note {{override}} expected-warning {{changes value}} +} + +void test_template() { + maybe_shrink_int<15>((int)3); // expected-note {{in instantiation}} + maybe_shrink_int<70000>((char)3); // expected-note {{in instantiation}} +} + + +// We don't want qualifiers on the types in the diagnostic. + +void test_qualifiers(int i) { + const int j = i; + struct {const unsigned char c;} c1 = {j}; // expected-error {{from type 'int' to 'unsigned char' in}} expected-note {{override}} + // Template arguments make it harder to avoid printing qualifiers: + Agg<const unsigned char> c2 = {j}; // expected-error {{from type 'int' to 'const unsigned char' in}} expected-note {{override}} +} + +// Test SFINAE checks. +template<unsigned> struct Value { }; + +template<typename T> +int &check_narrowed(Value<sizeof((T){1.1})>); + +template<typename T> +float &check_narrowed(...); + +void test_narrowed(Value<sizeof(int)> vi, Value<sizeof(double)> vd) { + int &ir = check_narrowed<double>(vd); + float &fr = check_narrowed<int>(vi); +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp new file mode 100644 index 0000000..4bcf113 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-cxx11-nowarn.cpp @@ -0,0 +1,210 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wno-error=c++11-narrowing -triple x86_64-apple-macosx10.6.7 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wno-error=narrowing -triple x86_64-apple-macosx10.6.7 -verify %s + +// Verify that narrowing conversions in initializer lists cause errors in C++0x +// mode. + +void std_example() { + int x = 999; // x is not a constant expression + const int y = 999; + const int z = 99; + char c1 = x; // OK, though it might narrow (in this case, it does narrow) + char c2{x}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + char c3{y}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} expected-warning {{changes value}} + char c4{z}; // OK: no narrowing needed + unsigned char uc1 = {5}; // OK: no narrowing needed + unsigned char uc2 = {-1}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + unsigned int ui1 = {-1}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + signed int si1 = + { (unsigned int)-1 }; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + int ii = {2.0}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + float f1 { x }; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + float f2 { 7 }; // OK: 7 can be exactly represented as a float + int f(int); + int a[] = + { 2, f(2), f(2.0) }; // OK: the double-to-int conversion is not at the top level +} + +// Test each rule individually. + +template<typename T> +struct Agg { + T t; +}; + +template<typename T> +struct Convert { + constexpr Convert(T v) : v(v) {} + constexpr operator T() const { return v; } + T v; +}; +template<typename T> Convert<T> ConvertVar(); + +// C++0x [dcl.init.list]p7: A narrowing conversion is an implicit conversion +// +// * from a floating-point type to an integer type, or + +void float_to_int() { + Agg<char> a1 = {1.0F}; // expected-warning {{type 'float' cannot be narrowed to 'char'}} expected-note {{override}} + Agg<char> a2 = {1.0}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<char> a3 = {1.0L}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + float f = 1.0; + double d = 1.0; + long double ld = 1.0; + Agg<char> a4 = {f}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<char> a5 = {d}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<char> a6 = {ld}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + Agg<char> ce1 = { Convert<float>(1.0) }; // expected-warning {{type 'float' cannot be narrowed to 'char'}} expected-note {{override}} + Agg<char> ce2 = { ConvertVar<double>() }; // expected-warning {{type 'double' cannot be narrowed to 'char'}} expected-note {{override}} +} + +// * from long double to double or float, or from double to float, except where +// the source is a constant expression and the actual value after conversion +// is within the range of values that can be represented (even if it cannot be +// represented exactly), or + +void shrink_float() { + // These aren't constant expressions. + float f = 1.0; + double d = 1.0; + long double ld = 1.0; + + // Variables. + Agg<float> f1 = {f}; // OK (no-op) + Agg<float> f2 = {d}; // expected-warning {{non-constant-expression cannot be narrowed from type 'double' to 'float'}} expected-note {{override}} + Agg<float> f3 = {ld}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + // Exact constants. + Agg<float> f4 = {1.0}; // OK (double constant represented exactly) + Agg<float> f5 = {1.0L}; // OK (long double constant represented exactly) + // Inexact but in-range constants. + Agg<float> f6 = {0.1}; // OK (double constant in range but rounded) + Agg<float> f7 = {0.1L}; // OK (long double constant in range but rounded) + // Out of range constants. + Agg<float> f8 = {1E50}; // expected-warning {{constant expression evaluates to 1.000000e+50 which cannot be narrowed to type 'float'}} expected-note {{override}} + Agg<float> f9 = {1E50L}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + // More complex constant expression. + constexpr long double e40 = 1E40L, e30 = 1E30L, e39 = 1E39L; + Agg<float> f10 = {e40 - 5 * e39 + e30 - 5 * e39}; // OK + + // Variables. + Agg<double> d1 = {f}; // OK (widening) + Agg<double> d2 = {d}; // OK (no-op) + Agg<double> d3 = {ld}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + // Exact constant. + Agg<double> d4 = {1.0L}; // OK (long double constant represented exactly) + // Inexact but in-range constant. + Agg<double> d5 = {0.1L}; // OK (long double constant in range but rounded) + // Out of range constant. + Agg<double> d6 = {1E315L}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + // More complex constant expression. + constexpr long double e315 = 1E315L, e305 = 1E305L, e314 = 1E314L; + Agg<double> d7 = {e315 - 5 * e314 + e305 - 5 * e314}; // OK + + Agg<float> ce1 = { Convert<double>(1e300) }; // expected-warning {{constant expression evaluates to 1.000000e+300 which cannot be narrowed to type 'float'}} expected-note {{override}} + Agg<double> ce2 = { ConvertVar<long double>() }; // expected-warning {{non-constant-expression cannot be narrowed from type 'long double' to 'double'}} expected-note {{override}} +} + +// * from an integer type or unscoped enumeration type to a floating-point type, +// except where the source is a constant expression and the actual value after +// conversion will fit into the target type and will produce the original +// value when converted back to the original type, or +void int_to_float() { + // Not a constant expression. + char c = 1; + + // Variables. Yes, even though all char's will fit into any floating type. + Agg<float> f1 = {c}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<double> f2 = {c}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<long double> f3 = {c}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + // Constants. + Agg<float> f4 = {12345678}; // OK (exactly fits in a float) + Agg<float> f5 = {123456789}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + Agg<float> ce1 = { Convert<int>(123456789) }; // expected-warning {{constant expression evaluates to 123456789 which cannot be narrowed to type 'float'}} expected-note {{override}} + Agg<double> ce2 = { ConvertVar<long long>() }; // expected-warning {{non-constant-expression cannot be narrowed from type 'long long' to 'double'}} expected-note {{override}} +} + +// * from an integer type or unscoped enumeration type to an integer type that +// cannot represent all the values of the original type, except where the +// source is a constant expression and the actual value after conversion will +// fit into the target type and will produce the original value when converted +// back to the original type. +void shrink_int() { + // Not a constant expression. + short s = 1; + unsigned short us = 1; + Agg<char> c1 = {s}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<unsigned short> s1 = {s}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<short> s2 = {us}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + // "that cannot represent all the values of the original type" means that the + // validity of the program depends on the relative sizes of integral types. + // This test compiles with -m64, so sizeof(int)<sizeof(long)==sizeof(long + // long). + long l1 = 1; + Agg<int> i1 = {l1}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + long long ll = 1; + Agg<long> l2 = {ll}; // OK + + // Constants. + Agg<char> c2 = {127}; // OK + Agg<char> c3 = {300}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} expected-warning {{changes value}} + + Agg<int> i2 = {0x7FFFFFFFU}; // OK + Agg<int> i3 = {0x80000000U}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<unsigned int> i4 = {-0x80000000L}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + // Bool is also an integer type, but conversions to it are a different AST + // node. + Agg<bool> b1 = {0}; // OK + Agg<bool> b2 = {1}; // OK + Agg<bool> b3 = {-1}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + + // Conversions from pointers to booleans aren't narrowing conversions. + Agg<bool> b = {&b1}; // OK + + Agg<short> ce1 = { Convert<int>(100000) }; // expected-warning {{constant expression evaluates to 100000 which cannot be narrowed to type 'short'}} expected-note {{override}} expected-warning {{changes value from 100000 to -31072}} + Agg<char> ce2 = { ConvertVar<short>() }; // expected-warning {{non-constant-expression cannot be narrowed from type 'short' to 'char'}} expected-note {{override}} +} + +// Be sure that type- and value-dependent expressions in templates get the warning +// too. + +template<int I, typename T> +void maybe_shrink_int(T t) { + Agg<short> s1 = {t}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} + Agg<short> s2 = {I}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} expected-warning {{changes value}} + Agg<T> t2 = {700}; // expected-warning {{ cannot be narrowed }} expected-note {{override}} expected-warning {{changes value}} +} + +void test_template() { + maybe_shrink_int<15>((int)3); // expected-note {{in instantiation}} + maybe_shrink_int<70000>((char)3); // expected-note {{in instantiation}} +} + + +// We don't want qualifiers on the types in the diagnostic. + +void test_qualifiers(int i) { + const int j = i; + struct {const unsigned char c;} c1 = {j}; // expected-warning {{from type 'int' to 'unsigned char' in}} expected-note {{override}} + // Template arguments make it harder to avoid printing qualifiers: + Agg<const unsigned char> c2 = {j}; // expected-warning {{from type 'int' to 'const unsigned char' in}} expected-note {{override}} +} + +// Make sure we still get the right SFINAE behavior. +template<unsigned> struct Value { }; + +template<typename T> +int &check_narrowed(Value<sizeof((T){1.1})>); + +template<typename T> +float &check_narrowed(...); + +void test_narrowed(Value<sizeof(int)> vi, Value<sizeof(double)> vd) { + int &ir = check_narrowed<double>(vd); + float &fr = check_narrowed<int>(vi); +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/basic.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/basic.cpp new file mode 100644 index 0000000..885d11b --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/basic.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5787 +class C { + public: + ~C() {} +}; + +template <typename T> +class E { + public: + E& Foo(const C&); + E& Bar() { return Foo(C()); } +}; + +void Test() { + E<int> e; + e.Bar(); +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp new file mode 100644 index 0000000..20c059e --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +int g(int); +void f() { + int i; + int& r = i; + r = 1; + int* p = &r; + int &rr=r; + int (&rg)(int) = g; + rg(i); + int a[3]; + int (&ra)[3] = a; + ra[1] = i; +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp new file mode 100644 index 0000000..47e215a --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +int& r1; // expected-error{{declaration of reference variable 'r1' requires an initializer}} +extern int& r2; diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp new file mode 100644 index 0000000..adbdff6 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp @@ -0,0 +1,194 @@ +// RUN: %clang_cc1 -std=c++11 -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 2{{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{{candidate function not viable: no known conversion from 'ConvertsTo<int &>' to 'int &&' for 1st argument}} \ + // expected-note{{candidate function not viable: no known conversion from 'ConvertsTo<float &>' to 'int &&' for 1st argument}} + + 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 matching function for call to 'int_rvalue_ref'}} + int_rvalue_ref(ConvertsTo<float&>()); // expected-error{{no matching function for call to 'int_rvalue_ref'}} + } + +} + +namespace pr10644 { + struct string { + string(const char* __s); + }; + class map { + int& operator[](const string& __k); + public: + int& operator[](const string&& __k); + }; + void foo() { + static map key_map; + key_map["line"]; + } +} + +namespace PR11003 { + class Value { + }; + struct MoveRef { + operator Value &() const ; + }; + MoveRef Move(int); + void growTo() { + Value x = Move(0); + Value y(Move(0)); + } +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp new file mode 100644 index 0000000..d58a129 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-show-option -verify %s + +// C++03 requires that we check for a copy constructor when binding a +// reference to a temporary, since we are allowed to make a copy, Even +// though we don't actually make that copy, make sure that we diagnose +// cases where that copy constructor is somehow unavailable. As an +// extension, this is only a warning. + +struct X1 { + X1(); + explicit X1(const X1&); +}; + +struct X2 { + X2(); + +private: + X2(const X2&); // expected-note{{declared private here}} +}; + +struct X3 { + X3(); + +private: + X3(X3&); // expected-note{{candidate constructor not viable: no known conversion from 'X3' to 'X3 &' for 1st argument}} +}; + +// Check for instantiation of default arguments +template<typename T> +T get_value_badly() { + double *dp = 0; + // The extension doesn't extend far enough to turn this error into a warning. + T *tp = dp; // expected-error{{cannot initialize a variable of type 'int *' with an lvalue of type 'double *'}} + return T(); +} + +template<typename T> +struct X4 { + X4(); + X4(const X4&, T = get_value_badly<T>()); // expected-note{{in instantiation of}} +}; + +// Check for "dangerous" default arguments that could cause recursion. +struct X5 { + X5(); + X5(const X5&, const X5& = X5()); // expected-warning{{no viable constructor copying parameter of type 'X5'}} +}; + +void g1(const X1&); +void g2(const X2&); +void g3(const X3&); +void g4(const X4<int>&); +void g5(const X5&); + +void test() { + 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}} + g3(X3()); // expected-warning{{no viable constructor copying parameter of type 'X3'}} + g4(X4<int>()); + g5(X5()); // Generates a warning in the default argument. +} + +// Check that unavailable copy constructors still cause SFINAE failures. +template<int> struct int_c { }; + +template<typename T> T f(const T&); + +// Would be ambiguous with the next g(), except the instantiation failure in +// sizeof() prevents that. +template<typename T> +int &g(int_c<sizeof(f(T()))> * = 0); + +template<typename T> float &g(); + +void h() { + float &fp2 = g<X3>(); // Not ambiguous. +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx0x-no-extra-copy.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx0x-no-extra-copy.cpp new file mode 100644 index 0000000..27eb6d1 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx0x-no-extra-copy.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// C++03 requires that we check for a copy constructor when binding a +// reference to a reference-compatible rvalue, since we are allowed to +// make a copy. C++0x does not permit the copy, so ensure that we +// don't diagnose cases where the copy constructor is unavailable. + +struct X1 { + X1(); + explicit X1(const X1&); +}; + +struct X2 { + X2(); + +private: + X2(const X2&); +}; + +struct X3 { + X3(); + +private: + X3(X3&); +}; + +template<typename T> +T get_value_badly() { + double *dp = 0; + T *tp = dp; + return T(); +} + +template<typename T> +struct X4 { + X4(); + X4(const X4&, T = get_value_badly<T>()); +}; + +void g1(const X1&); +void g2(const X2&); +void g3(const X3&); +void g4(const X4<int>&); + +void test() { + g1(X1()); + g2(X2()); + g3(X3()); + g4(X4<int>()); +} + +// Check that unavailable copy constructors do not cause SFINAE failures. +template<int> struct int_c { }; + +template<typename T> T f(const T&); + +template<typename T> +int &g(int_c<sizeof(f(T()))> * = 0); // expected-note{{candidate function [with T = X3]}} + +template<typename T> float &g(); // expected-note{{candidate function [with T = X3]}} + +void h() { + float &fp = g<X3>(); // expected-error{{call to 'g' is ambiguous}} +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp new file mode 100644 index 0000000..08d9639 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -ast-dump %s 2>&1 | FileCheck %s + +// CHECK: example0 +void example0() { + double d = 2.0; + // CHECK: double &rd = + // CHECK-NEXT: DeclRefExpr + double &rd = d; + // CHECK: const double &rcd = + // CHECK-NEXT: ImplicitCastExpr{{.*}}'const double' lvalue <NoOp> + const double &rcd = d; +} + +struct A { }; +struct B : A { } b; + +// CHECK: example1 +void example1() { + // CHECK: A &ra = + // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue <DerivedToBase (A)> + A &ra = b; + // CHECK: const A &rca = + // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <NoOp> + // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue <DerivedToBase (A)> + const A& rca = b; +} + +extern B f(); + +struct X { + operator B(); +} x; + +// CHECK: example2 +void example2() { + // CHECK: const A &rca = + // CHECK: ImplicitCastExpr{{.*}}'const struct A' <NoOp> + // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)> + // CHECK: CallExpr{{.*}}B + const A &rca = f(); + // CHECK: const A &r = + // CHECK: ImplicitCastExpr{{.*}}'const struct A' <NoOp> + // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)> + // CHECK: CXXMemberCallExpr{{.*}}'struct B' + const A& r = x; +} + +// CHECK: example3 +void example3() { + // CHECK: const double &rcd2 = + // CHECK: ImplicitCastExpr{{.*}} <IntegralToFloating> + const double& rcd2 = 2; +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp new file mode 100644 index 0000000..fee5f96 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp @@ -0,0 +1,135 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct Base { }; +struct Derived : Base { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}} +struct Unrelated { }; +struct Derived2 : Base { }; +struct Diamond : Derived, Derived2 { }; + +struct ConvertibleToBaseRef { + operator Base&() const; +}; + +struct ConvertibleToDerivedRef { + operator Derived&() const; +}; + +struct ConvertibleToBothDerivedRef { + operator Derived&(); // expected-note{{candidate function}} + operator Derived2&(); // expected-note{{candidate function}} +}; + +struct ConvertibleToIntRef { + operator int&(); +}; + +struct ConvertibleToBase { + operator Base() const; +}; + +struct ConvertibleToDerived { + operator Derived() const; +}; + +struct ConvertibleToBothDerived { + operator Derived(); // expected-note{{candidate function}} + operator Derived2(); // expected-note{{candidate function}} +}; + +struct ConvertibleToInt { + operator int(); +}; + +template<typename T> T create(); + +// First bullet: lvalue references binding to lvalues (the simple cases). +void bind_lvalue_to_lvalue(Base b, Derived d, + const Base bc, const Derived dc, + Diamond diamond, + int i) { + // Reference-compatible + Base &br1 = b; + Base &br2 = d; + Derived &dr1 = d; + Derived &dr2 = b; // expected-error{{non-const lvalue reference to type 'Derived' cannot bind to a value of unrelated type 'Base'}} + Base &br3 = bc; // expected-error{{drops qualifiers}} + Base &br4 = dc; // expected-error{{drops qualifiers}} + Base &br5 = diamond; // expected-error{{ambiguous conversion from derived class 'Diamond' to base class 'Base':}} + int &ir = i; + long &lr = i; // expected-error{{non-const lvalue reference to type 'long' cannot bind to a value of unrelated type 'int'}} +} + +void bind_lvalue_quals(volatile Base b, volatile Derived d, + volatile const Base bvc, volatile const Derived dvc, + volatile const int ivc) { + volatile Base &bvr1 = b; + volatile Base &bvr2 = d; + 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 'volatile int' to a value of type 'const volatile int' drops qualifiers}} + + const volatile Base &bcvr1 = b; + const volatile Base &bcvr2 = 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 '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 'const volatile Base' cannot bind to a value of unrelated type 'Unrelated'}} +} + +void bind_lvalue_to_conv_lvalue() { + // Not reference-related, but convertible + Base &nbr1 = ConvertibleToBaseRef(); + Base &nbr2 = ConvertibleToDerivedRef(); + Derived &ndr1 = ConvertibleToDerivedRef(); + int &ir = ConvertibleToIntRef(); +} + +void bind_lvalue_to_conv_lvalue_ambig(ConvertibleToBothDerivedRef both) { + Derived &dr1 = both; + Base &br1 = both; // expected-error{{reference initialization of type 'Base &' with initializer of type 'ConvertibleToBothDerivedRef' is ambiguous}} +} + +struct IntBitfield { + int i : 17; // expected-note{{bit-field is declared here}} +}; + +void test_bitfield(IntBitfield ib) { + int & ir1 = (ib.i); // expected-error{{non-const reference cannot bind to bit-field 'i'}} +} + +// Second bullet: const lvalue reference binding to an rvalue with +// similar type (both of which are class types). +void bind_const_lvalue_to_rvalue() { + const Base &br1 = create<Base>(); + const Base &br2 = create<Derived>(); + const Derived &dr1 = create<Base>(); // expected-error{{no viable conversion}} + + 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 '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>(); +} + +// Second bullet: const lvalue reference binds to the result of a conversion. +void bind_const_lvalue_to_class_conv_temporary() { + const Base &br1 = ConvertibleToBase(); + const Base &br2 = ConvertibleToDerived(); +} +void bind_lvalue_to_conv_rvalue_ambig(ConvertibleToBothDerived both) { + const Derived &dr1 = both; + const Base &br1 = both; // expected-error{{reference initialization of type 'const Base &' with initializer of type 'ConvertibleToBothDerived' is ambiguous}} +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp new file mode 100644 index 0000000..51d61a5 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR5909 { + struct Foo { + int x : 20; + }; + + bool Test(const int& foo); + + const Foo f = { 0 }; // It compiles without the 'const'. + bool z = Test(f.x); +} + +namespace PR6264 { + typedef int (&T)[3]; + struct S + { + operator T (); + }; + void f() + { + T bar = S(); + } +} + +namespace PR6066 { + struct B { }; + struct A : B { + operator B*(); + operator B&(); // expected-warning{{conversion function converting 'PR6066::A' to its base class 'PR6066::B' will never be used}} + }; + + void f(B&); // no rvalues accepted + void f(B*); + + int g() { + f(A()); // calls f(B*) + return 0; + } +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.string/p1.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.string/p1.cpp new file mode 100644 index 0000000..3631af1 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.string/p1.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +char x1[]("hello"); +extern char x1[6]; + +char x2[] = "hello"; +extern char x2[6]; + +char x3[] = { "hello" }; +extern char x3[6]; + +wchar_t x4[](L"hello"); +extern wchar_t x4[6]; + +wchar_t x5[] = L"hello"; +extern wchar_t x5[6]; + +wchar_t x6[] = { L"hello" }; +extern wchar_t x6[6]; diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.string/p2.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.string/p2.cpp new file mode 100644 index 0000000..3d67fcc --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.string/p2.cpp @@ -0,0 +1,2 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +char test1[1]="f"; // expected-error {{initializer-string for char array is too long}} diff --git a/clang/test/CXX/dcl.decl/dcl.init/p14-0x.cpp b/clang/test/CXX/dcl.decl/dcl.init/p14-0x.cpp new file mode 100644 index 0000000..419f2bf --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/p14-0x.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct NoDefault { + NoDefault() = delete; // expected-note {{here}} + NoDefault(int); +}; +struct Explicit { // expected-note 2 {{candidate}} expected-note {{here}} + explicit Explicit(int); +}; +struct NoCopy { + NoCopy(); + NoCopy(const NoCopy &) = delete; // expected-note {{here}} +}; +struct NoMove { + NoMove(); + NoMove(NoMove &&) = delete; // expected-note {{here}} +}; +class Private { + Private(int); // expected-note {{here}} +public: + Private(); +}; +class Friend { + friend class S; + Friend(int); +}; + + +class S { + NoDefault nd1; + NoDefault nd2 = 42; + Explicit e1; // expected-note {{here}} + Explicit e2 = 42; // expected-error {{no viable conversion}} + NoCopy nc = NoCopy(); // expected-error {{call to deleted}} + NoMove nm = NoMove(); // expected-error {{call to deleted}} + Private p = 42; // expected-error {{private constructor}} + Friend f = 42; + + S() {} // expected-error {{call to deleted constructor of 'NoDefault'}} \ + expected-error {{must explicitly initialize the member 'e1' which does not have a default constructor}} + S(int) : nd1(42), e1(42) {} +}; + +// FIXME: test the other forms which use copy-initialization diff --git a/clang/test/CXX/dcl.decl/dcl.init/p5.cpp b/clang/test/CXX/dcl.decl/dcl.init/p5.cpp new file mode 100644 index 0000000..b50e8d7 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/p5.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// FIXME: Very incomplete! + +// A program that calls for default-initialization or value-initialization of +// an entity of reference type is illformed. If T is a cv-qualified type, the +// cv-unqualified version of T is used for these definitions of +// zero-initialization, default-initialization, and value-initialization. +// +// FIXME: The diagnostics for these errors are terrible because they fall out +// of the AST representation rather than being explicitly issued during the +// respective initialization forms. +struct S { // expected-error {{implicit default constructor for 'S' must explicitly initialize the reference member}} \ + // expected-note {{candidate constructor (the implicit copy constructor) not viable}} + int& x; // expected-note {{declared here}} +}; +S s; // expected-note {{implicit default constructor for 'S' first required here}} +S f() { + return S(); // expected-error {{no matching constructor for initialization of 'S'}} +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/p6.cpp b/clang/test/CXX/dcl.decl/dcl.init/p6.cpp new file mode 100644 index 0000000..514fd0c --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/p6.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// FIXME: Very incomplete! + +// If a program calls for the default initialization of an object of a +// const-qualified type T, T shall be a class type with a +// user-provided default constructor. +struct MakeNonPOD { MakeNonPOD(); }; +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 'const NoUserDefault' requires a user-provided default constructor}} + const HasUserDefault x2; + const int x3; // expected-error{{default initialization of an object of const type 'const int'}} +} + +// rdar://8501008 +struct s0 {}; +struct s1 { static const s0 foo; }; +const struct s0 s1::foo; // expected-error{{default initialization of an object of const type 'const struct s0' requires a user-provided default constructor}} + +template<typename T> +struct s2 { + static const s0 foo; +}; + +template<> const struct s0 s2<int>::foo; // okay diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1-cxx0x.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1-cxx0x.cpp new file mode 100644 index 0000000..102746c --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1-cxx0x.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +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/clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp new file mode 100644 index 0000000..bb4a48e --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.array/p1.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s + +// Simple form +int ar1[10]; + +// Element type cannot be: +// - (cv) void +volatile void ar2[10]; // expected-error {{incomplete element type 'volatile void'}} +// - a reference +int& ar3[10]; // expected-error {{array of references}} +// - a function type +typedef void Fn(); +Fn ar4[10]; // expected-error {{array of functions}} +// - an abstract class +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 with a negative size}} +int ar7[0u]; // expected-warning {{zero size arrays are an extension}} + +// An array with unknown bound is incomplete. +int ar8[]; // expected-error {{needs an explicit size or an initializer}} +// So is an array with an incomplete element type. +struct Incomplete; // expected-note {{forward declaration}} +Incomplete ar9[10]; // expected-error {{incomplete type}} +// Neither of which should be a problem in situations where no complete type +// is required. (PR5048) +void fun(int p1[], Incomplete p2[10]); +extern int ear1[]; +extern Incomplete ear2[10]; + +// cv migrates to element type +typedef const int cint; +extern cint car1[10]; +typedef int intar[10]; +// thus this is a valid redeclaration +extern const intar car1; + +// Check that instantiation works properly when the element type is a template. +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/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p10.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p10.cpp new file mode 100644 index 0000000..385e45d --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p10.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A { + virtual void f(int a = 7); +}; + +struct B : public A { + void f(int a); // expected-note{{'f' declared here}} +}; + +void m() { + B* pb = new B; + A* pa = pb; + pa->f(); // OK, calls pa->B::f(7) + pb->f(); // expected-error{{too few arguments}} +} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p2.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p2.cpp new file mode 100644 index 0000000..0a107eb --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p2.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void point(int = 3, int = 4); + +void test_point() { + point(1,2); + point(1); + point(); +} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp new file mode 100644 index 0000000..e9c5e0c --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void nondecl(int (*f)(int x = 5)) // {expected-error {{default arguments can only be specified}}} +{ + void (*f2)(int = 17) // {expected-error {{default arguments can only be specified}}} + = (void (*)(int = 42))f; // {expected-error {{default arguments can only be specified}}} +} + +struct X0 { + int (*f)(int = 17); // expected-error{{default arguments can only be specified for parameters in a function declaration}} + + void mem8(int (*fp)(int) = (int (*)(int = 17))0); // expected-error{{default arguments can only be specified for parameters in a function declaration}} +}; diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp new file mode 100644 index 0000000..f3dec52 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void f0(int i, int j, int k = 3); +void f0(int i, int j, int k); +void f0(int i, int j = 2, int k); +void f0(int i, int j, int k); +void f0(int i = 1, // expected-note{{previous definition}} + int j, int k); +void f0(int i, int j, int k); + +namespace N0 { + void f0(int, int, int); // expected-note{{candidate}} + + void test_f0_inner_scope() { + f0(); // expected-error{{no matching}} + } +} + +void test_f0_outer_scope() { + f0(); // okay +} + +void f0(int i = 1, // expected-error{{redefinition of default argument}} + int, int); + +template<typename T> void f1(T); // expected-note{{previous}} + +template<typename T> +void f1(T = T()); // expected-error{{cannot be added}} + + +namespace N1 { + // example from C++03 standard + // FIXME: make these "f2"s into "f"s, then fix our scoping issues + void f2(int, int); + void f2(int, int = 7); + void h() { + f2(3); // OK, calls f(3, 7) + void f(int = 1, int); // expected-error{{missing default argument}} + } + + void m() + { + void f(int, int); // expected-note{{'f' declared here}} + f(4); // expected-error{{too few arguments to function call}} + void f(int, int = 5); // expected-note{{previous definition}} + f(4); // okay + void f(int, int = 5); // expected-error{{redefinition of default argument}} + } + + void n() + { + f2(6); // okay + } +} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p5.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p5.cpp new file mode 100644 index 0000000..3100e56 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p5.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +float global_f; + +void f0(int *ip = &global_f); // expected-error{{cannot initialize}} \ +// expected-note{{passing argument to parameter 'ip' here}} + +// Example from C++03 standard +int a = 1; +int f(int); +int g(int x = f(a)); + +void h() { + a = 2; + { + int *a = 0; + g(); // FIXME: check that a is called with a value of 2 + } +} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp new file mode 100644 index 0000000..9ab0b48 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class C { +public: + void f(int i = 3); // expected-note{{here}} + void g(int i, int j = 99); +}; + +void C::f(int i = 3) { } // expected-error{{redefinition of default argument}} + +void C::g(int i = 88, int j) { } + +void test_C(C c) { + c.f(); + c.g(); +} + +template<typename T> +struct X0 { + void f(int); + + struct Inner { + void g(int); + }; +}; + +// DR217 +template<typename T> +void X0<T>::f(int = 17) { } // expected-error{{cannot be added}} + +// DR217 + DR205 (reading tea leaves) +template<typename T> +void X0<T>::Inner::g(int = 17) { } // expected-error{{cannot be added}} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp new file mode 100644 index 0000000..164eb36 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void h() +{ + int i; + extern void h2(int x = sizeof(i)); // expected-error {{default argument references local variable 'i' of enclosing function}} +} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p8.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p8.cpp new file mode 100644 index 0000000..1a08ab7 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p8.cpp @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class A { + void f(A* p = this) { } // expected-error{{invalid use of 'this'}} +}; diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp new file mode 100644 index 0000000..a879829 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p2.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// FIXME: test with non-std qualifiers + +namespace move { + struct Const { + Const(const Const&&) = default; // expected-error {{the parameter for an explicitly-defaulted move constructor may not be const}} + Const& operator=(const Const&&) = default; // expected-error {{the parameter for an explicitly-defaulted move assignment operator may not be const}} + }; + + struct Volatile { + Volatile(volatile Volatile&&) = default; // expected-error {{the parameter for an explicitly-defaulted move constructor may not be volatile}} + Volatile& operator=(volatile Volatile&&) = default; // expected-error {{the parameter for an explicitly-defaulted move assignment operator may not be volatile}} + }; + + struct AssignmentRet1 { + AssignmentRet1&& operator=(AssignmentRet1&&) = default; // expected-error {{an explicitly-defaulted move assignment operator must return an unqualified lvalue reference to its class type}} + }; + + struct AssignmentRet2 { + const AssignmentRet2& operator=(AssignmentRet2&&) = default; // expected-error {{an explicitly-defaulted move assignment operator must return an unqualified lvalue reference to its class type}} + }; + + struct ConstAssignment { + ConstAssignment& operator=(ConstAssignment&&) const = default; // expected-error {{an explicitly-defaulted move assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} + }; +} + +namespace copy { + struct Volatile { + Volatile(const volatile Volatile&) = default; // expected-error {{the parameter for an explicitly-defaulted copy constructor may not be volatile}} + Volatile& operator=(const volatile Volatile&) = default; // expected-error {{the parameter for an explicitly-defaulted copy assignment operator may not be volatile}} + }; + + struct Const { + Const(const Const&) = default; + Const& operator=(const Const&) = default; + }; + + struct NonConst { + NonConst(NonConst&) = default; + NonConst& operator=(NonConst&) = default; + }; + + struct BadConst { + NonConst nc; // makes implicit copy non-const + BadConst(const BadConst&) = default; // expected-error {{is const, but}} + BadConst& operator=(const BadConst&) = default; // expected-error {{is const, but}} + }; + + struct AssignmentRet1 { + AssignmentRet1&& operator=(const AssignmentRet1&) = default; // expected-error {{an explicitly-defaulted copy assignment operator must return an unqualified lvalue reference to its class type}} + }; + + struct AssignmentRet2 { + const AssignmentRet2& operator=(const AssignmentRet2&) = default; // expected-error {{an explicitly-defaulted copy assignment operator must return an unqualified lvalue reference to its class type}} + }; + + struct ConstAssignment { + ConstAssignment& operator=(const ConstAssignment&) const = default; // expected-error {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} + }; +} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp new file mode 100644 index 0000000..19a5f23 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fcxx-exceptions -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/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp new file mode 100644 index 0000000..0e69521 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp new file mode 100644 index 0000000..6b1f3e4 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %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 *'}} +auto (d() -> int); // expected-error {{trailing return type may not be nested within parentheses}} +auto e() -> auto (*)() -> auto (*)() -> void; // ok: same as void (*(*e())())(); diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p3.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p3.cpp new file mode 100644 index 0000000..ad827fb --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p3.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +void f(int) { } // expected-note {{previous definition is here}} +void f(const int) { } // expected-error {{redefinition of 'f'}} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp new file mode 100644 index 0000000..2ec1454 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +void f0() &; // expected-error {{non-member function cannot have '&' qualifier}} +void f1() &&; // expected-error {{non-member function cannot have '&&' qualifier}} +void f2() const volatile &&; // expected-error {{non-member function cannot have 'const volatile &&' qualifier}} + +struct X { + void f0() &; + void f1() &&; + static void f2() &; // expected-error{{static member function cannot have '&' qualifier}} + static void f3() &&; // expected-error{{static member function cannot have '&&' qualifier}} +}; + +typedef void func_type_lvalue() &; +typedef void func_type_rvalue() &&; + +typedef func_type_lvalue *func_type_lvalue_ptr; // expected-error{{pointer to function type 'func_type_lvalue' (aka 'void () &') cannot have '&' qualifier}} +typedef func_type_rvalue *func_type_rvalue_ptr; // expected-error{{pointer to function type 'func_type_rvalue' (aka 'void () &&') cannot have '&&' qualifier}} + +typedef func_type_lvalue &func_type_lvalue_ref; // expected-error{{reference to function type 'func_type_lvalue' (aka 'void () &') cannot have '&' qualifier}} +typedef func_type_rvalue &func_type_rvalue_ref; // expected-error{{reference to function type 'func_type_rvalue' (aka 'void () &&') cannot have '&&' qualifier}} + +template<typename T = func_type_lvalue> struct wrap { + typedef T val; + typedef T *ptr; + typedef T &ref; +}; + +using func_type_lvalue = wrap<>::val; +using func_type_lvalue = wrap<func_type_lvalue>::val; +using func_type_rvalue = wrap<func_type_rvalue>::val; + +using func_type_lvalue_ptr = wrap<>::ptr; +using func_type_lvalue_ptr = wrap<func_type_lvalue>::ptr; +using func_type_rvalue_ptr = wrap<func_type_rvalue>::ptr; + +using func_type_lvalue_ref = wrap<>::ref; +using func_type_lvalue_ref = wrap<func_type_lvalue>::ref; +using func_type_rvalue_ref = wrap<func_type_rvalue>::ref; + +func_type_lvalue f2; // expected-error{{non-member function of type 'func_type_lvalue' (aka 'void () &') cannot have '&' qualifier}} +func_type_rvalue f3; // expected-error{{non-member function of type 'func_type_rvalue' (aka 'void () &&') cannot have '&&' 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{{non-member function cannot have '&&' qualifier}} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp new file mode 100644 index 0000000..e2d94fb --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +typedef void F() const; + +void f() const; // expected-error {{non-member function cannot have 'const' qualifier}} +F g; // expected-error {{non-member function of type 'F' (aka 'void () const') cannot have 'const' qualifier}} + +struct X { + void f() const; + friend void g() const; // expected-error {{non-member function cannot have 'const' qualifier}} + static void h() const; // expected-error {{static member function cannot have 'const' qualifier}} + F i; // ok + friend F j; // expected-error {{non-member function of type 'F' (aka 'void () const') cannot have 'const' qualifier}} + static F k; // expected-error {{static member function of type 'F' (aka 'void () const') cannot have 'const' qualifier}} +}; + +struct Y { + friend void X::f() const; + friend void ::f() const; // expected-error {{non-member function cannot have 'const' qualifier}} +}; diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8-0x.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8-0x.cpp new file mode 100644 index 0000000..11926f1 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8-0x.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +auto f() -> int[32]; // expected-error{{function cannot return array}} +auto g() -> int(int); // expected-error{{function cannot return function}} +auto h() -> auto() -> int; // expected-error{{function cannot return function}} +auto i() -> auto(*)() -> int; diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p8.cpp new file mode 100644 index 0000000..34a8c85 --- /dev/null +++ b/clang/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/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp new file mode 100644 index 0000000..574a3e7 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +auto j() -> enum { e3 }; // expected-error{{unnamed enumeration must be a definition}} expected-error {{requires a specifier or qualifier}} expected-error {{without trailing return type}} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp new file mode 100644 index 0000000..7e35788 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class A { +public: + int& i; + + A(int& i) : i(i) { } + + static int s; +}; + +template<typename T> void ft(T& t) { + t.*&T::i = 10; // expected-error{{cannot form a pointer-to-member to member 'i' of reference type 'int &'}} +} + +void f() { + int b; + A a(b); + + int A::*ip = &A::s; // expected-error {{cannot initialize a variable of type 'int A::*' with an rvalue of type 'int *'}} + a.*&A::s = 10; // expected-error{{right hand operand to .* has non pointer-to-member type 'int *'}} + + a.*&A::i = 10; // expected-error{{cannot form a pointer-to-member to member 'i' of reference type 'int &'}} + ft(a); // expected-note{{in instantiation of function template specialization 'ft<A>' requested here}} + + void A::*p = 0; // expected-error{{'p' declared as a member pointer to void}} +} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp new file mode 100644 index 0000000..c02105c --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p5.cpp @@ -0,0 +1,145 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++ [dcl.ref]p5: +// There shall be no references to references, no arrays of +// references, and no pointers to references. + +// The crazy formatting in here is to enforce the exact report locations. + +typedef int &intref; +typedef intref &intrefref; + +template <class T> class RefMem { // expected-warning{{class 'RefMem<int &>' does not declare any constructor to initialize its non-modifiable members}} + T + & + member; // expected-note{{reference member 'member' will never be initialized}} +}; + +struct RefRef { + int + & + & // expected-error {{declared as a reference to a reference}} + refref0; + + intref + & + refref1; // collapses + + intrefref + & + refref2; // collapses + + RefMem + < + int + & + > + refref3; // collapses expected-note{{in instantiation of template class 'RefMem<int &>' requested here}} +}; + + +template <class T> class PtrMem { + T + * // expected-error {{declared as a pointer to a reference}} + member; +}; + +struct RefPtr { + typedef + int + & + * // expected-error {{declared as a pointer to a reference}} + intrefptr; + + typedef + intref + * // expected-error {{declared as a pointer to a reference}} + intrefptr2; + + int + & + * // expected-error {{declared as a pointer to a reference}} + refptr0; + + intref + * // expected-error {{declared as a pointer to a reference}} + refptr1; + + PtrMem + < + int + & + > + refptr2; // expected-note {{in instantiation}} +}; + +template <class T> class ArrMem { + T + member + [ // expected-error {{declared as array of references}} + 10 + ]; +}; +template <class T, unsigned N> class DepArrMem { + T + member + [ // expected-error {{declared as array of references}} + N + ]; +}; + +struct RefArr { + typedef + int + & + intrefarr + [ // expected-error {{declared as array of references}} + 2 + ]; + + typedef + intref + intrefarr + [ // expected-error {{declared as array of references}} + 2 + ]; + + int + & + refarr0 + [ // expected-error {{declared as array of references}} + 2 + ]; + intref + refarr1 + [ // expected-error {{declared as array of references}} + 2 + ]; + ArrMem + < + int + & + > + refarr2; // expected-note {{in instantiation}} + DepArrMem + < + int + &, + 10 + > + refarr3; // expected-note {{in instantiation}} +}; + + +// The declaration of a reference shall contain an initializer +// (8.5.3) except when the declaration contains an explicit extern +// specifier (7.1.1), is a class member (9.2) declaration within a +// class definition, or is the declaration of a parameter or a +// return type (8.3.5); see 3.1. A reference shall be initialized to +// refer to a valid object or function. [ Note: in particular, a +// null reference cannot exist in a well-defined program, because +// the only way to create such a reference would be to bind it to +// the "object" obtained by dereferencing a null pointer, which +// causes undefined behavior. As described in 9.6, a reference +// cannot be bound directly to a bit-field. + diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp new file mode 100644 index 0000000..4ce80bc --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.ref/p6-0x.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp new file mode 100644 index 0000000..99334b8 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// The nested-name-specifier of a qualified declarator-id shall not begin with a decltype-specifier. +class foo { + static int i; + void func(); +}; + +int decltype(foo())::i; // expected-error{{'decltype' cannot be used to name a declaration}} +void decltype(foo())::func() { // expected-error{{'decltype' cannot be used to name a declaration}} +} + + +template<typename T> +class tfoo { + static int i; + void func(); +}; + +template<typename T> +int decltype(tfoo<T>())::i; // expected-error{{nested name specifier 'decltype(tfoo<T>())::' for declaration does not refer into a class, class template or class template partial specialization}} +template<typename T> +void decltype(tfoo<T>())::func() { // expected-error{{nested name specifier 'decltype(tfoo<T>())::' for declaration does not refer into a class, class template or class template partial specialization}} +} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/p1.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/p1.cpp new file mode 100644 index 0000000..3672ea0 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.meaning/p1.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR8019 { + struct x; + template<typename T> struct x2; + struct y { + struct PR8019::x { int x; }; // expected-error{{non-friend class member 'x' cannot have a qualified name}} + + struct inner; + struct y::inner { }; // expected-warning{{extra qualification on member 'inner'}} + + template<typename T> + struct PR8019::x2 { }; // expected-error{{non-friend class member 'x2' cannot have a qualified name}} + + template<typename T> + struct inner_template; + + template<typename T> + struct y::inner_template { }; // expected-warning{{extra qualification on member 'inner_template'}} + }; + +} + +namespace NS { + void foo(); + extern int bar; + struct X; + template<typename T> struct Y; + template<typename T> void wibble(T); +} +namespace NS { + void NS::foo() {} // expected-warning{{extra qualification on member 'foo'}} + int NS::bar; // expected-warning{{extra qualification on member 'bar'}} + struct NS::X { }; // expected-warning{{extra qualification on member 'X'}} + template<typename T> struct NS::Y; // expected-warning{{extra qualification on member 'Y'}} + template<typename T> void NS::wibble(T) { } // expected-warning{{extra qualification on member 'wibble'}} +} diff --git a/clang/test/CXX/dcl.decl/dcl.name/p1.cpp b/clang/test/CXX/dcl.decl/dcl.name/p1.cpp new file mode 100644 index 0000000..9838b4f --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.name/p1.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace pr6200 { + struct v {}; + enum E { e }; + struct s { + int i; + operator struct v() { return v(); }; + operator enum E() { return e; } + }; + + void f() + { + // None of these is a declaration. + (void)new struct s; + (void)new enum E; + (void)&s::operator struct v; + (void)&s::operator enum E; + } +} diff --git a/clang/test/CXX/dcl.decl/p4-0x.cpp b/clang/test/CXX/dcl.decl/p4-0x.cpp new file mode 100644 index 0000000..98c33b2 --- /dev/null +++ b/clang/test/CXX/dcl.decl/p4-0x.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct X { + void f() &; + void g() &&; +}; + +void (X::*pmf)() & = &X::f; diff --git a/clang/test/CXX/except/except.handle/p16.cpp b/clang/test/CXX/except/except.handle/p16.cpp new file mode 100644 index 0000000..0810be1 --- /dev/null +++ b/clang/test/CXX/except/except.handle/p16.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fcxx-exceptions -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) +// is copy-initialized (8.5) from the exception object. +// +template<typename T> +class X { + T* ptr; + +public: + X(const X<T> &) { + int *ip = 0; + ptr = ip; // expected-error{{assigning to 'float *' from incompatible type 'int *'}} + } + + ~X() { + float *fp = 0; + ptr = fp; // expected-error{{assigning to 'int *' from incompatible type 'float *'}} + } +}; + +void f() { + try { + } catch (X<float>) { // expected-note{{instantiation}} + // copy constructor + } catch (X<int> xi) { // expected-note{{instantiation}} + // destructor + } +} + +struct Abstract { + virtual void f() = 0; // expected-note{{pure virtual}} +}; + +void g() { + try { + } catch (Abstract) { // expected-error{{variable type 'Abstract' is an abstract class}} + } +} diff --git a/clang/test/CXX/except/except.spec/canonical.cpp b/clang/test/CXX/except/except.spec/canonical.cpp new file mode 100644 index 0000000..81ca2ae --- /dev/null +++ b/clang/test/CXX/except/except.spec/canonical.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// PR10087: Make sure that we don't conflate exception specifications +// from different functions in the canonical type system. +namespace std +{ + +template <class _Tp> _Tp&& declval() noexcept; + +template <class _Tp, class... _Args> +struct __is_nothrow_constructible +{ + static const bool value = noexcept(_Tp(declval<_Args>()...)); +}; + +template<class, class _Traits, class _Allocator> +class basic_string +{ +public: + typedef typename _Traits::char_type value_type; + typedef _Allocator allocator_type; + + basic_string() + noexcept(__is_nothrow_constructible<allocator_type>::value); +}; + +template <class, class, class _Compare> +struct __map_value_compare +{ +public: + __map_value_compare() + noexcept(__is_nothrow_constructible<_Compare>::value); +}; + +struct less +{ +}; + +struct map +{ + typedef __map_value_compare<int, short, less> __vc; + __vc vc_; +}; + + +template<class T, class _Traits, class _Allocator> +basic_string<T, _Traits, _Allocator>::basic_string() noexcept(__is_nothrow_constructible<allocator_type>::value) {} + +template <class T, class Value, class _Compare> +__map_value_compare<T, Value, _Compare>::__map_value_compare() + noexcept(__is_nothrow_constructible<_Compare>::value) {} + +} // std diff --git a/clang/test/CXX/except/except.spec/p1.cpp b/clang/test/CXX/except/except.spec/p1.cpp new file mode 100644 index 0000000..e184ec4 --- /dev/null +++ b/clang/test/CXX/except/except.spec/p1.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s + +// Simple parser tests, dynamic specification. + +namespace dyn { + + struct X { }; + + struct Y { }; + + void f() throw() { } + + void g(int) throw(X) { } + + void h() throw(X, Y) { } + + class Class { + void foo() throw (X, Y) { } + }; + + void (*fptr)() throw(); + +} + +// Simple parser tests, noexcept specification. + +namespace noex { + + void f1() noexcept { } + void f2() noexcept (true) { } + void f3() noexcept (false) { } + void f4() noexcept (1 < 2) { } + + class CA1 { + void foo() noexcept { } + void bar() noexcept (true) { } + }; + + void (*fptr1)() noexcept; + void (*fptr2)() noexcept (true); + +} + +namespace mix { + + void f() throw(int) noexcept { } // expected-error {{cannot have both}} + void g() noexcept throw(int) { } // expected-error {{cannot have both}} + +} + +// Sema tests, noexcept specification + +namespace noex { + + struct A {}; + + void g1() noexcept(A()); // expected-error {{not contextually convertible}} + void g2(bool b) noexcept(b); // expected-error {{argument to noexcept specifier must be a constant expression}} + +} + +namespace noexcept_unevaluated { + template<typename T> bool f(T) { + T* x = 1; + } + + template<typename T> + void g(T x) noexcept((sizeof(T) == sizeof(int)) || noexcept(f(x))) { } + + void h() { + g(1); + } +} + +namespace PR11084 { + template<int X> struct A { + static int f() noexcept(1/X) { return 10; } // expected-error{{argument to noexcept specifier must be a constant expression}} expected-note{{division by zero}} + }; + + void g() { A<0>::f(); } // expected-note{{in instantiation of exception specification for 'f' requested here}} +} diff --git a/clang/test/CXX/except/except.spec/p11.cpp b/clang/test/CXX/except/except.spec/p11.cpp new file mode 100644 index 0000000..0e4fad5 --- /dev/null +++ b/clang/test/CXX/except/except.spec/p11.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s + +// This is the "let the user shoot himself in the foot" clause. +void f() noexcept { + throw 0; // no-error +} +void g() throw() { + throw 0; // no-error +} +void h() throw(int) { + throw 0.0; // no-error +} diff --git a/clang/test/CXX/except/except.spec/p14-ir.cpp b/clang/test/CXX/except/except.spec/p14-ir.cpp new file mode 100644 index 0000000..81fbf7d --- /dev/null +++ b/clang/test/CXX/except/except.spec/p14-ir.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -o - %s | FileCheck %s + +// Copy constructor +struct X0 { + X0(); + X0(const X0 &) throw(); + X0(X0 &); +}; + +struct X1 { + X1(); + X1(const X1 &) throw(); +}; + +struct X2 : X1 { + X2(); +}; +struct X3 : X0, X1 { + X3(); +}; + +struct X4 { + X4(X4 &) throw(); +}; + +struct X5 : X0, X4 { }; + +void test(X2 x2, X3 x3, X5 x5) { + // CHECK: define linkonce_odr void @_ZN2X2C1ERKS_(%struct.X2* %this, %struct.X2*) unnamed_addr + // CHECK: call void @_ZN2X2C2ERKS_({{.*}}) nounwind + // CHECK-NEXT: ret void + // CHECK-NEXT: } + X2 x2a(x2); + // CHECK: define linkonce_odr void @_ZN2X3C1ERKS_(%struct.X3* %this, %struct.X3*) unnamed_addr + // CHECK: call void @_ZN2X3C2ERKS_({{.*}}) nounwind + // CHECK-NEXT: ret void + // CHECK-NEXT: } + X3 x3a(x3); + // CHECK: define linkonce_odr void @_ZN2X5C1ERS_({{.*}}) unnamed_addr + // CHECK-NOT: call void @__cxa_call_unexpected + // CHECK: ret void + X5 x5a(x5); +} + +// Default constructor +struct X6 { + X6() throw(); +}; + +struct X7 { + X7(); +}; + +struct X8 : X6 { }; +struct X9 : X6, X7 { }; + +void test() { + // CHECK: define linkonce_odr void @_ZN2X8C1Ev(%struct.X8* %this) unnamed_addr + // CHECK: call void @_ZN2X8C2Ev({{.*}}) nounwind + // CHECK-NEXT: ret void + X8(); + + // CHECK: define linkonce_odr void @_ZN2X9C1Ev(%struct.X9* %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(%struct.X9* %this) unnamed_addr + // CHECK: call void @_ZN2X6C2Ev({{.*}}) nounwind + // FIXME: and here: + // CHECK-NEXT: bitcast + // CHECK-NEXT: call void @_ZN2X7C2Ev({{.*}}) + // CHECK: ret void + + // CHECK: define linkonce_odr void @_ZN2X8C2Ev(%struct.X8* %this) unnamed_addr + // CHECK: call void @_ZN2X6C2Ev({{.*}}) nounwind + // CHECK-NEXT: ret void +} diff --git a/clang/test/CXX/except/except.spec/p14.cpp b/clang/test/CXX/except/except.spec/p14.cpp new file mode 100644 index 0000000..8763a70 --- /dev/null +++ b/clang/test/CXX/except/except.spec/p14.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -verify -std=c++11 %s +struct A { }; +struct B { }; +struct C { }; + +// Destructor +struct X0 { + virtual ~X0() throw(A); // expected-note{{overridden virtual function is here}} +}; +struct X1 { + virtual ~X1() throw(B); // expected-note{{overridden virtual function is here}} +}; +struct X2 : public X0, public X1 { }; // expected-error 2{{exception specification of overriding function is more lax than base version}} + +// Copy-assignment operator. +struct CA0 { + CA0 &operator=(const CA0&) throw(A); +}; +struct CA1 { + CA1 &operator=(const CA1&) throw(B); +}; +struct CA2 : CA0, CA1 { }; + +void test_CA() { + CA2 &(CA2::*captr1)(const CA2&) throw(A, B) = &CA2::operator=; + CA2 &(CA2::*captr2)(const CA2&) throw(A, B, C) = &CA2::operator=; + CA2 &(CA2::*captr3)(const CA2&) throw(A) = &CA2::operator=; // expected-error{{target exception specification is not superset of source}} + CA2 &(CA2::*captr4)(const CA2&) throw(B) = &CA2::operator=; // expected-error{{target exception specification is not superset of source}} +} + +// In-class member initializers. +struct IC0 { + int inClassInit = 0; +}; +struct IC1 { + int inClassInit = (throw B(), 0); +}; +// FIXME: the exception specification on the default constructor is wrong: +// we cannot currently compute the set of thrown types. +static_assert(noexcept(IC0()), "IC0() does not throw"); +static_assert(!noexcept(IC1()), "IC1() throws"); diff --git a/clang/test/CXX/except/except.spec/p15.cpp b/clang/test/CXX/except/except.spec/p15.cpp new file mode 100644 index 0000000..110ec3f --- /dev/null +++ b/clang/test/CXX/except/except.spec/p15.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s + +// Deallocation functions are implicitly noexcept. +// Thus, explicit specs aren't allowed to conflict. + +void f() { + // Force implicit declaration of delete. + delete new int; + delete[] new int[1]; +} + +void operator delete(void*) noexcept; +void operator delete[](void*) noexcept; + +// Same goes for explicit declarations. +void operator delete(void*, float); +void operator delete(void*, float) noexcept; + +void operator delete[](void*, float); +void operator delete[](void*, float) noexcept; + +// But explicit specs stay. +void operator delete(void*, double) throw(int); // expected-note {{previous}} +void operator delete(void*, double) noexcept; // expected-error {{does not match}} diff --git a/clang/test/CXX/except/except.spec/p2-dynamic-types.cpp b/clang/test/CXX/except/except.spec/p2-dynamic-types.cpp new file mode 100644 index 0000000..57f8c32 --- /dev/null +++ b/clang/test/CXX/except/except.spec/p2-dynamic-types.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s + +// Dynamic specifications: valid types. + +struct Incomplete; // expected-note 3 {{forward declaration}} + +// Exception spec must not have incomplete types, or pointers to them, except +// void. +void ic1() throw(void); // expected-error {{incomplete type 'void' is not allowed in exception specification}} +void ic2() throw(Incomplete); // expected-error {{incomplete type 'Incomplete' is not allowed in exception specification}} +void ic3() throw(void*); +void ic4() throw(Incomplete*); // expected-error {{pointer to incomplete type 'Incomplete' is not allowed in exception specification}} +void ic5() throw(Incomplete&); // expected-error {{reference to incomplete type 'Incomplete' is not allowed in exception specification}} + +// Don't suppress errors in template instantiation. +template <typename T> struct TEx; // expected-note {{template is declared here}} + +void tf() throw(TEx<int>); // expected-error {{implicit instantiation of undefined template}} + +// DR 437, class throws itself. +struct DR437 { + void f() throw(DR437); + void g() throw(DR437*); + void h() throw(DR437&); +}; + +// DR 437 within a nested class +struct DR437_out { + struct DR437_in { + void f() throw(DR437_out); + void g() throw(DR437_out*); + void h() throw(DR437_out&); + }; +}; diff --git a/clang/test/CXX/except/except.spec/p2-places.cpp b/clang/test/CXX/except/except.spec/p2-places.cpp new file mode 100644 index 0000000..67647fb --- /dev/null +++ b/clang/test/CXX/except/except.spec/p2-places.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s + +// Tests where specs are allowed and where they aren't. + +namespace dyn { + + // Straight from the standard: + + // Plain function with spec + void f() throw(int); + + // Pointer to function with spec + void (*fp)() throw (int); + + // Function taking reference to function with spec + void g(void pfa() throw(int)); + + // Typedef for pointer to function with spec + typedef int (*pf)() throw(int); // expected-error {{specifications are not allowed in typedefs}} + + // Some more: + + // Function returning function with spec + void (*h())() throw(int); + + // Ultimate parser thrill: function with spec returning function with spec and + // taking pointer to function with spec. + // The actual function throws int, the return type double, the argument float. + void (*i() throw(int))(void (*)() throw(float)) throw(double); + + // Pointer to pointer to function taking function with spec + void (**k)(void pfa() throw(int)); // no-error + + // Pointer to pointer to function with spec + void (**j)() throw(int); // expected-error {{not allowed beyond a single}} + + // Pointer to function returning pointer to pointer to function with spec + void (**(*h())())() throw(int); // expected-error {{not allowed beyond a single}} + +} + +namespace noex { + + // These parallel those from above. + + void f() noexcept(false); + + void (*fp)() noexcept(false); + + void g(void pfa() noexcept(false)); + + typedef int (*pf)() noexcept(false); // expected-error {{specifications are not allowed in typedefs}} + + void (*h())() noexcept(false); + + void (*i() noexcept(false))(void (*)() noexcept(true)) noexcept(false); + + void (**k)(void pfa() noexcept(false)); // no-error + + void (**j)() noexcept(false); // expected-error {{not allowed beyond a single}} + + void (**(*h())())() noexcept(false); // expected-error {{not allowed beyond a single}} +} diff --git a/clang/test/CXX/except/except.spec/p3.cpp b/clang/test/CXX/except/except.spec/p3.cpp new file mode 100644 index 0000000..d77aea4 --- /dev/null +++ b/clang/test/CXX/except/except.spec/p3.cpp @@ -0,0 +1,106 @@ +// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s + +// Exception specification compatibility. +// We test function pointers, because functions have an extra rule in p4. + +// Same type is compatible +extern void (*r1)() throw(int); +extern void (*r1)() throw(int); + +// Typedefs don't matter. +typedef int INT; +extern void (*r2)() throw(int); +extern void (*r2)() throw(INT); + +// Order doesn't matter. +extern void (*r3)() throw(int, float); +extern void (*r3)() throw(float, int); + +// MS throw-any spec and no spec at all are compatible +extern void (*r4)(); +extern void (*r4)() throw(...); + +// throw(X) and no spec are not compatible +extern void (*r5)() throw(int); // expected-note {{previous declaration}} +extern void (*r5)(); // expected-error {{exception specification in declaration does not match}} + +// For functions, we accept this with a warning. +extern void f5() throw(int); // expected-note {{previous declaration}} +extern void f5(); // expected-warning {{missing exception specification}} + +// Different types are not compatible. +extern void (*r7)() throw(int); // expected-note {{previous declaration}} +extern void (*r7)() throw(float); // expected-error {{exception specification in declaration does not match}} + +// Top-level const doesn't matter. +extern void (*r8)() throw(int); +extern void (*r8)() throw(const int); + +// Multiple appearances don't matter. +extern void (*r9)() throw(int, int); +extern void (*r9)() throw(int, int); + + +// noexcept is compatible with itself +extern void (*r10)() noexcept; +extern void (*r10)() noexcept; + +// noexcept(true) is compatible with noexcept +extern void (*r11)() noexcept; +extern void (*r11)() noexcept(true); + +// noexcept(false) isn't +extern void (*r12)() noexcept; // expected-note {{previous declaration}} +extern void (*r12)() noexcept(false); // expected-error {{does not match}} + +// The form of the boolean expression doesn't matter. +extern void (*r13)() noexcept(1 < 2); +extern void (*r13)() noexcept(2 > 1); + +// noexcept(false) is incompatible with noexcept(true) +extern void (*r14)() noexcept(true); // expected-note {{previous declaration}} +extern void (*r14)() noexcept(false); // expected-error {{does not match}} + +// noexcept(false) is compatible with itself +extern void (*r15)() noexcept(false); +extern void (*r15)() noexcept(false); + +// noexcept(false) is compatible with MS throw(...) +extern void (*r16)() noexcept(false); +extern void (*r16)() throw(...); + +// noexcept(false) is *not* compatible with no spec +extern void (*r17)(); // expected-note {{previous declaration}} +extern void (*r17)() noexcept(false); // expected-error {{does not match}} + +// except for functions +void f17(); +void f17() noexcept(false); + +// noexcept(false) is compatible with dynamic specs that throw unless +// CWG 1073 resolution is accepted. Clang implements it. +//extern void (*r18)() throw(int); +//extern void (*r18)() noexcept(false); + +// noexcept(true) is compatible with dynamic specs that don't throw +extern void (*r19)() throw(); +extern void (*r19)() noexcept(true); + +// The other way round doesn't work. +extern void (*r20)() throw(); // expected-note {{previous declaration}} +extern void (*r20)() noexcept(false); // expected-error {{does not match}} + +extern void (*r21)() throw(int); // expected-note {{previous declaration}} +extern void (*r21)() noexcept(true); // expected-error {{does not match}} + + +// As a very special workaround, we allow operator new to match no spec +// with a throw(bad_alloc) spec, because C++0x makes an incompatible change +// here. +extern "C++" { namespace std { class bad_alloc {}; } } +typedef decltype(sizeof(int)) mysize_t; +void* operator new(mysize_t) throw(std::bad_alloc); +void* operator new(mysize_t); +void* operator new[](mysize_t); +void* operator new[](mysize_t) throw(std::bad_alloc); + diff --git a/clang/test/CXX/except/except.spec/p5-pointers.cpp b/clang/test/CXX/except/except.spec/p5-pointers.cpp new file mode 100644 index 0000000..dd3c060 --- /dev/null +++ b/clang/test/CXX/except/except.spec/p5-pointers.cpp @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s + +// Assignment of function pointers. + +struct A +{ +}; + +struct B1 : A +{ +}; + +struct B2 : A +{ +}; + +struct D : B1, B2 +{ +}; + +struct P : private A +{ +}; + +// Some functions to play with below. +void s1() throw(); +void s2() throw(int); +void s3() throw(A); +void s4() throw(B1); +void s5() throw(D); +void s6(); +void s7() throw(int, float); +void (*s8())() throw(B1); // s8 returns a pointer to function with spec +void s9(void (*)() throw(B1)); // s9 takes pointer to function with spec + +void s10() noexcept; +void s11() noexcept(true); +void s12() noexcept(false); + +void fnptrs() +{ + // Assignment and initialization of function pointers. + void (*t1)() throw() = &s1; // valid + t1 = &s2; // expected-error {{not superset}} expected-error {{incompatible type}} + t1 = &s3; // expected-error {{not superset}} expected-error {{incompatible type}} + void (&t2)() throw() = s2; // expected-error {{not superset}} + void (*t3)() throw(int) = &s2; // valid + void (*t4)() throw(A) = &s1; // valid + t4 = &s3; // valid + t4 = &s4; // valid + t4 = &s5; // expected-error {{not superset}} expected-error {{incompatible type}} + void (*t5)() = &s1; // valid + t5 = &s2; // valid + t5 = &s6; // valid + t5 = &s7; // valid + t1 = t3; // expected-error {{not superset}} expected-error {{incompatible type}} + t3 = t1; // valid + void (*t6)() throw(B1); + t6 = t4; // expected-error {{not superset}} expected-error {{incompatible type}} + t4 = t6; // valid + t5 = t1; // valid + t1 = t5; // expected-error {{not superset}} expected-error {{incompatible type}} + + // return types and arguments must match exactly, no inheritance allowed + void (*(*t7)())() throw(B1) = &s8; // valid + void (*(*t8)())() throw(A) = &s8; // expected-error {{return types differ}} + void (*(*t9)())() throw(D) = &s8; // expected-error {{return types differ}} + void (*t10)(void (*)() throw(B1)) = &s9; // valid expected-warning{{disambiguated}} + void (*t11)(void (*)() throw(A)) = &s9; // expected-error {{argument types differ}} expected-warning{{disambiguated}} + void (*t12)(void (*)() throw(D)) = &s9; // expected-error {{argument types differ}} expected-warning{{disambiguated}} +} + +// Member function stuff + +struct Str1 { void f() throw(int); }; // expected-note {{previous declaration}} +void Str1::f() // expected-warning {{missing exception specification}} +{ +} + +void mfnptr() +{ + void (Str1::*pfn1)() throw(int) = &Str1::f; // valid + void (Str1::*pfn2)() = &Str1::f; // valid + void (Str1::*pfn3)() throw() = &Str1::f; // expected-error {{not superset}} +} diff --git a/clang/test/CXX/except/except.spec/p5-virtual.cpp b/clang/test/CXX/except/except.spec/p5-virtual.cpp new file mode 100644 index 0000000..69daec6 --- /dev/null +++ b/clang/test/CXX/except/except.spec/p5-virtual.cpp @@ -0,0 +1,96 @@ +// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s + +// Compatibility of virtual functions. + +struct A +{ +}; + +struct B1 : A +{ +}; + +struct B2 : A +{ +}; + +struct D : B1, B2 +{ +}; + +struct P : private A +{ +}; + +struct Base +{ + virtual void f1() throw(); + virtual void f2() throw(int, float); + + virtual void f3() throw(int, float); + virtual void f4() throw(A); + virtual void f5() throw(A, int, float); + virtual void f6(); + + virtual void f7() noexcept; + virtual void f8() noexcept; + virtual void f9() noexcept(false); + virtual void f10() noexcept(false); + + virtual void f11() throw(); + virtual void f12() noexcept; + virtual void f13() noexcept(false); + virtual void f14() throw(int); + + virtual void f15(); + virtual void f16(); + + virtual void g1() throw(); // expected-note {{overridden virtual function is here}} + virtual void g2() throw(int); // expected-note {{overridden virtual function is here}} + virtual void g3() throw(A); // expected-note {{overridden virtual function is here}} + virtual void g4() throw(B1); // expected-note {{overridden virtual function is here}} + virtual void g5() throw(A); // expected-note {{overridden virtual function is here}} + + virtual void g6() noexcept; // expected-note {{overridden virtual function is here}} + virtual void g7() noexcept; // expected-note {{overridden virtual function is here}} + + virtual void g8() noexcept; // expected-note {{overridden virtual function is here}} + virtual void g9() throw(); // expected-note {{overridden virtual function is here}} + virtual void g10() throw(int); // expected-note {{overridden virtual function is here}} +}; +struct Derived : Base +{ + virtual void f1() throw(); + virtual void f2() throw(float, int); + + virtual void f3() throw(float); + virtual void f4() throw(B1); + virtual void f5() throw(B1, B2, int); + virtual void f6() throw(B2, B2, int, float, char, double, bool); + + virtual void f7() noexcept; + virtual void f8() noexcept(true); + virtual void f9() noexcept(true); + virtual void f10() noexcept(false); + + virtual void f11() noexcept; + virtual void f12() throw(); + virtual void f13() throw(int); + virtual void f14() noexcept(true); + + virtual void f15() noexcept; + virtual void f16() throw(); + + virtual void g1() throw(int); // expected-error {{exception specification of overriding function is more lax}} + virtual void g2(); // expected-error {{exception specification of overriding function is more lax}} + virtual void g3() throw(D); // expected-error {{exception specification of overriding function is more lax}} + virtual void g4() throw(A); // expected-error {{exception specification of overriding function is more lax}} + virtual void g5() throw(P); // expected-error {{exception specification of overriding function is more lax}} + + virtual void g6() noexcept(false); // expected-error {{exception specification of overriding function is more lax}} + virtual void g7(); // expected-error {{exception specification of overriding function is more lax}} + + virtual void g8() throw(int); // expected-error {{exception specification of overriding function is more lax}} + virtual void g9() noexcept(false); // expected-error {{exception specification of overriding function is more lax}} + virtual void g10() noexcept(false); // expected-error {{exception specification of overriding function is more lax}} +}; diff --git a/clang/test/CXX/except/except.spec/p9-dynamic.cpp b/clang/test/CXX/except/except.spec/p9-dynamic.cpp new file mode 100644 index 0000000..4559e0d --- /dev/null +++ b/clang/test/CXX/except/except.spec/p9-dynamic.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s + +void external(); + +void target() throw(int) +{ + // CHECK: invoke void @_Z8externalv() + external(); +} +// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) +// CHECK-NEXT: filter [1 x i8*] [i8* bitcast (i8** @_ZTIi to i8*)] +// CHECK: call void @__cxa_call_unexpected diff --git a/clang/test/CXX/except/except.spec/p9-noexcept.cpp b/clang/test/CXX/except/except.spec/p9-noexcept.cpp new file mode 100644 index 0000000..7c8d0ef --- /dev/null +++ b/clang/test/CXX/except/except.spec/p9-noexcept.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -emit-llvm -o - -fcxx-exceptions -fexceptions | FileCheck %s + +void external(); + +void target() noexcept +{ + // CHECK: invoke void @_Z8externalv() + external(); +} +// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) +// CHECK-NEXT: catch i8* null +// CHECK-NEXT: call void @_ZSt9terminatev() noreturn nounwind +// CHECK-NEXT: unreachable + +void reverse() noexcept(false) +{ + // CHECK: call void @_Z8externalv() + external(); +} diff --git a/clang/test/CXX/except/except.spec/template.cpp b/clang/test/CXX/except/except.spec/template.cpp new file mode 100644 index 0000000..805a604 --- /dev/null +++ b/clang/test/CXX/except/except.spec/template.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s + +// We use pointer assignment compatibility to test instantiation. + +template <int N> void f1() throw(int); +template <int N> void f2() noexcept(N > 1); + +void (*t1)() throw(int) = &f1<0>; +void (*t2)() throw() = &f1<0>; // expected-error {{not superset}} + +void (*t3)() noexcept = &f2<2>; // no-error +void (*t4)() noexcept = &f2<0>; // expected-error {{not superset}} diff --git a/clang/test/CXX/expr/expr.ass/p9-cxx11.cpp b/clang/test/CXX/expr/expr.ass/p9-cxx11.cpp new file mode 100644 index 0000000..206c82c --- /dev/null +++ b/clang/test/CXX/expr/expr.ass/p9-cxx11.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +template<typename T> struct complex { + complex(T = T(), T = T()); + void operator+=(complex); + T a, b; +}; + +void std_example() { + complex<double> z; + z = { 1, 2 }; + z += { 1, 2 }; + + int a, b; + a = b = { 1 }; + a = { 1 } = b; // expected-error {{initializer list cannot be used on the left hand side of operator '='}} + a = a + { 4 }; // expected-error {{initializer list cannot be used on the right hand side of operator '+'}} + a = { 3 } * { 4 }; // expected-error {{initializer list cannot be used on the left hand side of operator '*'}} \ + expected-error {{initializer list cannot be used on the right hand side of operator '*'}} +} + +struct S { + constexpr S(int a, int b) : a(a), b(b) {} + int a, b; +}; +struct T { + constexpr int operator=(S s) { return s.a; } + constexpr int operator+=(S s) { return s.b; } +}; +static_assert((T() = {4, 9}) == 4, ""); +static_assert((T() += {4, 9}) == 9, ""); + +int k1 = T() = { 1, 2 } = { 3, 4 }; // expected-error {{initializer list cannot be used on the left hand side of operator '='}} +int k2 = T() = { 1, 2 } + 1; // expected-error {{initializer list cannot be used on the left hand side of operator '+'}} diff --git a/clang/test/CXX/expr/expr.cast/p4-0x.cpp b/clang/test/CXX/expr/expr.cast/p4-0x.cpp new file mode 100644 index 0000000..96bf5f9 --- /dev/null +++ b/clang/test/CXX/expr/expr.cast/p4-0x.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/expr/expr.cast/p4.cpp b/clang/test/CXX/expr/expr.cast/p4.cpp new file mode 100644 index 0000000..907e008 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp new file mode 100644 index 0000000..054669e --- /dev/null +++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp @@ -0,0 +1,596 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -pedantic -verify -fcxx-exceptions %s -fconstexpr-depth 128 -triple i686-pc-linux-gnu + +// A conditional-expression is a core constant expression unless it involves one +// of the following as a potentially evaluated subexpression [...]: + +// - this (5.1.1 [expr.prim.general]) [Note: when evaluating a constant +// expression, function invocation substitution (7.1.5 [dcl.constexpr]) +// replaces each occurrence of this in a constexpr member function with a +// pointer to the class object. -end note]; +struct This { + int this1 : this1; // expected-error {{undeclared}} + int this2 : this->this1; // expected-error {{invalid}} + void this3() { + int n1[this->this1]; // expected-warning {{variable length array}} + int n2[this1]; // expected-warning {{variable length array}} + (void)n1, (void)n2; + } +}; + +// - an invocation of a function other than a constexpr constructor for a +// literal class or a constexpr function [ Note: Overload resolution (13.3) +// is applied as usual - end note ]; +struct NonConstexpr1 { + static int f() { return 1; } // expected-note {{here}} + int n : f(); // expected-error {{constant expression}} expected-note {{non-constexpr function 'f' cannot be used in a constant expression}} +}; +struct NonConstexpr2 { + constexpr NonConstexpr2(); // expected-note {{here}} + int n; +}; +struct NonConstexpr3 { + NonConstexpr3(); + int m : NonConstexpr2().n; // expected-error {{constant expression}} expected-note {{undefined constructor 'NonConstexpr2'}} +}; +struct NonConstexpr4 { + NonConstexpr4(); // expected-note {{declared here}} + int n; +}; +struct NonConstexpr5 { + int n : NonConstexpr4().n; // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr4' cannot be used in a constant expression}} +}; + +// - an invocation of an undefined constexpr function or an undefined +// constexpr constructor; +struct UndefinedConstexpr { + constexpr UndefinedConstexpr(); + static constexpr int undefinedConstexpr1(); // expected-note {{here}} + int undefinedConstexpr2 : undefinedConstexpr1(); // expected-error {{constant expression}} expected-note {{undefined function 'undefinedConstexpr1' cannot be used in a constant expression}} +}; + +// - an invocation of a constexpr function with arguments that, when substituted +// by function invocation substitution (7.1.5), do not produce a core constant +// expression; +namespace NonConstExprReturn { + static constexpr const int &id_ref(const int &n) { + return n; + } + struct NonConstExprFunction { + int n : id_ref(16); // ok + }; + constexpr const int *address_of(const int &a) { + return &a; + } + constexpr const int *return_param(int n) { // expected-note {{declared here}} + return address_of(n); + } + struct S { + int n : *return_param(0); // expected-error {{constant expression}} expected-note {{read of variable whose lifetime has ended}} + }; +} + +// - an invocation of a constexpr constructor with arguments that, when +// substituted by function invocation substitution (7.1.5), do not produce all +// constant expressions for the constructor calls and full-expressions in the +// mem-initializers (including conversions); +namespace NonConstExprCtor { + struct T { + constexpr T(const int &r) : + r(r) { + } + const int &r; + }; + constexpr int n = 0; + constexpr T t1(n); // ok + constexpr T t2(0); // expected-error {{must be initialized by a constant expression}} expected-note {{temporary created here}} expected-note {{reference to temporary is not a constant expression}} + + struct S { + int n : T(4).r; // ok + }; +} + +// - an invocation of a constexpr function or a constexpr constructor that would +// exceed the implementation-defined recursion limits (see Annex B); +namespace RecursionLimits { + constexpr int RecurseForever(int n) { + return n + RecurseForever(n+1); // expected-note {{constexpr evaluation exceeded maximum depth of 128 calls}} expected-note 9{{in call to 'RecurseForever(}} expected-note {{skipping 118 calls}} + } + struct AlsoRecurseForever { + constexpr AlsoRecurseForever(int n) : + n(AlsoRecurseForever(n+1).n) // expected-note {{constexpr evaluation exceeded maximum depth of 128 calls}} expected-note 9{{in call to 'AlsoRecurseForever(}} expected-note {{skipping 118 calls}} + {} + int n; + }; + struct S { + int k : RecurseForever(0); // expected-error {{constant expression}} expected-note {{in call to}} + int l : AlsoRecurseForever(0).n; // expected-error {{constant expression}} expected-note {{in call to}} + }; +} + +// DR1458: taking the address of an object of incomplete class type +namespace IncompleteClassTypeAddr { + struct S; + extern S s; + constexpr S *p = &s; // ok + static_assert(p, ""); + + extern S sArr[]; + constexpr S (*p2)[] = &sArr; // ok + + struct S { + constexpr S *operator&() { return nullptr; } + }; + constexpr S *q = &s; // ok + static_assert(!q, ""); +} + +// - an operation that would have undefined behavior [Note: including, for +// example, signed integer overflow (Clause 5 [expr]), certain pointer +// arithmetic (5.7 [expr.add]), division by zero (5.6 [expr.mul]), or certain +// shift operations (5.8 [expr.shift]) -end note]; +namespace UndefinedBehavior { + void f(int n) { + switch (n) { + case (int)4.4e9: // expected-error {{constant expression}} expected-note {{value 4.4E+9 is outside the range of representable values of type 'int'}} + case (int)0x80000000u: // ok + case (int)10000000000ll: // expected-note {{here}} + case (unsigned int)10000000000ll: // expected-error {{duplicate case value}} + case (int)(unsigned)(long long)4.4e9: // ok + case (int)(float)1e300: // expected-error {{constant expression}} expected-note {{value 1.0E+300 is outside the range of representable values of type 'float'}} + case (int)((float)1e37 / 1e30): // ok + case (int)(__fp16)65536: // expected-error {{constant expression}} expected-note {{value 65536 is outside the range of representable values of type 'half'}} + break; + } + } + + constexpr int int_min = ~0x7fffffff; + constexpr int minus_int_min = -int_min; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}} + constexpr int div0 = 3 / 0; // expected-error {{constant expression}} expected-note {{division by zero}} expected-warning {{undefined}} + constexpr int mod0 = 3 % 0; // expected-error {{constant expression}} expected-note {{division by zero}} expected-warning {{undefined}} + constexpr int int_min_div_minus_1 = int_min / -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}} + constexpr int int_min_mod_minus_1 = int_min % -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range}} + + constexpr int shl_m1 = 0 << -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}} expected-warning {{negative}} + constexpr int shl_0 = 0 << 0; // ok + constexpr int shl_31 = 0 << 31; // ok + constexpr int shl_32 = 0 << 32; // expected-error {{constant expression}} expected-note {{shift count 32 >= width of type 'int' (32}} expected-warning {{>= width of type}} + constexpr int shl_unsigned_negative = unsigned(-3) << 1; // ok + constexpr int shl_unsigned_into_sign = 1u << 31; // ok + constexpr int shl_unsigned_overflow = 1024u << 31; // ok + constexpr int shl_signed_negative = (-3) << 1; // expected-error {{constant expression}} expected-note {{left shift of negative value -3}} + constexpr int shl_signed_ok = 1 << 30; // ok + constexpr int shl_signed_into_sign = 1 << 31; // ok (DR1457) + constexpr int shl_signed_into_sign_2 = 0x7fffffff << 1; // ok (DR1457) + constexpr int shl_signed_off_end = 2 << 31; // expected-error {{constant expression}} expected-note {{signed left shift discards bits}} expected-warning {{signed shift result (0x100000000) requires 34 bits to represent, but 'int' only has 32 bits}} + constexpr int shl_signed_off_end_2 = 0x7fffffff << 2; // expected-error {{constant expression}} expected-note {{signed left shift discards bits}} expected-warning {{signed shift result (0x1FFFFFFFC) requires 34 bits to represent, but 'int' only has 32 bits}} + constexpr int shl_signed_overflow = 1024 << 31; // expected-error {{constant expression}} expected-note {{signed left shift discards bits}} expected-warning {{requires 43 bits to represent}} + constexpr int shl_signed_ok2 = 1024 << 20; // ok + + constexpr int shr_m1 = 0 >> -1; // expected-error {{constant expression}} expected-note {{negative shift count -1}} expected-warning {{negative}} + constexpr int shr_0 = 0 >> 0; // ok + constexpr int shr_31 = 0 >> 31; // ok + constexpr int shr_32 = 0 >> 32; // expected-error {{constant expression}} expected-note {{shift count 32 >= width of type}} expected-warning {{>= width of type}} + + struct S { + int m; + }; + constexpr S s = { 5 }; + constexpr const int *p = &s.m + 1; + constexpr const int &f(const int *q) { + return q[0]; + } + constexpr int n = (f(p), 0); // ok + struct T { + int n : f(p); // expected-error {{not an integral constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}} + }; + + namespace Ptr { + struct A {}; + struct B : A { int n; }; + B a[3][3]; + constexpr B *p = a[0] + 4; // expected-error {{constant expression}} expected-note {{element 4 of array of 3 elements}} + B b = {}; + constexpr A *pa = &b + 1; // expected-error {{constant expression}} expected-note {{base class of pointer past the end}} + constexpr B *pb = (B*)((A*)&b + 1); // expected-error {{constant expression}} expected-note {{derived class of pointer past the end}} + constexpr const int *pn = &(&b + 1)->n; // expected-error {{constant expression}} expected-note {{field of pointer past the end}} + constexpr B *parr = &a[3][0]; // expected-error {{constant expression}} expected-note {{array element of pointer past the end}} + + constexpr A *na = nullptr; + constexpr B *nb = nullptr; + constexpr A &ra = *nb; // expected-error {{constant expression}} expected-note {{cannot access base class of null pointer}} + constexpr B &rb = (B&)*na; // expected-error {{constant expression}} expected-note {{cannot access derived class of null pointer}} + static_assert((A*)nb == 0, ""); + static_assert((B*)na == 0, ""); + constexpr const int &nf = nb->n; // expected-error {{constant expression}} expected-note {{cannot access field of null pointer}} + constexpr const int &np = (*(int(*)[4])nullptr)[2]; // expected-error {{constant expression}} expected-note {{cannot access array element of null pointer}} + + struct C { + constexpr int f() { return 0; } + } constexpr c = C(); + constexpr int k1 = c.f(); // ok + constexpr int k2 = ((C*)nullptr)->f(); // expected-error {{constant expression}} expected-note {{cannot call member function on null pointer}} + constexpr int k3 = (&c)[1].f(); // expected-error {{constant expression}} expected-note {{cannot call member function on pointer past the end of object}} + C c2; + constexpr int k4 = c2.f(); // ok! + + constexpr int diff1 = &a[2] - &a[0]; + constexpr int diff2 = &a[1][3] - &a[1][0]; + constexpr int diff3 = &a[2][0] - &a[1][0]; // expected-error {{constant expression}} expected-note {{subtracted pointers are not elements of the same array}} + static_assert(&a[2][0] == &a[1][3], ""); + constexpr int diff4 = (&b + 1) - &b; + constexpr int diff5 = &a[1][2].n - &a[1][0].n; // expected-error {{constant expression}} expected-note {{subtracted pointers are not elements of the same array}} + constexpr int diff6 = &a[1][2].n - &a[1][2].n; + constexpr int diff7 = (A*)&a[0][1] - (A*)&a[0][0]; // expected-error {{constant expression}} expected-note {{subtracted pointers are not elements of the same array}} + } + + namespace Overflow { + // Signed int overflow. + constexpr int n1 = 2 * 3 * 3 * 7 * 11 * 31 * 151 * 331; // ok + constexpr int n2 = 65536 * 32768; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} + constexpr int n3 = n1 + 1; // ok + constexpr int n4 = n3 + 1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} + constexpr int n5 = -65536 * 32768; // ok + constexpr int n6 = 3 * -715827883; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} + constexpr int n7 = -n3 + -1; // ok + constexpr int n8 = -1 + n7; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} + constexpr int n9 = n3 - 0; // ok + constexpr int n10 = n3 - -1; // expected-error {{constant expression}} expected-note {{value 2147483648 is outside the range of }} + constexpr int n11 = -1 - n3; // ok + constexpr int n12 = -2 - n3; // expected-error {{constant expression}} expected-note {{value -2147483649 is outside the range of }} + constexpr int n13 = n5 + n5; // expected-error {{constant expression}} expected-note {{value -4294967296 is outside the range of }} + constexpr int n14 = n3 - n5; // expected-error {{constant expression}} expected-note {{value 4294967295 is outside the range of }} + constexpr int n15 = n5 * n5; // expected-error {{constant expression}} expected-note {{value 4611686018427387904 is outside the range of }} + constexpr signed char c1 = 100 * 2; // ok + constexpr signed char c2 = '\x64' * '\2'; // also ok + constexpr long long ll1 = 0x7fffffffffffffff; // ok + constexpr long long ll2 = ll1 + 1; // expected-error {{constant}} expected-note {{ 9223372036854775808 }} + constexpr long long ll3 = -ll1 - 1; // ok + constexpr long long ll4 = ll3 - 1; // expected-error {{constant}} expected-note {{ -9223372036854775809 }} + constexpr long long ll5 = ll3 * ll3; // expected-error {{constant}} expected-note {{ 85070591730234615865843651857942052864 }} + + // Yikes. + char melchizedek[2200000000]; + typedef decltype(melchizedek[1] - melchizedek[0]) ptrdiff_t; + constexpr ptrdiff_t d1 = &melchizedek[0x7fffffff] - &melchizedek[0]; // ok + constexpr ptrdiff_t d2 = &melchizedek[0x80000000u] - &melchizedek[0]; // expected-error {{constant expression}} expected-note {{ 2147483648 }} + constexpr ptrdiff_t d3 = &melchizedek[0] - &melchizedek[0x80000000u]; // ok + constexpr ptrdiff_t d4 = &melchizedek[0] - &melchizedek[0x80000001u]; // expected-error {{constant expression}} expected-note {{ -2147483649 }} + + // Unsigned int overflow. + static_assert(65536u * 65536u == 0u, ""); // ok + static_assert(4294967295u + 1u == 0u, ""); // ok + static_assert(0u - 1u == 4294967295u, ""); // ok + static_assert(~0u * ~0u == 1u, ""); // ok + + // Floating-point overflow and NaN. + constexpr float f1 = 1e38f * 3.4028f; // ok + constexpr float f2 = 1e38f * 3.4029f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} + constexpr float f3 = 1e38f / -.2939f; // ok + constexpr float f4 = 1e38f / -.2938f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} + constexpr float f5 = 2e38f + 2e38f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} + constexpr float f6 = -2e38f - 2e38f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} + constexpr float f7 = 0.f / 0.f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces a NaN}} + } +} + +// - a lambda-expression (5.1.2); +struct Lambda { + // FIXME: clang crashes when trying to parse this! Revisit this check once + // lambdas are fully implemented. + //int n : []{ return 1; }(); +}; + +// - an lvalue-to-rvalue conversion (4.1) unless it is applied to +namespace LValueToRValue { + // - a non-volatile glvalue of integral or enumeration type that refers to a + // non-volatile const object with a preceding initialization, initialized + // with a constant expression [Note: a string literal (2.14.5 [lex.string]) + // corresponds to an array of such objects. -end note], or + volatile const int vi = 1; // expected-note 2{{here}} + const int ci = 1; + volatile const int &vrci = ci; + static_assert(vi, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + static_assert(const_cast<int&>(vi), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}} + static_assert(vrci, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + + // - a non-volatile glvalue of literal type that refers to a non-volatile + // object defined with constexpr, or that refers to a sub-object of such an + // object, or + struct V { + constexpr V() : v(1) {} + volatile int v; // expected-note {{not literal because}} + }; + constexpr V v; // expected-error {{non-literal type}} + struct S { + constexpr S(int=0) : i(1), v(const_cast<volatile int&>(vi)) {} + constexpr S(const S &s) : i(2), v(const_cast<volatile int&>(vi)) {} + int i; + volatile int &v; + }; + constexpr S s; // ok + constexpr volatile S vs; // expected-note {{here}} + constexpr const volatile S &vrs = s; // ok + static_assert(s.i, ""); + static_assert(s.v, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + static_assert(const_cast<int&>(s.v), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}} + static_assert(vs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + static_assert(const_cast<int&>(vs.i), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vs'}} + static_assert(vrs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} + + // - a non-volatile glvalue of literal type that refers to a non-volatile + // temporary object whose lifetime has not ended, initialized with a + // constant expression; + constexpr volatile S f() { return S(); } + static_assert(f().i, ""); // ok! there's no lvalue-to-rvalue conversion here! + static_assert(((volatile const S&&)(S)0).i, ""); // expected-error {{constant expression}} +} + +// DR1312: The proposed wording for this defect has issues, so we ignore this +// bullet and instead prohibit casts from pointers to cv void (see core-20842 +// and core-20845). +// +// - an lvalue-to-rvalue conversion (4.1 [conv.lval]) that is applied to a +// glvalue of type cv1 T that refers to an object of type cv2 U, where T and U +// are neither the same type nor similar types (4.4 [conv.qual]); + +// - an lvalue-to-rvalue conversion (4.1) that is applied to a glvalue that +// refers to a non-active member of a union or a subobject thereof; +namespace LValueToRValueUnion { + // test/SemaCXX/constant-expression-cxx11.cpp contains more thorough testing + // of this. + union U { int a, b; } constexpr u = U(); + static_assert(u.a == 0, ""); + constexpr const int *bp = &u.b; + constexpr int b = *bp; // expected-error {{constant expression}} expected-note {{read of member 'b' of union with active member 'a'}} + + extern const U pu; + constexpr const int *pua = &pu.a; + constexpr const int *pub = &pu.b; + constexpr U pu = { .b = 1 }; // expected-warning {{C99 feature}} + constexpr const int a2 = *pua; // expected-error {{constant expression}} expected-note {{read of member 'a' of union with active member 'b'}} + constexpr const int b2 = *pub; // ok +} + +// - an id-expression that refers to a variable or data member of reference type +// unless the reference has a preceding initialization, initialized with a +// constant expression; +namespace References { + const int a = 2; + int &b = *const_cast<int*>(&a); + int c = 10; // expected-note 2 {{here}} + int &d = c; + constexpr int e = 42; + int &f = const_cast<int&>(e); + extern int &g; + constexpr int &h(); // expected-note {{here}} + int &i = h(); // expected-note {{here}} + constexpr int &j() { return b; } + int &k = j(); + + struct S { + int A : a; + int B : b; + int C : c; // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}} + int D : d; // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}} + int D2 : &d - &c + 1; + int E : e / 2; + int F : f - 11; + int G : g; // expected-error {{constant expression}} + int H : h(); // expected-error {{constant expression}} expected-note {{undefined function 'h'}} + int I : i; // expected-error {{constant expression}} expected-note {{initializer of 'i' is not a constant expression}} + int J : j(); + int K : k; + }; +} + +// - a dynamic_cast (5.2.7); +namespace DynamicCast { + struct S { int n; }; + constexpr S s { 16 }; + struct T { + int n : dynamic_cast<const S*>(&s)->n; // expected-warning {{constant expression}} expected-note {{dynamic_cast}} + }; +} + +// - a reinterpret_cast (5.2.10); +namespace ReinterpretCast { + struct S { int n; }; + constexpr S s { 16 }; + struct T { + int n : reinterpret_cast<const S*>(&s)->n; // expected-warning {{constant expression}} expected-note {{reinterpret_cast}} + }; + struct U { + int m : (long)(S*)6; // expected-warning {{constant expression}} expected-note {{reinterpret_cast}} + }; +} + +// - a pseudo-destructor call (5.2.4); +namespace PseudoDtor { + int k; + typedef int I; + struct T { + int n : (k.~I(), 0); // expected-error {{constant expression}} + }; +} + +// - increment or decrement operations (5.2.6, 5.3.2); +namespace IncDec { + int k = 2; + struct T { + int n : ++k; // expected-error {{constant expression}} + int m : --k; // expected-error {{constant expression}} + }; +} + +// - a typeid expression (5.2.8) whose operand is of a polymorphic class type; +namespace std { + struct type_info { + virtual ~type_info(); + const char *name; + }; +} +namespace TypeId { + struct S { virtual void f(); }; + constexpr S *p = 0; + constexpr const std::type_info &ti1 = typeid(*p); // expected-error {{must be initialized by a constant expression}} expected-note {{typeid applied to expression of polymorphic type 'TypeId::S'}} + + struct T {} t; + constexpr const std::type_info &ti2 = typeid(t); +} + +// - a new-expression (5.3.4); +// - a delete-expression (5.3.5); +namespace NewDelete { + int *p = 0; + struct T { + int n : *new int(4); // expected-error {{constant expression}} + int m : (delete p, 2); // expected-error {{constant expression}} + }; +} + +// - a relational (5.9) or equality (5.10) operator where the result is +// unspecified; +namespace UnspecifiedRelations { + int a, b; + constexpr int *p = &a, *q = &b; + // C++11 [expr.rel]p2: If two pointers p and q of the same type point to + // different objects that are not members of the same array or to different + // functions, or if only one of them is null, the results of p<q, p>q, p<=q, + // and p>=q are unspecified. + constexpr bool u1 = p < q; // expected-error {{constant expression}} + constexpr bool u2 = p > q; // expected-error {{constant expression}} + constexpr bool u3 = p <= q; // expected-error {{constant expression}} + constexpr bool u4 = p >= q; // expected-error {{constant expression}} + constexpr bool u5 = p < 0; // expected-error {{constant expression}} + constexpr bool u6 = p <= 0; // expected-error {{constant expression}} + constexpr bool u7 = p > 0; // expected-error {{constant expression}} + constexpr bool u8 = p >= 0; // expected-error {{constant expression}} + constexpr bool u9 = 0 < q; // expected-error {{constant expression}} + constexpr bool u10 = 0 <= q; // expected-error {{constant expression}} + constexpr bool u11 = 0 > q; // expected-error {{constant expression}} + constexpr bool u12 = 0 >= q; // expected-error {{constant expression}} + void f(), g(); + + constexpr void (*pf)() = &f, (*pg)() = &g; + constexpr bool u13 = pf < pg; // expected-error {{constant expression}} + constexpr bool u14 = pf == pg; + + // If two pointers point to non-static data members of the same object with + // different access control, the result is unspecified. + struct A { + public: + constexpr A() : a(0), b(0) {} + int a; + constexpr bool cmp() { return &a < &b; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{comparison of address of fields 'a' and 'b' of 'A' with differing access specifiers (public vs private) has unspecified value}} + private: + int b; + }; + class B { + public: + A a; + constexpr bool cmp() { return &a.a < &b.a; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{comparison of address of fields 'a' and 'b' of 'B' with differing access specifiers (public vs protected) has unspecified value}} + protected: + A b; + }; + + // If two pointers point to different base sub-objects of the same object, or + // one points to a base subobject and the other points to a member, the result + // of the comparison is unspecified. This is not explicitly called out by + // [expr.rel]p2, but is covered by 'Other pointer comparisons are + // unspecified'. + struct C { + int c[2]; + }; + struct D { + int d; + }; + struct E : C, D { + struct Inner { + int f; + } e; + } e; + constexpr bool base1 = &e.c[0] < &e.d; // expected-error {{constant expression}} expected-note {{comparison of addresses of subobjects of different base classes has unspecified value}} + constexpr bool base2 = &e.c[1] < &e.e.f; // expected-error {{constant expression}} expected-note {{comparison of address of base class subobject 'C' of class 'E' to field 'e' has unspecified value}} + constexpr bool base3 = &e.e.f < &e.d; // expected-error {{constant expression}} expected-note {{comparison of address of base class subobject 'D' of class 'E' to field 'e' has unspecified value}} + + // [expr.rel]p3: Pointers to void can be compared [...] if both pointers + // represent the same address or are both the null pointer [...]; otherwise + // the result is unspecified. + struct S { int a, b; } s; + constexpr void *null = 0; + constexpr void *pv = (void*)&s.a; + constexpr void *qv = (void*)&s.b; + constexpr bool v1 = null < 0; + constexpr bool v2 = null < pv; // expected-error {{constant expression}} + constexpr bool v3 = null == pv; // ok + constexpr bool v4 = qv == pv; // ok + constexpr bool v5 = qv >= pv; // expected-error {{constant expression}} expected-note {{unequal pointers to void}} + constexpr bool v6 = qv > null; // expected-error {{constant expression}} + constexpr bool v7 = qv <= (void*)&s.b; // ok + constexpr bool v8 = qv > (void*)&s.a; // expected-error {{constant expression}} expected-note {{unequal pointers to void}} +} + +// - an assignment or a compound assignment (5.17); or +namespace Assignment { + int k; + struct T { + int n : (k = 9); // expected-error {{constant expression}} + int m : (k *= 2); // expected-error {{constant expression}} + }; + + struct Literal { + constexpr Literal(const char *name) : name(name) {} + const char *name; + }; + struct Expr { + constexpr Expr(Literal l) : IsLiteral(true), l(l) {} + bool IsLiteral; + union { + Literal l; + // ... + }; + }; + struct MulEq { + constexpr MulEq(Expr a, Expr b) : LHS(a), RHS(b) {} + Expr LHS; + Expr RHS; + }; + constexpr MulEq operator*=(Expr a, Expr b) { return MulEq(a, b); } + Literal a("a"); + Literal b("b"); + MulEq c = a *= b; // ok +} + +// - a throw-expression (15.1) +namespace Throw { + struct S { + int n : (throw "hello", 10); // expected-error {{constant expression}} + }; +} + +// PR9999 +template<unsigned int v> +class bitWidthHolding { +public: + static const + unsigned int width = (v == 0 ? 0 : bitWidthHolding<(v >> 1)>::width + 1); +}; + +static const int width=bitWidthHolding<255>::width; + +template<bool b> +struct always_false { + static const bool value = false; +}; + +template<bool b> +struct and_or { + static const bool and_value = b && and_or<always_false<b>::value>::and_value; + static const bool or_value = !b || and_or<always_false<b>::value>::or_value; +}; + +static const bool and_value = and_or<true>::and_value; +static const bool or_value = and_or<true>::or_value; + +static_assert(and_value == false, ""); +static_assert(or_value == true, ""); diff --git a/clang/test/CXX/expr/expr.const/p3-0x-nowarn.cpp b/clang/test/CXX/expr/expr.const/p3-0x-nowarn.cpp new file mode 100644 index 0000000..c891374 --- /dev/null +++ b/clang/test/CXX/expr/expr.const/p3-0x-nowarn.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wno-c++11-narrowing -verify %s + +// <rdar://problem/11121178> +void f(int x) { + switch (x) { + case 0x80000001: break; + } +} diff --git a/clang/test/CXX/expr/expr.const/p3-0x.cpp b/clang/test/CXX/expr/expr.const/p3-0x.cpp new file mode 100644 index 0000000..6ddd11b --- /dev/null +++ b/clang/test/CXX/expr/expr.const/p3-0x.cpp @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +// A converted constant expression of type T is a core constant expression, +int nonconst = 8; // expected-note 3 {{here}} +enum NonConstE : unsigned char { NCE = nonconst }; // expected-error {{enumerator value is not a constant expression}} expected-note {{read of non-const}} +template<int = nonconst> struct NonConstT {}; // expected-error {{non-type template argument is not a constant expression}} expected-note {{read of non-const}} +void NonConstF() { + switch (nonconst) { + case nonconst: // expected-error {{case value is not a constant expression}} expected-note {{read of non-const}} + break; + } + return; +} + +// implicitly converted to a prvalue of type T, where the converted expression +// is a literal constant expression + +bool a(int n) { + constexpr char vowels[] = "aeiou"; + switch (n) { + case vowels[0]: + case vowels[1]: + case vowels[2]: + case vowels[3]: + case vowels[4]: + static_assert(!vowels[5], "unexpected number of vowels"); + return true; + } + return false; +} + +// and the implicit conversion sequence contains only +// +// user-defined conversions, +struct S { constexpr operator int() const { return 5; } }; +enum E : unsigned char { E5 = S(), E6, E10 = S() * 2, E1 = E5 / 5 }; + +// lvalue-to-rvalue conversions, +const E e10 = E10; +template<E> struct T {}; +T<e10> s10; + +// integral promotions, and +enum class EE { EE32 = ' ', EE65 = 'A', EE1 = (short)1, EE5 = E5 }; + +// integral conversions other than narrowing conversions +int b(unsigned n) { + switch (n) { + case E6: + case EE::EE32: // expected-error {{not implicitly convertible}} + case (int)EE::EE32: + case 1000: + case (long long)1e10: // expected-error {{case value evaluates to 10000000000, which cannot be narrowed to type 'unsigned int'}} + case -3: // expected-error {{case value evaluates to -3, which cannot be narrowed to type 'unsigned int'}} + return n; + } + return 0; +} +enum class EEE : unsigned short { + a = E6, + b = EE::EE32, // expected-error {{not implicitly convertible}} + c = (int)EE::EE32, + d = 1000, + e = 123456, // expected-error {{enumerator value evaluates to 123456, which cannot be narrowed to type 'unsigned short'}} + f = -3 // expected-error {{enumerator value evaluates to -3, which cannot be narrowed to type 'unsigned short'}} +}; +template<unsigned char> using A = int; +using Int = A<E6>; +using Int = A<EE::EE32>; // expected-error {{not implicitly convertible}} +using Int = A<(int)EE::EE32>; +using Int = A<200>; +using Int = A<1000>; // expected-error {{template argument evaluates to 1000, which cannot be narrowed to type 'unsigned char'}} +using Int = A<-3>; // expected-error {{template argument evaluates to -3, which cannot be narrowed to type 'unsigned char'}} + +// Note, conversions from integral or unscoped enumeration types to bool are +// integral conversions as well as boolean conversions. +template<typename T, T v> struct Val { static constexpr T value = v; }; +static_assert(Val<bool, E1>::value == 1, ""); // ok +static_assert(Val<bool, '\0'>::value == 0, ""); // ok +static_assert(Val<bool, U'\1'>::value == 1, ""); // ok +static_assert(Val<bool, E5>::value == 1, ""); // expected-error {{5, which cannot be narrowed to type 'bool'}} + +// (no other conversions are permitted) +using Int = A<1.0>; // expected-error {{conversion from 'double' to 'unsigned char' is not allowed in a converted constant expression}} +enum B : bool { + True = &a, // expected-error {{conversion from 'bool (*)(int)' to 'bool' is not allowed in a converted constant expression}} + False = nullptr // expected-error {{conversion from 'nullptr_t' to 'bool' is not allowed in a converted constant expression}} +}; +void c() { + // Note, promoted type of switch is 'int'. + switch (bool b = a(5)) { // expected-warning {{boolean value}} + case 0.0f: // expected-error {{conversion from 'float' to 'int' is not allowed in a converted constant expression}} + break; + } +} +template<bool B> int f() { return B; } +template int f<&S::operator int>(); // expected-error {{does not refer to a function template}} +template int f<(bool)&S::operator int>(); + +int n = Val<bool, &S::operator int>::value; // expected-error {{conversion from 'int (S::*)() const' to 'bool' is not allowed in a converted constant expression}} + +namespace NonConstLValue { + struct S { + constexpr operator int() { return 10; } + }; + S s; // not constexpr + // Under the FDIS, this is not a converted constant expression. + // Under the new proposed wording, it is. + enum E : char { e = s }; +} diff --git a/clang/test/CXX/expr/expr.const/p5-0x.cpp b/clang/test/CXX/expr/expr.const/p5-0x.cpp new file mode 100644 index 0000000..60fabe3 --- /dev/null +++ b/clang/test/CXX/expr/expr.const/p5-0x.cpp @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +// If an expression of literal class type is used in a context where an integral +// constant expression is required, then that class type shall have a single +// non-explicit conversion function to an integral or unscoped enumeration type +namespace std_example { + +struct A { + constexpr A(int i) : val(i) { } + constexpr operator int() { return val; } + constexpr operator long() { return 43; } +private: + int val; +}; +template<int> struct X { }; +constexpr A a = 42; +X<a> x; // ok, unique conversion to int +int ary[a]; // expected-error {{size of array has non-integer type 'const std_example::A'}} + +} + +struct OK { + constexpr OK() {} + constexpr operator int() { return 8; } +} constexpr ok; +extern struct Incomplete incomplete; // expected-note 4{{forward decl}} +struct Explicit { + constexpr Explicit() {} + constexpr explicit operator int() { return 4; } // expected-note 4{{here}} +} constexpr expl; +struct Ambiguous { + constexpr Ambiguous() {} + constexpr operator int() { return 2; } // expected-note 4{{here}} + constexpr operator long() { return 1; } // expected-note 4{{here}} +} constexpr ambig; + +constexpr int test_ok = ok; // ok +constexpr int test_explicit(expl); // ok +constexpr int test_ambiguous = ambig; // ok + +static_assert(test_ok == 8, ""); +static_assert(test_explicit == 4, ""); +static_assert(test_ambiguous == 2, ""); + +// [expr.new]p6: Every constant-expression in a noptr-new-declarator shall be +// an integral constant expression +auto new1 = new int[1][ok]; +auto new2 = new int[1][incomplete]; // expected-error {{incomplete}} +auto new3 = new int[1][expl]; // expected-error {{explicit conversion}} +auto new4 = new int[1][ambig]; // expected-error {{ambiguous conversion}} + +// [dcl.enum]p5: If the underlying type is not fixed [...] the initializing +// value [...] shall be an integral constant expression. +enum NotFixed { + enum1 = ok, + enum2 = incomplete, // expected-error {{incomplete}} + enum3 = expl, // expected-error {{explicit conversion}} + enum4 = ambig // expected-error {{ambiguous conversion}} +}; + +// [dcl.align]p2: When the alignment-specifier is of the form +// alignas(assignment-expression), the assignment-expression shall be an +// integral constant expression +int alignas(ok) alignas1; +int alignas(incomplete) alignas2; // expected-error {{incomplete}} +int alignas(expl) alignas3; // expected-error {{explicit conversion}} +int alignas(ambig) alignas4; // expected-error {{ambiguous conversion}} + +// [dcl.array]p1: If the constant-expression is present, it shall be an integral +// constant expression +// FIXME: The VLA recovery results in us giving diagnostics which aren't great +// here. +int array1[ok]; +int array2[incomplete]; // expected-error {{non-integer type}} +int array3[expl]; // expected-error {{non-integer type}} +int array4[ambig]; // expected-error {{non-integer type}} + +// [class.bit]p1: The constasnt-expression shall be an integral constant +// expression +struct Bitfields { + int bitfield1 : ok; + int bitfield2 : incomplete; // expected-error {{incomplete}} + int bitfield3 : expl; // expected-error {{explicit conversion}} + int bitfield4 : ambig; // expected-error {{ambiguous conversion}} +}; diff --git a/clang/test/CXX/expr/expr.mptr.oper/p5.cpp b/clang/test/CXX/expr/expr.mptr.oper/p5.cpp new file mode 100644 index 0000000..7380b5d --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.mptr.oper/p6-0x.cpp b/clang/test/CXX/expr/expr.mptr.oper/p6-0x.cpp new file mode 100644 index 0000000..917b2da --- /dev/null +++ b/clang/test/CXX/expr/expr.mptr.oper/p6-0x.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/expr/expr.post/expr.call/p7-0x.cpp b/clang/test/CXX/expr/expr.post/expr.call/p7-0x.cpp new file mode 100644 index 0000000..d51ba09 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.call/p7-0x.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct X1 { + X1(); +}; + +struct X2 { + X2(); + ~X2(); +}; + +void vararg(...); + +void f(X1 x1, X2 x2) { + vararg(x1); // okay + vararg(x2); // expected-error{{cannot pass object of non-trivial type 'X2' through variadic function; call will abort at runtime}} +} + + +namespace PR11131 { + struct S; + + S &getS(); + + void f(...); + + void g() { + (void)sizeof(f(getS())); + } +} diff --git a/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp b/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp new file mode 100644 index 0000000..6ba8d51 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp b/clang/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp new file mode 100644 index 0000000..cddd5cf --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/expr/expr.post/expr.ref/p3.cpp b/clang/test/CXX/expr/expr.post/expr.ref/p3.cpp new file mode 100644 index 0000000..98771d3 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.ref/p3.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify -fsyntax-only %s + +template<typename T> struct Node { + int lhs; + void splay( ) + { + Node<T> n[1]; + (void)n->lhs; + } +}; + +void f() { + Node<int> n; + return n.splay(); +} diff --git a/clang/test/CXX/expr/expr.post/expr.reinterpret.cast/p1-0x.cpp b/clang/test/CXX/expr/expr.post/expr.reinterpret.cast/p1-0x.cpp new file mode 100644 index 0000000..22892a6 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.reinterpret.cast/p1-0x.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp b/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp new file mode 100644 index 0000000..9ef15e6 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/expr/expr.post/expr.static.cast/p9-0x.cpp b/clang/test/CXX/expr/expr.post/expr.static.cast/p9-0x.cpp new file mode 100644 index 0000000..731c508 --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.static.cast/p9-0x.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/expr/expr.post/expr.type.conv/p1-0x.cpp b/clang/test/CXX/expr/expr.post/expr.type.conv/p1-0x.cpp new file mode 100644 index 0000000..253744e --- /dev/null +++ b/clang/test/CXX/expr/expr.post/expr.type.conv/p1-0x.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct foo { + foo(); + foo(int); +}; + +int func(foo& f) { + decltype(foo())(); + f = (decltype(foo()))5; + return decltype(3)(5); +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp new file mode 100644 index 0000000..249c976 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct S { + int *j = &nonexistent; // expected-error {{use of undeclared identifier 'nonexistent'}} + int *m = &n; // ok + + int n = f(); // ok + int f(); +}; + +int i = sizeof(S::m); // ok +int j = sizeof(S::m + 42); // ok + + +struct T { + int n; + static void f() { + int a[n]; // expected-error {{invalid use of member 'n' in static member function}} + int b[sizeof n]; // ok + } +}; + +// Make sure the rule for unevaluated operands works correctly with typeid. +namespace std { + class type_info; +} +class Poly { virtual ~Poly(); }; +const std::type_info& k = typeid(S::m); +const std::type_info& m = typeid(*(Poly*)S::m); // expected-error {{invalid use of non-static data member}} +const std::type_info& n = typeid(*(Poly*)(0*sizeof S::m)); + +namespace PR11956 { + struct X { char a; }; + struct Y { int f() { return sizeof(X::a); } }; // ok + + struct A { enum E {} E; }; + struct B { int f() { return sizeof(A::E); } }; // ok +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp new file mode 100644 index 0000000..030c90c --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +struct A { + int &f(int*); + float &f(int*) const noexcept; + + int *ptr; + auto g1() noexcept(noexcept(f(ptr))) -> decltype(f(this->ptr)); + auto g2() const noexcept(noexcept(f((*this).ptr))) -> decltype(f(ptr)); +}; + +void testA(A &a) { + int &ir = a.g1(); + float &fr = a.g2(); + static_assert(!noexcept(a.g1()), "exception-specification failure"); + static_assert(noexcept(a.g2()), "exception-specification failure"); +} + +struct B { + char g(); + template<class T> auto f(T t) -> decltype(t + g()) + { return t + g(); } +}; + +template auto B::f(int t) -> decltype(t + g()); + +template<typename T> +struct C { + int &f(T*); + float &f(T*) const noexcept; + + T* ptr; + auto g1() noexcept(noexcept(f(ptr))) -> decltype(f((*this).ptr)); + auto g2() const noexcept(noexcept(f(((this))->ptr))) -> decltype(f(ptr)); +}; + +void test_C(C<int> ci) { + int *p = 0; + int &ir = ci.g1(); + float &fr = ci.g2(); + static_assert(!noexcept(ci.g1()), "exception-specification failure"); + static_assert(noexcept(ci.g2()), "exception-specification failure"); +} + +namespace PR10036 { + template <class I> + void + iter_swap(I x, I y) noexcept; + + template <class T> + class A + { + T t_; + public: + void swap(A& a) noexcept(noexcept(iter_swap(&t_, &a.t_))); + }; + + void test() { + A<int> i, j; + i.swap(j); + } +} + +namespace Static { + struct X1 { + int m; + static auto f() -> decltype(m); // expected-error{{'this' cannot be implicitly used in a static member function declaration}} + static auto g() -> decltype(this->m); // expected-error{{'this' cannot be used in a static member function declaration}} + + static int h(); + + static int i() noexcept(noexcept(m + 2)); // expected-error{{'this' cannot be implicitly used in a static member function declaration}} + }; + + auto X1::h() -> decltype(m) { return 0; } // expected-error{{'this' cannot be implicitly used in a static member function declaration}} + + template<typename T> + struct X2 { + int m; + + T f(T*); + static T f(int); + + auto g(T x) -> decltype(f(x)) { return 0; } + }; + + void test_X2() { + X2<int>().g(0); + } +} + +namespace PR12564 { + struct Base { + void bar(Base&) {} // unexpected-note {{here}} + }; + + struct Derived : Base { + // FIXME: This should be accepted. + void foo(Derived& d) noexcept(noexcept(d.bar(d))) {} // unexpected-error {{cannot bind to a value of unrelated type}} + }; +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp new file mode 100644 index 0000000..4e57b74 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct S { + S *p = this; // ok + decltype(this) q; // expected-error {{invalid use of 'this' outside of a non-static member function}} + + int arr[sizeof(this)]; // expected-error {{invalid use of 'this' outside of a non-static member function}} + int sz = sizeof(this); // ok +}; + +namespace CaptureThis { + struct X { + int n = 10; + int m = [&]{return n + 1; }(); + int o = [&]{return this->m + 1; }(); + int p = [&]{return [&](int x) { return this->m + x;}(o); }(); + }; + + X x; +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp new file mode 100644 index 0000000..5b3a004 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp @@ -0,0 +1,78 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +struct global { +}; + +namespace PR10127 { + struct outer { + struct middle { + struct inner { + int func(); + int i; + }; + struct inner2 { + }; + struct inner3 { + }; + int mfunc(); + }; + typedef int td_int; + }; + + struct str { + operator decltype(outer::middle::inner()) (); + operator decltype(outer::middle())::inner2 (); + operator decltype(outer())::middle::inner3 (); + str(int (decltype(outer::middle::inner())::*n)(), + int (decltype(outer::middle())::inner::*o)(), + int (decltype(outer())::middle::inner::*p)()); + }; + + decltype(outer::middle::inner()) a; + void scope() { + a.decltype(outer::middle())::mfunc(); // expected-error{{'PR10127::outer::middle::mfunc' is not a member of class 'decltype(outer::middle::inner())'}} + a.decltype(outer::middle::inner())::func(); + a.decltype(outer::middle())::inner::func(); + a.decltype(outer())::middle::inner::func(); + + a.decltype(outer())::middle::inner::~inner(); + + decltype(outer())::middle::inner().func(); + } + decltype(outer::middle())::inner b; + decltype(outer())::middle::inner c; + decltype(outer())::fail d; // expected-error{{no type named 'fail' in 'PR10127::outer'}} + decltype(outer())::fail::inner e; // expected-error{{no member named 'fail' in 'PR10127::outer'}} + decltype()::fail f; // expected-error{{expected expression}} + decltype()::middle::fail g; // expected-error{{expected expression}} + + decltype(int()) h; + decltype(int())::PR10127::outer i; // expected-error{{'decltype(int())' (aka 'int') is not a class, namespace, or scoped enumeration}} + decltype(int())::global j; // expected-error{{'decltype(int())' (aka 'int') is not a class, namespace, or scoped enumeration}} + + outer::middle k = decltype(outer())::middle(); + outer::middle::inner l = decltype(outer())::middle::inner(); + + template<typename T> + struct templ { + typename decltype(T())::middle::inner x; // expected-error{{type 'decltype(int())' (aka 'int') cannot be used prior to '::' because it has no members}} + }; + + template class templ<int>; // expected-note{{in instantiation of template class 'PR10127::templ<int>' requested here}} + template class templ<outer>; + + enum class foo { + bar, + baz + }; + + foo m = decltype(foo::bar)::baz; + + enum E { + }; + struct bar { + enum E : decltype(outer())::td_int(4); + enum F : decltype(outer())::td_int; + enum G : decltype; // expected-error{{expected '(' after 'decltype'}} + }; +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm new file mode 100644 index 0000000..0c3fdb2 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm @@ -0,0 +1,88 @@ +// RUN: %clang_cc1 -std=c++11 -fblocks %s -verify + +void block_capture_errors() { + __block int var; // expected-note 2{{'var' declared here}} + (void)[var] { }; // expected-error{{__block variable 'var' cannot be captured in a lambda}} + + (void)[=] { var = 17; }; // expected-error{{__block variable 'var' cannot be captured in a lambda}} +} + +void conversion_to_block(int captured) { + int (^b1)(int) = [=](int x) { return x + captured; }; + + const auto lambda = [=](int x) { return x + captured; }; + int (^b2)(int) = lambda; +} + +template<typename T> +class ConstCopyConstructorBoom { +public: + ConstCopyConstructorBoom(ConstCopyConstructorBoom&); + + ConstCopyConstructorBoom(const ConstCopyConstructorBoom&) { + T *ptr = 1; // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}} + } + + void foo() const; +}; + +void conversion_to_block_init(ConstCopyConstructorBoom<int> boom, + ConstCopyConstructorBoom<float> boom2) { + const auto& lambda1([=] { boom.foo(); }); // okay + + const auto& lambda2([=] { boom2.foo(); }); // expected-note{{in instantiation of member function}} + void (^block)(void) = lambda2; +} + + +void nesting() { + int array[7]; // expected-note 2{{'array' declared here}} + [=] () mutable { + [&] { + ^ { + int i = array[2]; + i += array[3]; + }(); + }(); + }(); + + [&] { + [=] () mutable { + ^ { + int i = array[2]; // expected-error{{cannot refer to declaration with an array type inside block}} + i += array[3]; // expected-error{{cannot refer to declaration with an array type inside block}} + }(); + }(); + }(); +} + +namespace overloading { + void bool_conversion() { + if ([](){}) { + } + + bool b = []{}; + b = (bool)[]{}; + } + + void conversions() { + int (*fp)(int) = [](int x) { return x + 1; }; + fp = [](int x) { return x + 1; }; + + typedef int (*func_ptr)(int); + fp = (func_ptr)[](int x) { return x + 1; }; + + int (^bp)(int) = [](int x) { return x + 1; }; + bp = [](int x) { return x + 1; }; + + typedef int (^block_ptr)(int); + bp = (block_ptr)[](int x) { return x + 1; }; + } + + int &accept_lambda_conv(int (*fp)(int)); + float &accept_lambda_conv(int (^bp)(int)); + + void call_with_lambda() { + int &ir = accept_lambda_conv([](int x) { return x + 1; }); + } +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp new file mode 100644 index 0000000..5dac886 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -Wno-lambda-extensions -verify + +void defargs() { + auto l1 = [](int i, int j = 17, int k = 18) { return i + j + k; }; + int i1 = l1(1); + int i2 = l1(1, 2); + int i3 = l1(1, 2, 3); +} + + +void defargs_errors() { + auto l1 = [](int i, + int j = 17, + int k) { }; // expected-error{{missing default argument on parameter 'k'}} + + auto l2 = [](int i, int j = i) {}; // expected-error{{default argument references parameter 'i'}} + + int foo; + auto l3 = [](int i = foo) {}; // expected-error{{default argument references local variable 'foo' of enclosing function}} +} + +struct NonPOD { + NonPOD(); + NonPOD(const NonPOD&); + ~NonPOD(); +}; + +struct NoDefaultCtor { + NoDefaultCtor(const NoDefaultCtor&); // expected-note{{candidate constructor}} + ~NoDefaultCtor(); +}; + +template<typename T> +void defargs_in_template_unused(T t) { + auto l1 = [](const T& value = T()) { }; + l1(t); +} + +template void defargs_in_template_unused(NonPOD); +template void defargs_in_template_unused(NoDefaultCtor); + +template<typename T> +void defargs_in_template_used() { + auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}} + l1(); // expected-note{{in instantiation of default function argument expression for 'operator()<NoDefaultCtor>' required here}} +} + +template void defargs_in_template_used<NonPOD>(); +template void defargs_in_template_used<NoDefaultCtor>(); // expected-note{{in instantiation of function template specialization}} + diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp new file mode 100644 index 0000000..245e270 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +int GlobalVar; // expected-note {{declared here}} + +namespace N { + int AmbiguousVar; // expected-note {{candidate}} +} +int AmbiguousVar; // expected-note {{candidate}} +using namespace N; + +class X0 { + int Member; + + static void Overload(int); + void Overload(); + virtual X0& Overload(float); + + void explicit_capture() { + int variable; // expected-note {{declared here}} + (void)[&Overload] () {}; // expected-error {{does not name a variable}} + (void)[&GlobalVar] () {}; // expected-error {{does not have automatic storage duration}} + (void)[&AmbiguousVar] () {}; // expected-error {{reference to 'AmbiguousVar' is ambiguous}} + (void)[&Variable] () {}; // expected-error {{use of undeclared identifier 'Variable'; did you mean 'variable'}} + } +}; + +void test_reaching_scope() { + int local; // expected-note{{declared here}} + static int local_static; // expected-note{{'local_static' declared here}} + (void)[=]() { + struct InnerLocal { + void member() { + (void)[local, // expected-error{{reference to local variable 'local' declared in enclosing function 'test_reaching_scope'}} + local_static]() { // expected-error{{'local_static' cannot be captured because it does not have automatic storage duration}} + return 0; + }; + } + }; + }; +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp new file mode 100644 index 0000000..d265dd7 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +void test_reaching_scope() { + int local; // expected-note{{declared here}} + static int local_static; + (void)[=]() { + struct InnerLocal { + void member() { + (void)[=]() { + return local + // expected-error{{reference to local variable 'local' declared in enclosing function 'test_reaching_scope'}} + local_static; + }; + } + }; + }; +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp new file mode 100644 index 0000000..4a2a4f3 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +void odr_used() { + int i = 17; + [i]{}(); +} + +struct ReachingThis { + static void static_foo() { + (void)[this](){}; // expected-error{{'this' cannot be captured in this context}} + + struct Local { + int i; + + void bar() { + (void)[this](){}; + (void)[&](){i = 7; }; + } + }; + } + + void foo() { + (void)[this](){}; + + struct Local { + int i; + + static void static_bar() { + (void)[this](){}; // expected-error{{'this' cannot be captured in this context}} + (void)[&](){i = 7; }; // expected-error{{invalid use of member 'i' in static member function}} + } + }; + } +}; + +void immediately_enclosing(int i) { // expected-note{{'i' declared here}} + [i]() { + [i] {}(); + }(); + + [=]() { + [i] {}(); + }(); + + []() { // expected-note{{lambda expression begins here}} + [i] {}(); // expected-error{{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}} + }(); +} + +void f1(int i) { // expected-note{{declared here}} + int const N = 20; + auto m1 = [=]{ + int const M = 30; + auto m2 = [i]{ + int x[N][M]; + x[0][0] = i; + }; + (void)N; + (void)M; + (void)m2; + }; + struct s1 { + int f; + void work(int n) { // expected-note{{declared here}} + int m = n*n; + int j = 40; // expected-note{{declared here}} + auto m3 = [this,m] { // expected-note 3{{lambda expression begins here}} + auto m4 = [&,j] { // expected-error{{variable 'j' cannot be implicitly captured in a lambda with no capture-default specified}} + int x = n; // expected-error{{variable 'n' cannot be implicitly captured in a lambda with no capture-default specified}} + x += m; + x += i; // expected-error{{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}} + x += f; + }; + }; + } + }; +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp new file mode 100644 index 0000000..8bb707e --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +void f2() { + int i = 1; + void g1(int = ([i]{ return i; })()); // expected-error{{lambda expression in default argument cannot capture any entity}} + void g2(int = ([i]{ return 0; })()); // expected-error{{lambda expression in default argument cannot capture any entity}} + void g3(int = ([=]{ return i; })()); // expected-error{{lambda expression in default argument cannot capture any entity}} + void g4(int = ([=]{ return 0; })()); + void g5(int = ([]{ return sizeof i; })()); +} + +namespace lambda_in_default_args { + int f(int = [] () -> int { int n; return ++n; } ()); + template<typename T> T g(T = [] () -> T { T n; return ++n; } ()); + int k = f() + g<int>(); +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp new file mode 100644 index 0000000..678fa4b --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +template<typename T> void capture(const T&); + +class NonCopyable { + NonCopyable(const NonCopyable&); // expected-note 2 {{implicitly declared private here}} +public: + void foo() const; +}; + +class NonConstCopy { +public: + NonConstCopy(NonConstCopy&); // expected-note{{would lose const}} +}; + +void capture_by_copy(NonCopyable nc, NonCopyable &ncr, const NonConstCopy nco) { + (void)[nc] { }; // expected-error{{capture of variable 'nc' as type 'NonCopyable' calls private copy constructor}} + (void)[=] { + ncr.foo(); // expected-error{{capture of variable 'ncr' as type 'NonCopyable' calls private copy constructor}} + }(); + + [nco] {}(); // expected-error{{no matching constructor for initialization of 'const NonConstCopy'}} +} + +struct NonTrivial { + NonTrivial(); + NonTrivial(const NonTrivial &); + ~NonTrivial(); +}; + +struct CopyCtorDefault { + CopyCtorDefault(); + CopyCtorDefault(const CopyCtorDefault&, NonTrivial nt = NonTrivial()); + + void foo() const; +}; + +void capture_with_default_args(CopyCtorDefault cct) { + (void)[=] () -> void { cct.foo(); }; +} + +struct ExpectedArrayLayout { + CopyCtorDefault array[3]; +}; + +void capture_array() { + CopyCtorDefault array[3]; + auto x = [=]() -> void { + capture(array[0]); + }; + static_assert(sizeof(x) == sizeof(ExpectedArrayLayout), "layout mismatch"); +} + +// Check for the expected non-static data members. + +struct ExpectedLayout { + char a; + short b; +}; + +void test_layout(char a, short b) { + auto x = [=] () -> void { + capture(a); + capture(b); + }; + static_assert(sizeof(x) == sizeof(ExpectedLayout), "Layout mismatch!"); +} + +struct ExpectedThisLayout { + ExpectedThisLayout* a; + void f() { + auto x = [this]() -> void {}; + static_assert(sizeof(x) == sizeof(ExpectedThisLayout), "Layout mismatch!"); + } +}; diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp new file mode 100644 index 0000000..c4deba9 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +class NonCopyable { + NonCopyable(const NonCopyable&); +}; + +void capture_by_ref(NonCopyable nc, NonCopyable &ncr) { + int array[3]; + (void)[&nc] () -> void {}; + (void)[&ncr] () -> void {}; + (void)[&array] () -> void {}; +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp new file mode 100644 index 0000000..0cf01ad --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + + +struct X { + X(const X&) = delete; // expected-note 2{{explicitly marked deleted}} + X(X&); +}; + +void test_capture(X x) { + [x] { }(); // okay: non-const copy ctor + + [x] { + [x] { // expected-error{{call to deleted constructor of 'X'}} + }(); + }(); + + [x] { + [&x] { + [x] { // expected-error{{call to deleted constructor of 'const X'}} + }(); + }(); + }(); + + int a; + [=]{ + [&] { + int &x = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}} + int &x2 = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}} + }(); + }(); + + [=]{ + [&a] { + [&] { + int &x = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}} + int &x2 = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}} + }(); + }(); + }(); +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp new file mode 100644 index 0000000..930a4b3 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +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; +}; + +void f3() { + float x, &r = x; + int i; + int &ir = i; + const int &irc = i; + + [=,&irc,&ir] { + static_assert(is_same<decltype(((r))), float const&>::value, + "should be const float&"); + static_assert(is_same<decltype(x), float>::value, "should be float"); + static_assert(is_same<decltype((x)), const float&>::value, + "should be const float&"); + static_assert(is_same<decltype(r), float&>::value, "should be float&"); + static_assert(is_same<decltype(ir), int&>::value, "should be int&"); + static_assert(is_same<decltype((ir)), int&>::value, "should be int&"); + static_assert(is_same<decltype(irc), const int&>::value, + "should be const int&"); + static_assert(is_same<decltype((irc)), const int&>::value, + "should be const int&"); + }(); + + [=] { + [=] () mutable { + static_assert(is_same<decltype(x), float>::value, "should be float"); + static_assert(is_same<decltype((x)), float&>::value, + "should be float&"); + }(); + }(); + + [&i] { + static_assert(is_same<decltype((i)), int&>::value, "should be int&"); + }(); +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp new file mode 100644 index 0000000..6fe3b25 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +struct MoveOnly { + MoveOnly(MoveOnly&&); + MoveOnly(const MoveOnly&); +}; + +template<typename T> T &&move(T&); +void test_special_member_functions(MoveOnly mo, int i) { + auto lambda1 = [i]() { }; // expected-note 2 {{lambda expression begins here}} + + // Default constructor + decltype(lambda1) lambda2; // expected-error{{call to implicitly-deleted default constructor of 'decltype(lambda1)' (aka '<lambda}} + + // Copy assignment operator + lambda1 = lambda1; // expected-error{{overload resolution selected implicitly-deleted copy assignment operator}} + + // Move assignment operator + lambda1 = move(lambda1); + + // Copy constructor + decltype(lambda1) lambda3 = lambda1; + decltype(lambda1) lambda4(lambda1); + + // Move constructor + decltype(lambda1) lambda5 = move(lambda1); + decltype(lambda1) lambda6(move(lambda1)); +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp new file mode 100644 index 0000000..c6ed308 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +// prvalue +void prvalue() { + auto&& x = []()->void { }; + auto& y = []()->void { }; // expected-error{{cannot bind to a temporary of type}} +} + +namespace std { + class type_info; +} + +struct P { + virtual ~P(); +}; + +void unevaluated_operand(P &p, int i) { + int i2 = sizeof([]()->void{}()); // expected-error{{lambda expression in an unevaluated operand}} + const std::type_info &ti1 = typeid([&]() -> P& { return p; }()); + const std::type_info &ti2 = typeid([&]() -> int { return i; }()); // expected-error{{lambda expression in an unevaluated operand}} +} + +template<typename T> +struct Boom { + Boom(const Boom&) { + T* x = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \ + // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}} \ + // expected-error{{cannot initialize a variable of type 'double *' with an rvalue of type 'int'}} + } + void tickle() const; +}; + +void odr_used(P &p, Boom<int> boom_int, Boom<float> boom_float, + Boom<double> boom_double) { + const std::type_info &ti1 + = typeid([=,&p]() -> P& { boom_int.tickle(); return p; }()); // expected-note{{in instantiation of member function 'Boom<int>::Boom' requested here}} + const std::type_info &ti2 + = typeid([=]() -> int { boom_float.tickle(); return 0; }()); // expected-error{{lambda expression in an unevaluated operand}} \ + // expected-note{{in instantiation of member function 'Boom<float>::Boom' requested here}} + + auto foo = [=]() -> int { boom_double.tickle(); return 0; }; // expected-note{{in instantiation of member function 'Boom<double>::Boom' requested here}} +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp new file mode 100644 index 0000000..4487cfc --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify + +template<typename T> +void destroy(T* ptr) { + ptr->~T(); + (*ptr).~T(); +} + +void destructor() { + auto lambda = []{}; + destroy(&lambda); +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp new file mode 100644 index 0000000..7139058 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +struct DirectInitOnly { + explicit DirectInitOnly(DirectInitOnly&); +}; + +void direct_init_capture(DirectInitOnly &dio) { + [dio] {}(); +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp new file mode 100644 index 0000000..174db25 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +void print(); + +template<typename T, typename... Ts> +void print(T first, Ts... rest) { + (void)first; + print(rest...); +} + +template<typename... Ts> +void unsupported(Ts ...values) { + auto unsup = [values] {}; // expected-error{{unexpanded function parameter pack capture is unsupported}} +} + +template<typename... Ts> +void implicit_capture(Ts ...values) { + auto implicit = [&] { print(values...); }; + implicit(); +} + +template<typename... Ts> +void do_print(Ts... values) { + auto bycopy = [values...]() { print(values...); }; + bycopy(); + auto byref = [&values...]() { print(values...); }; + byref(); + + auto bycopy2 = [=]() { print(values...); }; + bycopy2(); + auto byref2 = [&]() { print(values...); }; + byref2(); +} + +template void do_print(int, float, double); + +template<typename T, int... Values> +void bogus_expansions(T x) { + auto l1 = [x...] {}; // expected-error{{pack expansion does not contain any unexpanded parameter packs}} + auto l2 = [Values...] {}; // expected-error{{'Values' in capture list does not name a variable}} +} + +void g(int*, float*, double*); + +template<class... Args> +void std_example(Args... args) { + auto lm = [&, args...] { return g(args...); }; +}; + +template void std_example(int*, float*, double*); + +template<typename ...Args> +void variadic_lambda(Args... args) { + auto lambda = [](Args... inner_args) { return g(inner_args...); }; + lambda(args...); +} + +template void variadic_lambda(int*, float*, double*); diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp new file mode 100644 index 0000000..562f92a --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +void test_nonaggregate(int i) { + auto lambda = [i]() -> void {}; // expected-note 3{{candidate constructor}} + decltype(lambda) foo = { 1 }; // expected-error{{no matching constructor}} +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp new file mode 100644 index 0000000..d816e17 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +void missing_lambda_declarator() { + [](){}(); +} + +template<typename T> T get(); + +void infer_void_return_type(int i) { + if (i > 17) + return []() { }(); + + if (i > 11) + return []() { return; }(); + + return [](int x) { + switch (x) { + case 0: return get<void>(); + case 1: return; + case 2: return { 1, 2.0 }; // expected-error{{cannot deduce lambda return type from initializer list}} + } + }(7); +} + +struct X { }; + +X infer_X_return_type(X x) { + return [&x](int y) { // expected-warning{{omitted result type}} + if (y > 0) + return X(); + else + return x; + }(5); +} + +X infer_X_return_type_fail(X x) { + return [x](int y) { // expected-warning{{omitted result type}} + if (y > 0) + return X(); + else + return x; // expected-error{{return type 'const X' must match previous return type 'X' when lambda expression has unspecified explicit return type}} + }(5); +} + +struct Incomplete; // expected-note{{forward declaration of 'Incomplete'}} +void test_result_type(int N) { + auto l1 = [] () -> Incomplete { }; // expected-error{{incomplete result type 'Incomplete' in lambda expression}} + + typedef int vla[N]; + auto l2 = [] () -> vla { }; // expected-error{{function cannot return array type 'vla' (aka 'int [N]')}} +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm new file mode 100644 index 0000000..0126e23 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +@interface A +@end + +void test_result_type() { + auto l1 = [] () -> A { }; // expected-error{{non-pointer Objective-C class type 'A' in lambda expression result}} +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp new file mode 100644 index 0000000..68460f0 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -std=c++11 %s -Winvalid-noreturn -verify + +// An attribute-specifier-seq in a lambda-declarator appertains to the +// type of the corresponding function call operator. +void test_attributes() { + auto nrl = [](int x) -> int { if (x > 0) return x; }; // expected-warning{{control may reach end of non-void lambda}} + + auto nrl2 = []() [[noreturn]] { return; }; // expected-error{{lambda declared 'noreturn' should not return}} +} + +template<typename T> +struct bogus_override_if_virtual : public T { + bogus_override_if_virtual() : T(*(T*)0) { } + int operator()() const; +}; + +void test_quals() { + // This function call operator is declared const (9.3.1) if and only + // if the lambda- expression's parameter-declaration-clause is not + // followed by mutable. + auto l = [=](){}; // expected-note{{method is not marked volatile}} + const decltype(l) lc = l; + l(); + lc(); + + auto ml = [=]() mutable{}; // expected-note{{method is not marked const}} \ + // expected-note{{method is not marked volatile}} + const decltype(ml) mlc = ml; + ml(); + mlc(); // expected-error{{no matching function for call to object of type}} + + // It is neither virtual nor declared volatile. + volatile decltype(l) lv = l; + volatile decltype(ml) mlv = ml; + lv(); // expected-error{{no matching function for call to object of type}} + mlv(); // expected-error{{no matching function for call to object of type}} + + bogus_override_if_virtual<decltype(l)> bogus; +} + +// Default arguments (8.3.6) shall not be specified in the +// parameter-declaration-clause of a lambda- declarator. +// Note: Removed by core issue 974. +int test_default_args() { + return [](int i = 5, // expected-warning{{C++11 forbids default arguments for lambda expressions}} + int j = 17) { return i+j;}(5, 6); +} + +// Any exception-specification specified on a lambda-expression +// applies to the corresponding function call operator. +void test_exception_spec() { + auto tl1 = []() throw(int) {}; + auto tl2 = []() {}; + static_assert(!noexcept(tl1()), "lambda can throw"); + static_assert(!noexcept(tl2()), "lambda can throw"); + + auto ntl1 = []() throw() {}; + auto ntl2 = []() noexcept(true) {}; + auto ntl3 = []() noexcept {}; + static_assert(noexcept(ntl1()), "lambda cannot throw"); + static_assert(noexcept(ntl2()), "lambda cannot throw"); + static_assert(noexcept(ntl3()), "lambda cannot throw"); +} + diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp new file mode 100644 index 0000000..8b43cef --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +void test_conversion() { + int (*fp1)(int) = [](int x) { return x + 1; }; + void (*fp2)(int) = [](int x) { }; + + const auto lambda = [](int x) { }; + void (*fp3)(int) = lambda; + + volatile const auto lambda2 = [](int x) { }; // expected-note{{but method is not marked volatile}} + void (*fp4)(int) = lambda2; // expected-error{{no viable conversion}} +} + +void test_no_conversion() { + int (*fp1)(int) = [=](int x) { return x + 1; }; // expected-error{{no viable conversion}} + void (*fp2)(int) = [&](int x) { }; // expected-error{{no viable conversion}} +} + +void test_wonky() { + const auto l = [](int x) mutable -> int { return + 1; }; + l(17); // okay: uses conversion function +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp new file mode 100644 index 0000000..9dbe2e1 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify + +// Check that analysis-based warnings work in lambda bodies. +void analysis_based_warnings() { + (void)[]() -> int { }; // expected-warning{{control reaches end of non-void lambda}} +} + +// Check that we get the right types of captured variables (the +// semantic-analysis part of p7). +int &check_const_int(int&); +float &check_const_int(const int&); + +void test_capture_constness(int i, const int ic) { + (void)[i,ic] ()->void { + float &fr1 = check_const_int(i); + float &fr2 = check_const_int(ic); + }; + + (void)[=] ()->void { + float &fr1 = check_const_int(i); + float &fr2 = check_const_int(ic); + }; + + (void)[i,ic] () mutable ->void { + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; + + (void)[=] () mutable ->void { + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; + + (void)[&i,&ic] ()->void { + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; + + (void)[&] ()->void { + int &ir = check_const_int(i); + float &fr = check_const_int(ic); + }; +} + + +struct S1 { + int x, y; + S1 &operator=(int*); + int operator()(int); + void f() { + [&]()->int { + S1 &s1 = operator=(&this->x); + return operator()(this->x + y); + }(); + } +}; diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp new file mode 100644 index 0000000..d1384f1 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +class X0 { + void explicit_capture() { + int foo; + + (void)[foo, foo] () {}; // expected-error {{'foo' can appear only once}} + (void)[this, this] () {}; // expected-error {{'this' can appear only once}} + (void)[=, foo] () {}; // expected-error {{'&' must precede a capture when}} + (void)[=, &foo] () {}; + (void)[=, this] () {}; // expected-error {{'this' cannot be explicitly captured}} + (void)[&, foo] () {}; + (void)[&, &foo] () {}; // expected-error {{'&' cannot precede a capture when}} + (void)[&, this] () {}; + } +}; + +struct S2 { + void f(int i); + void g(int i); +}; + +void S2::f(int i) { + (void)[&, i]{ }; + (void)[&, &i]{ }; // expected-error{{'&' cannot precede a capture when the capture default is '&'}} + (void)[=, this]{ }; // expected-error{{'this' cannot be explicitly captured}} + (void)[=]{ this->g(i); }; + (void)[i, i]{ }; // expected-error{{'i' can appear only once in a capture list}} +} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp new file mode 100644 index 0000000..49b9c66 --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp @@ -0,0 +1,149 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Winvalid-noreturn %s -verify + +template<typename T> +void test_attributes() { + auto nrl = []() [[noreturn]] {}; // expected-error{{lambda declared 'noreturn' should not return}} +} + +template void test_attributes<int>(); // expected-note{{in instantiation of function}} + +template<typename T> +void call_with_zero() { + [](T *ptr) -> T& { return *ptr; }(0); +} + +template void call_with_zero<int>(); + +template<typename T> +T captures(T x, T y) { + auto lambda = [=, &y] () -> T { + T i = x; + return i + y; + }; + + return lambda(); +} + +struct X { + X(const X&); +}; + +X operator+(X, X); +X operator-(X, X); + +template int captures(int, int); +template X captures(X, X); + +template<typename T> +int infer_result(T x, T y) { + auto lambda = [=](bool b) { return x + y; }; + return lambda(true); // expected-error{{no viable conversion from 'X' to 'int'}} +} + +template int infer_result(int, int); +template int infer_result(X, X); // expected-note{{in instantiation of function template specialization 'infer_result<X>' requested here}} + +// Make sure that lambda's operator() can be used from templates. +template<typename F> +void accept_lambda(F f) { + f(1); +} + +template<typename T> +void pass_lambda(T x) { + accept_lambda([&x](T y) { return x + y; }); +} + +template void pass_lambda(int); + +namespace std { + class type_info; +} + +namespace p2 { + struct P { + virtual ~P(); + }; + + template<typename T> + struct Boom { + Boom(const Boom&) { + T* x = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \ + // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}} + } + void tickle() const; + }; + + template<typename R, typename T> + void odr_used(R &r, Boom<T> boom) { + const std::type_info &ti + = typeid([=,&r] () -> R& { // expected-error{{lambda expression in an unevaluated operand}} + boom.tickle(); // expected-note{{in instantiation of member function}} + return r; + }()); + } + + template void odr_used(int&, Boom<int>); // expected-note{{in instantiation of function template specialization}} + + template<typename R, typename T> + void odr_used2(R &r, Boom<T> boom) { + const std::type_info &ti + = typeid([=,&r] () -> R& { + boom.tickle(); // expected-note{{in instantiation of member function}} + return r; + }()); + } + + template void odr_used2(P&, Boom<float>); +} + +namespace p5 { + struct NonConstCopy { + NonConstCopy(const NonConstCopy&) = delete; + NonConstCopy(NonConstCopy&); + }; + + template<typename T> + void double_capture(T &nc) { + [=] () mutable { + [=] () mutable { + T nc2(nc); + }(); + }(); + } + + template void double_capture(NonConstCopy&); +} + +namespace NonLocalLambdaInstantation { + template<typename T> + struct X { + static int value; + }; + + template<typename T> + int X<T>::value = []{ return T(); }(); // expected-error{{cannot initialize a variable of type 'int' with an rvalue of type 'int *'}} + + template int X<int>::value; + template int X<float>::value; + template int X<int*>::value; // expected-note{{in instantiation of static data member }} + + template<typename T> + void defaults(int x = []{ return T(); }()) { }; // expected-error{{cannot initialize a parameter of type 'int' with an rvalue of type 'int *'}} \ + // expected-note{{passing argument to parameter 'x' here}} + + void call_defaults() { + defaults<int>(); + defaults<float>(); + defaults<int*>(); // expected-note{{in instantiation of default function argument expression for 'defaults<int *>' required here}} + } + + template<typename T> + struct X2 { + int x = []{ return T(); }(); // expected-error{{cannot initialize a member subobject of type 'int' with an rvalue of type 'int *'}} + }; + + X2<int> x2i; + X2<float> x2f; + X2<int*> x2ip; // expected-note{{in instantiation of template class 'NonLocalLambdaInstantation::X2<int *>' requested here}} +} diff --git a/clang/test/CXX/expr/expr.unary/expr.delete/p5.cpp b/clang/test/CXX/expr/expr.unary/expr.delete/p5.cpp new file mode 100644 index 0000000..ecb2918 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.delete/p5.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -verify %s + +// If the object being deleted has incomplete class type at the point of +// deletion and the complete class has a non-trivial destructor or a +// deallocation function, the behavior is undefined. + +// The trivial case. +class T0; // expected-note {{forward declaration}} +void f0(T0 *a) { delete a; } // expected-warning {{deleting pointer to incomplete type}} +class T0 { ~T0(); }; + +// The trivial case, inside a template instantiation. +template<typename T> +struct T1_A { T *x; ~T1_A() { delete x; } }; // expected-warning {{deleting pointer to incomplete type}} +class T1_B; // expected-note {{forward declaration}} +void f0() { T1_A<T1_B> x; } // expected-note {{in instantiation of member function}} + +// This case depends on when we check T2_C::f0. +class T2_A; +template<typename T> +struct T2_B { void f0(T *a) { delete a; } }; +struct T2_C { T2_B<T2_A> x; void f0(T2_A *a) { x.f0(a); } }; +void f0(T2_A *a) { T2_C x; x.f0(a); } +class T2_A { }; + +// An alternate version of the same. +class T3_A; +template<typename T> +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(); // expected-note{{declared private here}} +}; diff --git a/clang/test/CXX/expr/expr.unary/expr.new/p17-crash.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p17-crash.cpp new file mode 100644 index 0000000..27b915e --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.new/p17-crash.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -emit-llvm-only %s + +// this used to crash due to templ<int>'s dtor not being marked as used by the +// new expression in func() +struct non_trivial { + non_trivial() {} + ~non_trivial() {} +}; +template < typename T > class templ { + non_trivial n; +}; +void func() { + new templ<int>[1][1]; +} diff --git a/clang/test/CXX/expr/expr.unary/expr.new/p17.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p17.cpp new file mode 100644 index 0000000..0d108eb --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.new/p17.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class ctor { + ctor(); // expected-note{{implicitly declared private here}} +}; + +class dtor { + ~dtor(); // expected-note 3 {{implicitly declared private here}} +}; + +void test() { + new ctor[0]; // expected-error{{calling a private constructor of class 'ctor'}} + new dtor[0]; // expected-error{{calling a private destructor of class 'dtor'}} + new dtor[3]; // expected-error{{calling a private destructor of class 'dtor'}} + new dtor[3][3]; // expected-error{{calling a private destructor of class 'dtor'}} +} diff --git a/clang/test/CXX/expr/expr.unary/expr.new/p19.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p19.cpp new file mode 100644 index 0000000..bb69fd5 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.new/p19.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fexceptions %s +typedef __SIZE_TYPE__ size_t; + +// Operator delete template for placement new with global lookup +template<int I> +struct X0 { + X0(); + + static void* operator new(size_t) { + return I; // expected-error{{cannot initialize}} + } + + static void operator delete(void*) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X0() { + // Using the global operator new suppresses the search for a + // operator delete in the class. + ::new X0<2>; + + new X0<3>; // expected-note 2{{instantiation}} +} + +// Operator delete template for placement new[] with global lookup +template<int I> +struct X1 { + X1(); + + static void* operator new[](size_t) { + return I; // expected-error{{cannot initialize}} + } + + static void operator delete[](void*) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X1() { + // Using the global operator new suppresses the search for a + // operator delete in the class. + ::new X1<2> [17]; + + new X1<3> [17]; // expected-note 2{{instantiation}} +} diff --git a/clang/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp new file mode 100644 index 0000000..4ebbfce --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.new/p2-cxx0x.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +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/clang/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp new file mode 100644 index 0000000..eca1ec7 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fexceptions %s +typedef __SIZE_TYPE__ size_t; + +struct S { + // Placement allocation function: + static void* operator new(size_t, size_t); + // Usual (non-placement) deallocation function: + static void operator delete(void*, size_t); // expected-note{{declared here}} +}; + +void testS() { + S* p = new (0) S; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}} +} diff --git a/clang/test/CXX/expr/expr.unary/expr.new/p20.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p20.cpp new file mode 100644 index 0000000..8cbe2b9 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.new/p20.cpp @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fexceptions %s +typedef __SIZE_TYPE__ size_t; + +// Overloaded operator delete with two arguments +template<int I> +struct X0 { + X0(); + static void* operator new(size_t); + static void operator delete(void*, size_t) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X0() { + new X0<1>; // expected-note{{instantiation}} +} + +// Overloaded operator delete with one argument +template<int I> +struct X1 { + X1(); + + static void* operator new(size_t); + static void operator delete(void*) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X1() { + new X1<1>; // expected-note{{instantiation}} +} + +// Overloaded operator delete for placement new +template<int I> +struct X2 { + X2(); + + static void* operator new(size_t, double, double); + static void* operator new(size_t, int, int); + + static void operator delete(void*, const int, int) { + int *ip = I; // expected-error{{cannot initialize}} + } + + static void operator delete(void*, double, double); +}; + +void test_X2() { + new (0, 0) X2<1>; // expected-note{{instantiation}} +} + +// Operator delete template for placement new +struct X3 { + X3(); + + static void* operator new(size_t, double, double); + + template<typename T> + static void operator delete(void*, T x, T) { + double *dp = &x; + int *ip = &x; // expected-error{{cannot initialize}} + } +}; + +void test_X3() { + new (0, 0) X3; // expected-note{{instantiation}} +} + +// Operator delete template for placement new in global scope. +struct X4 { + X4(); + static void* operator new(size_t, double, double); +}; + +template<typename T> +void operator delete(void*, T x, T) { + double *dp = &x; + int *ip = &x; // expected-error{{cannot initialize}} +} + +void test_X4() { + new (0, 0) X4; // expected-note{{instantiation}} +} + +// Useless operator delete hides global operator delete template. +struct X5 { + X5(); + static void* operator new(size_t, double, double); + void operator delete(void*, double*, double*); +}; + +void test_X5() { + new (0, 0) X5; // okay, we found X5::operator delete but didn't pick it +} + +// Operator delete template for placement new +template<int I> +struct X6 { + X6(); + + static void* operator new(size_t) { + return I; // expected-error{{cannot initialize}} + } + + static void operator delete(void*) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X6() { + new X6<3>; // expected-note 2{{instantiation}} +} + +void *operator new(size_t, double, double, double); + +template<typename T> +void operator delete(void*, T x, T, T) { + double *dp = &x; + int *ip = &x; // expected-error{{cannot initialize}} +} +void test_int_new() { + new (1.0, 1.0, 1.0) int; // expected-note{{instantiation}} +} + +// We don't need an operator delete if the type has a trivial +// constructor, since we know that constructor cannot throw. +// FIXME: Is this within the standard? Seems fishy, but both EDG+GCC do it. +#if 0 +template<int I> +struct X7 { + static void* operator new(size_t); + static void operator delete(void*, size_t) { + int *ip = I; // okay, since it isn't instantiated. + } +}; + +void test_X7() { + new X7<1>; +} +#endif + diff --git a/clang/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp b/clang/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp new file mode 100644 index 0000000..afd8ef0 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.sizeof/p5-0x.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp new file mode 100644 index 0000000..5c1029f --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/cg.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-darwin10 -S -emit-llvm -std=c++11 -include %S/ser.h %s -o - | FileCheck %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-darwin10 -emit-pch -o %t-ser.pch -std=c++11 -x c++ %S/ser.h +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -triple x86_64-apple-darwin10 -S -emit-llvm -std=c++11 -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/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp new file mode 100644 index 0000000..b5de1a7 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp @@ -0,0 +1,189 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -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 noexcept_true() noexcept; +void noexcept_false() noexcept(false); + +void call() { + N(nospec()); + N(allspec()); + N(intspec()); + P(emptyspec()); + P(nothrowattr()); + P(noexcept_true()); + N(noexcept_false()); +} + +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); +}; + +typedef int X; + +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()); + P(X().~X()); +} + +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 <class T> void f(T&&) noexcept; +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()); + P(f(T())); + P(new (0) T); + P(delete (T*)0); +} +struct S3 { + virtual ~S3() throw(); + S3() throw(); + explicit S3(int); + S3(const S2&); +}; +template <class T> T&& f2() noexcept; +template <typename T> +void late2() { + P(dynamic_cast<S3&>(f2<T&>())); +} +void operator +(const S1&, float) throw(); +void operator +(const S1&, const S3&); +void tlate() { + late<float, true>(); + late<S3, false>(); + late2<S3>(); +} diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/ser.h b/clang/test/CXX/expr/expr.unary/expr.unary.noexcept/ser.h new file mode 100644 index 0000000..e6e7b79 --- /dev/null +++ b/clang/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/clang/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp new file mode 100644 index 0000000..2dd6b23 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.op/p3.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only %s -verify + +namespace rdar10544564 { + // Check that we don't attempt to use an overloaded operator& when + // naming a pointer-to-member. + struct X { + void** operator & (); + }; + + struct Y + { + public: + X member; + X memfunc1(); + X memfunc2(); + X memfunc2(int); + + void test() { + X Y::*data_mem_ptr = &Y::member; + X (Y::*func_mem_ptr1)() = &Y::memfunc1; + X (Y::*func_mem_ptr2)() = &Y::memfunc2; + } + }; + + X Y::*data_mem_ptr = &Y::member; + X (Y::*func_mem_ptr1)() = &Y::memfunc1; + X (Y::*func_mem_ptr2)() = &Y::memfunc2; +} diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp new file mode 100644 index 0000000..06cc610 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// rdar://problem/8347416 +namespace test0 { + struct A { + void foo(void (A::*)(int)); // expected-note {{passing argument to parameter here}} + template<typename T> void g(T); + + void test() { + foo(&g<int>); // expected-error {{can't form member pointer of type 'void (test0::A::*)(int)' without '&' and class name}} + } + }; +} + +// This should succeed. +namespace test1 { + struct A { + static void f(void (A::*)()); + static void f(void (*)(int)); + void g(); + static void g(int); + + void test() { + f(&g); + } + }; +} + +// Also rdar://problem/8347416 +namespace test2 { + struct A { + static int foo(short); + static int foo(float); + int foo(int); + int foo(double); + + void test(); + }; + + void A::test() { + 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/clang/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp new file mode 100644 index 0000000..ac11940 --- /dev/null +++ b/clang/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp @@ -0,0 +1,35 @@ +// 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 +{ + bool f() { } // expected-note{{possible target for call}} + void f(char) { } // expected-note{{possible target for call}} + bool b = !&f; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} +} diff --git a/clang/test/CXX/expr/p3.cpp b/clang/test/CXX/expr/p3.cpp new file mode 100644 index 0000000..6b243c2 --- /dev/null +++ b/clang/test/CXX/expr/p3.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +double operator +(double, double); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}} + +struct A +{ + operator int(); +}; + +int main() +{ + A a, b; + int i0 = a + 1; + int i1 = a + b; +} diff --git a/clang/test/CXX/expr/p8.cpp b/clang/test/CXX/expr/p8.cpp new file mode 100644 index 0000000..2f6c094 --- /dev/null +++ b/clang/test/CXX/expr/p8.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int a0; +const volatile int a1 = 2; +int a2[16]; +int a3(); + +void f0(int); +void f1(int *); +void f2(int (*)()); + +int main() +{ + f0(a0); + f0(a1); + f1(a2); + f2(a3); +} diff --git a/clang/test/CXX/expr/p9.cpp b/clang/test/CXX/expr/p9.cpp new file mode 100644 index 0000000..803b0cc --- /dev/null +++ b/clang/test/CXX/expr/p9.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// floating-point overloads + +__typeof__(0 + 0.0L) ld0; +long double &ldr = ld0; + +__typeof__(0 + 0.0) d0; +double &dr = d0; + +__typeof__(0 + 0.0f) f0; +float &fr = f0; + +// integral promotions + +signed char c0; +__typeof__(c0 + c0) c1; +int &cr = c1; + +unsigned char uc0; +__typeof__(uc0 + uc0) uc1; +int &ucr = uc1; + +short s0; +__typeof__(s0 + s0) s1; +int &sr = s1; + +unsigned short us0; +__typeof__(us0 + us0) us1; +int &usr = us1; + +// integral overloads + +__typeof__(0 + 0UL) ul0; +unsigned long &ulr = ul0; + +template<bool T> struct selector; +template<> struct selector<true> { typedef long type; }; +template<> struct selector<false> {typedef unsigned long type; }; +__typeof__(0U + 0L) ui_l0; +selector<(sizeof(long) > sizeof(unsigned int))>::type &ui_lr = ui_l0; + +__typeof__(0 + 0L) l0; +long &lr = l0; + +__typeof__(0 + 0U) u0; +unsigned &ur = u0; + +__typeof__(0 + 0) i0; +int &ir = i0; diff --git a/clang/test/CXX/lex/lex.charset/p2-cxx11.cpp b/clang/test/CXX/lex/lex.charset/p2-cxx11.cpp new file mode 100644 index 0000000..b9192ce --- /dev/null +++ b/clang/test/CXX/lex/lex.charset/p2-cxx11.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +char c00 = '\u0000'; // ok +char c01 = '\u0001'; // ok +char c1f = '\u001f'; // ok +char c20 = '\u0020'; // ' ', ok +char c22 = '\u0022'; // ", ok +char c23 = '\u0023'; // #, ok +char c24 = '\u0024'; // $, ok +char c25 = '\u0025'; // %, ok +char c27 = '\u0027'; // ', ok +char c3f = '\u003f'; // ?, ok +char c40 = '\u0040'; // @, ok +char c41 = '\u0041'; // A, ok +char c5f = '\u005f'; // _, ok +char c60 = '\u0060'; // `, ok +char c7e = '\u007e'; // ~, ok +char c7f = '\u007f'; // ok + +wchar_t w007f = L'\u007f'; +wchar_t w0080 = L'\u0080'; +wchar_t w009f = L'\u009f'; +wchar_t w00a0 = L'\u00a0'; + +wchar_t wd799 = L'\ud799'; +wchar_t wd800 = L'\ud800'; // expected-error {{invalid universal character}} +wchar_t wdfff = L'\udfff'; // expected-error {{invalid universal character}} +wchar_t we000 = L'\ue000'; + +char32_t w10fffe = U'\U0010fffe'; +char32_t w10ffff = U'\U0010ffff'; +char32_t w110000 = U'\U00110000'; // expected-error {{invalid universal character}} + +const char *p1 = "\u0000\u0001\u001f\u0020\u0022\u0023\u0024\u0025\u0027\u003f\u0040\u0041\u005f\u0060\u007e\u007f"; +const wchar_t *p2 = L"\u0000\u0012\u004e\u007f\u0080\u009f\u00a0\ud799\ue000"; +const char *p3 = u8"\u0000\u0012\u004e\u007f\u0080\u009f\u00a0\ud799\ue000"; +const char16_t *p4 = u"\u0000\u0012\u004e\u007f\u0080\u009f\u00a0\ud799\ue000"; +const char32_t *p5 = U"\u0000\u0012\u004e\u007f\u0080\u009f\u00a0\ud799\ue000"; +const wchar_t *p6 = L"foo \U00110000 bar"; // expected-error {{invalid universal character}} +const char *p7 = u8"foo \U0000d800 bar"; // expected-error {{invalid universal character}} +const char16_t *p8 = u"foo \U0000dfff bar"; // expected-error {{invalid universal character}} +const char32_t *p9 = U"foo \U0010ffff bar"; // ok diff --git a/clang/test/CXX/lex/lex.charset/p2-cxx98.cpp b/clang/test/CXX/lex/lex.charset/p2-cxx98.cpp new file mode 100644 index 0000000..a5b7ab6 --- /dev/null +++ b/clang/test/CXX/lex/lex.charset/p2-cxx98.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -verify -std=c++98 %s + +char c00 = '\u0000'; // expected-error {{universal character name refers to a control character}} +char c01 = '\u0001'; // expected-error {{universal character name refers to a control character}} +char c1f = '\u001f'; // expected-error {{universal character name refers to a control character}} +char c20 = '\u0020'; // ' ', expected-error {{character ' ' cannot be specified by a universal character name}} +char c22 = '\u0022'; // ", expected-error {{character '"' cannot be specified by a universal character name}} +char c23 = '\u0023'; // #, expected-error {{character '#' cannot be specified by a universal character name}} +char c24 = '\u0024'; // $, ok +char c25 = '\u0025'; // %, expected-error {{character '%' cannot be specified by a universal character name}} +char c27 = '\u0027'; // ', expected-error {{character ''' cannot be specified by a universal character name}} +char c3f = '\u003f'; // ?, expected-error {{character '?' cannot be specified by a universal character name}} +char c40 = '\u0040'; // @, ok +char c41 = '\u0041'; // A, expected-error {{character 'A' cannot be specified by a universal character name}} +char c5f = '\u005f'; // _, expected-error {{character '_' cannot be specified by a universal character name}} +char c60 = '\u0060'; // `, ok +char c7e = '\u007e'; // ~, expected-error {{character '~' cannot be specified by a universal character name}} +char c7f = '\u007f'; // expected-error {{universal character name refers to a control character}} + +wchar_t w007f = L'\u007f'; // expected-error {{universal character name refers to a control character}} +wchar_t w0080 = L'\u0080'; // expected-error {{universal character name refers to a control character}} +wchar_t w009f = L'\u009f'; // expected-error {{universal character name refers to a control character}} +wchar_t w00a0 = L'\u00a0'; + +wchar_t wd799 = L'\ud799'; +wchar_t wd800 = L'\ud800'; // expected-error {{invalid universal character}} +wchar_t wdfff = L'\udfff'; // expected-error {{invalid universal character}} +wchar_t we000 = L'\ue000'; + +const char *s00 = "\u0000"; // expected-error {{universal character name refers to a control character}} +const char *s01 = "\u0001"; // expected-error {{universal character name refers to a control character}} +const char *s1f = "\u001f"; // expected-error {{universal character name refers to a control character}} +const char *s20 = "\u0020"; // ' ', expected-error {{character ' ' cannot be specified by a universal character name}} +const char *s22 = "\u0022"; // ", expected-error {{character '"' cannot be specified by a universal character name}} +const char *s23 = "\u0023"; // #, expected-error {{character '#' cannot be specified by a universal character name}} +const char *s24 = "\u0024"; // $, ok +const char *s25 = "\u0025"; // %, expected-error {{character '%' cannot be specified by a universal character name}} +const char *s27 = "\u0027"; // ', expected-error {{character ''' cannot be specified by a universal character name}} +const char *s3f = "\u003f"; // ?, expected-error {{character '?' cannot be specified by a universal character name}} +const char *s40 = "\u0040"; // @, ok +const char *s41 = "\u0041"; // A, expected-error {{character 'A' cannot be specified by a universal character name}} +const char *s5f = "\u005f"; // _, expected-error {{character '_' cannot be specified by a universal character name}} +const char *s60 = "\u0060"; // `, ok +const char *s7e = "\u007e"; // ~, expected-error {{character '~' cannot be specified by a universal character name}} +const char *s7f = "\u007f"; // expected-error {{universal character name refers to a control character}} + +const wchar_t *ws007f = L"\u007f"; // expected-error {{universal character name refers to a control character}} +const wchar_t *ws0080 = L"\u0080"; // expected-error {{universal character name refers to a control character}} +const wchar_t *ws009f = L"\u009f"; // expected-error {{universal character name refers to a control character}} +const wchar_t *ws00a0 = L"\u00a0"; + +const wchar_t *wsd799 = L"\ud799"; +const wchar_t *wsd800 = L"\ud800"; // expected-error {{invalid universal character}} +const wchar_t *wsdfff = L"\udfff"; // expected-error {{invalid universal character}} +const wchar_t *wse000 = L"\ue000"; diff --git a/clang/test/CXX/lex/lex.literal/lex.ccon/p1.cpp b/clang/test/CXX/lex/lex.literal/lex.ccon/p1.cpp new file mode 100644 index 0000000..5342153 --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ccon/p1.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Check types of char literals +extern char a; +extern __typeof('a') a; +extern int b; +extern __typeof('asdf') b; +extern wchar_t c; +extern __typeof(L'a') c; +#if __cplusplus >= 201103L +extern char16_t d; +extern __typeof(u'a') d; +extern char32_t e; +extern __typeof(U'a') e; +#endif diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp new file mode 100644 index 0000000..1c227a1 --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +void operator "" p31(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} +void operator "" _p31(long double); +long double operator "" pi(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} + +float hexfloat = 0x1p31; // allow hexfloats diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp new file mode 100644 index 0000000..1b5d388 --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +using size_t = decltype(sizeof(int)); +void operator "" wibble(const char *); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}} +void operator "" wibble(const char *, size_t); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}} + +template<typename T> +void f() { + // A program containing a reserved ud-suffix is ill-formed. + 123wibble; // expected-error {{invalid suffix 'wibble'}} + 123.0wibble; // expected-error {{invalid suffix 'wibble'}} + const char *p = ""wibble; // expected-error {{invalid suffix on literal; C++11 requires a space between literal and identifier}} expected-error {{expected ';'}} + const char *q = R"x("hello")x"wibble; // expected-error {{invalid suffix on literal; C++11 requires a space between literal and identifier}} expected-error {{expected ';'}} +} diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p2.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p2.cpp new file mode 100644 index 0000000..3f3f796 --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p2.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +typedef decltype(sizeof(int)) size_t; + +// FIXME: These diagnostics should say 'size_t' instead of 'unsigned long' +int a = 123_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'unsigned long long' or 'const char *', and no matching literal operator template}} +int b = 4.2_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'long double' or 'const char *', and no matching literal operator template}} +int c = "foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const char *' and 'unsigned}} +int d = L"foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const wchar_t *' and 'unsigned}} +int e = u8"foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const char *' and 'unsigned}} +int f = u"foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const char16_t *' and 'unsigned}} +int g = U"foo"_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with arguments of types 'const char32_t *' and 'unsigned}} +int h = 'y'_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'char'}} +int i = L'y'_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'wchar_t'}} +int j = u'y'_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'char16_t'}} +int k = U'y'_x; // expected-error {{no matching literal operator for call to 'operator "" _x' with argument of type 'char32_t'}} diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p3.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p3.cpp new file mode 100644 index 0000000..43f3468 --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p3.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +int &operator "" _x1 (unsigned long long); +int &i1 = 0x123_x1; + +double &operator "" _x1 (const char *); +int &i2 = 45_x1; + +template<char...> char &operator "" _x1 (); +int &i3 = 0377_x1; + +int &i4 = 90000000000000000000000000000000000000000000000_x1; // expected-warning {{integer constant is too large}} + +double &operator "" _x2 (const char *); +double &i5 = 123123123123123123123123123123123123123123123_x2; + +template<char...Cs> constexpr int operator "" _x3() { return sizeof...(Cs); } +static_assert(123456789012345678901234567890123456789012345678901234567890_x3 == 60, ""); diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p4.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p4.cpp new file mode 100644 index 0000000..011e832 --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p4.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +int &operator "" _x1 (long double); +int &i1 = 0.123_x1; + +double &operator "" _x1 (const char *); +int &i2 = 45._x1; + +template<char...> char &operator "" _x1 (); +int &i3 = 0377e-1_x1; + +int &i4 = 1e1000000_x1; // expected-warning {{too large for type 'long double'}} + +double &operator "" _x2 (const char *); +double &i5 = 1e1000000_x2; + +template<char...Cs> constexpr int operator "" _x3() { return sizeof...(Cs); } +static_assert(1e1000000_x3 == 9, ""); diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p5.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p5.cpp new file mode 100644 index 0000000..4655aa1 --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p5.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +using size_t = decltype(sizeof(int)); + +int &operator "" _x1 (const char *); +double &operator "" _x1 (const char *, size_t); +double &i1 = "foo"_x1; +double &i2 = u8"foo"_x1; +double &i3 = L"foo"_x1; // expected-error {{no matching literal operator}} + +char &operator "" _x1(const wchar_t *, size_t); +char &i4 = L"foo"_x1; // ok +double &i5 = R"(foo)"_x1; // ok diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p6.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p6.cpp new file mode 100644 index 0000000..23cd708 --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p6.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +using size_t = decltype(sizeof(int)); + +int &operator "" _x1 (const char *); +double &i1 = 'a'_x1; // expected-error {{no matching literal operator}} +double &operator "" _x1 (wchar_t); +double &i2 = L'a'_x1; +double &i3 = 'a'_x1; // expected-error {{no matching literal operator}} +double &i4 = operator"" _x1('a'); // ok + +char &operator "" _x1(char16_t); +char &i5 = u'a'_x1; // ok +double &i6 = L'a'_x1; // ok diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p7.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p7.cpp new file mode 100644 index 0000000..79c9394 --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p7.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +using size_t = decltype(sizeof(int)); +namespace std { + struct string {}; +} + +template<typename T, typename U> struct same_type; +template<typename T> struct same_type<T, T> {}; + +namespace std_example { + +long double operator "" _w(long double); +std::string operator "" _w(const char16_t*, size_t); +unsigned operator "" _w(const char*); +int main() { + auto v1 = 1.2_w; // calls operator "" _w(1.2L) + auto v2 = u"one"_w; // calls operator "" _w(u"one", 3) + auto v3 = 12_w; // calls operator "" _w("12") + "two"_w; // expected-error {{no matching literal operator}} + + same_type<decltype(v1), long double> test1; + same_type<decltype(v2), std::string> test2; + same_type<decltype(v3), unsigned> test3; +} + +} diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p8.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p8.cpp new file mode 100644 index 0000000..d907822 --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p8.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +using size_t = decltype(sizeof(int)); +constexpr const char *operator "" _id(const char *p, size_t) { return p; } +constexpr const char *s = "foo"_id "bar" "baz"_id "quux"; + +constexpr bool streq(const char *p, const char *q) { + return *p == *q && (!*p || streq(p+1, q+1)); +} +static_assert(streq(s, "foobarbazquux"), ""); + +constexpr const char *operator "" _trim(const char *p, size_t n) { + return *p == ' ' ? operator "" _trim(p + 1, n - 1) : p; +} +constexpr const char *t = " " " "_trim " foo"; +static_assert(streq(t, "foo"), ""); + +const char *u = "foo" "bar"_id "baz" "quux"_di "corge"; // expected-error {{differing user-defined suffixes ('_id' and '_di') in string literal concatenation}} diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p9.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p9.cpp new file mode 100644 index 0000000..65e27b4 --- /dev/null +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p9.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +using size_t = decltype(sizeof(int)); +void operator "" _x(const wchar_t *, size_t); + +namespace std_example { + +int main() { + L"A" "B" "C"_x; + "P"_x "Q" "R"_y; // expected-error {{differing user-defined suffixes ('_x' and '_y') in string literal concatenation}} +} + +} diff --git a/clang/test/CXX/lex/lex.pptoken/p3-0x.cpp b/clang/test/CXX/lex/lex.pptoken/p3-0x.cpp new file mode 100644 index 0000000..3d56ac1 --- /dev/null +++ b/clang/test/CXX/lex/lex.pptoken/p3-0x.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +int a<::> = { 1, 2, 3 }; +int b = a<:::a<:0:>:>; +bool c = a<:0:><::b; + +template<int &n> void f() {} +template void f<::b>(); + +#define x a<:: ## : b :> +int d = x; // expected-error {{pasting formed ':::', an invalid preprocessing token}} expected-error {{expected unqualified-id}} diff --git a/clang/test/CXX/lex/lex.trigraph/p1.cpp b/clang/test/CXX/lex/lex.trigraph/p1.cpp new file mode 100644 index 0000000..aacbc55 --- /dev/null +++ b/clang/test/CXX/lex/lex.trigraph/p1.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -trigraphs -Wtrigraphs -verify %s + +??=pragma // expected-warning {{trigraph converted to '#' character}} + +int a = '??/0'; // expected-warning {{trigraph converted to '\' character}} + +int b = 1 ??' 0; // expected-warning {{trigraph converted to '^' character}} + +int c ??(1]; // expected-warning {{trigraph converted to '[' character}} + +int d [1??); // expected-warning {{trigraph converted to ']' character}} + +int e = 1 ??! 0; // expected-warning {{trigraph converted to '|' character}} + +void f() ??<} // expected-warning {{trigraph converted to '{' character}} + +void g() {??> // expected-warning {{trigraph converted to '}' character}} + +int h = ??- 0; // expected-warning {{trigraph converted to '~' character}} diff --git a/clang/test/CXX/lex/lex.trigraph/p2.cpp b/clang/test/CXX/lex/lex.trigraph/p2.cpp new file mode 100644 index 0000000..7d11d5b --- /dev/null +++ b/clang/test/CXX/lex/lex.trigraph/p2.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -fsyntax-only -trigraphs -Wtrigraphs -verify %s + +??=define arraycheck(a,b) a??(b??) ??!??! b??(a??) // expected-warning {{trigraph converted to '#' character}} expected-warning {{trigraph converted to '[' character}} expected-warning {{trigraph converted to ']' character}} expected-warning {{trigraph converted to '|' character}} expected-warning {{trigraph converted to '|' character}} expected-warning {{trigraph converted to '[' character}} expected-warning {{trigraph converted to ']' character}} diff --git a/clang/test/CXX/lex/lex.trigraph/p3.cpp b/clang/test/CXX/lex/lex.trigraph/p3.cpp new file mode 100644 index 0000000..2be0328 --- /dev/null +++ b/clang/test/CXX/lex/lex.trigraph/p3.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -trigraphs -Wtrigraphs -verify %s + +char a[] = +"?? ??\"??#??$??%??&??*??+??,??.??0??1??2??3??4??5??6" +"??7??8??9??:??;?????@??A??B??C??D??E??F??G??H??I??J" +"??K??L??M??N??O??P??Q??R??S??T??U??V??W??X??Y??Z??[" +"??\\??]??^??_??`??a??b??c??d??e??f??g??h??i??j??k??l" +"??m??n??o??p??q??r??s??t??u??v??w??x??y??z??{??|??}??~"; diff --git a/clang/test/CXX/over/over.built/p1.cpp b/clang/test/CXX/over/over.built/p1.cpp new file mode 100644 index 0000000..6000f5b --- /dev/null +++ b/clang/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/clang/test/CXX/over/over.built/p23.cpp b/clang/test/CXX/over/over.built/p23.cpp new file mode 100644 index 0000000..4125521 --- /dev/null +++ b/clang/test/CXX/over/over.built/p23.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +struct Variant { + template <typename T> operator T(); +}; + +Variant getValue(); + +void testVariant() { + bool ret1 = getValue() || getValue(); + bool ret2 = getValue() && getValue(); + bool ret3 = !getValue(); +} + +struct ExplicitVariant { + template <typename T> explicit operator T(); +}; + +ExplicitVariant getExplicitValue(); + +void testExplicitVariant() { + bool ret1 = getExplicitValue() || getExplicitValue(); + bool ret2 = getExplicitValue() && getExplicitValue(); + bool ret3 = !getExplicitValue(); +} diff --git a/clang/test/CXX/over/over.built/p25.cpp b/clang/test/CXX/over/over.built/p25.cpp new file mode 100644 index 0000000..aea3854 --- /dev/null +++ b/clang/test/CXX/over/over.built/p25.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %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/clang/test/CXX/over/over.load/p2-0x.cpp b/clang/test/CXX/over/over.load/p2-0x.cpp new file mode 100644 index 0000000..cf38741 --- /dev/null +++ b/clang/test/CXX/over/over.load/p2-0x.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.list/p6.cpp b/clang/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.list/p6.cpp new file mode 100644 index 0000000..ea059ce --- /dev/null +++ b/clang/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.list/p6.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// rdar://problem/11120365 +namespace test0 { + template <class T> struct A { + static void foo(const T &t) {} + static void foo(T &&t) { + t.foo(); // expected-error {{member reference base type 'int' is not a structure or union}} + } + }; + + void test() { + A<int>::foo({}); // expected-note {{requested here}} + } +} diff --git a/clang/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.user/p3-0x.cpp b/clang/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.user/p3-0x.cpp new file mode 100644 index 0000000..1c71468 --- /dev/null +++ b/clang/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.user/p3-0x.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +namespace PR6285 { + template<typename T> struct identity + { typedef T type; }; + + struct D { + template<typename T = short> + operator typename identity<T>::type(); // expected-note{{candidate}} + }; + + int f() { return D(); } // expected-error{{no viable conversion}} +} + diff --git a/clang/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp b/clang/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp new file mode 100644 index 0000000..3971acc --- /dev/null +++ b/clang/test/CXX/over/over.match/over.match.best/over.ics.rank/p3-0x.cpp @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/over/over.match/over.match.best/p1.cpp b/clang/test/CXX/over/over.match/over.match.best/p1.cpp new file mode 100644 index 0000000..5c315a7 --- /dev/null +++ b/clang/test/CXX/over/over.match/over.match.best/p1.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> int &f0(T*, int); +float &f0(void*, int); + +void test_f0(int* ip, void *vp) { + // One argument is better... + int &ir = f0(ip, 0); + + // Prefer non-templates to templates + float &fr = f0(vp, 0); +} + +// Partial ordering of function template specializations will be tested +// elsewhere +// FIXME: Initialization by user-defined conversion is tested elsewhere diff --git a/clang/test/CXX/over/over.match/over.match.funcs/over.match.copy/p1.cpp b/clang/test/CXX/over/over.match/over.match.funcs/over.match.copy/p1.cpp new file mode 100644 index 0000000..31a679f --- /dev/null +++ b/clang/test/CXX/over/over.match/over.match.funcs/over.match.copy/p1.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s -verify + +namespace ExplicitConv { + struct X { }; // expected-note 2{{candidate constructor}} + + struct Y { + explicit operator X() const; + }; + + void test(const Y& y) { + X x(static_cast<X>(y)); + X x2((X)y); + X x3 = y; // expected-error{{no viable conversion from 'const ExplicitConv::Y' to 'ExplicitConv::X'}} + } +} + +namespace DR899 { + struct C { }; // expected-note 2 {{candidate constructor}} + + struct A { + explicit operator int() const; + explicit operator C() const; + }; + + struct B { + int i; + B(const A& a): i(a) { } + }; + + int main() { + A a; + int i = a; // expected-error{{no viable conversion}} + int j(a); + C c = a; // expected-error{{no viable conversion}} + C c2(a); + } +} diff --git a/clang/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp b/clang/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp new file mode 100644 index 0000000..3845af0 --- /dev/null +++ b/clang/test/CXX/over/over.match/over.match.funcs/p4-0x.cpp @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/over/over.oper/over.literal/p2.cpp b/clang/test/CXX/over/over.oper/over.literal/p2.cpp new file mode 100644 index 0000000..c012104 --- /dev/null +++ b/clang/test/CXX/over/over.oper/over.literal/p2.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +void operator "" _a(const char *); + +namespace N { + using ::operator "" _a; + + void operator "" _b(const char *); +} + +using N::operator "" _b; + +class C { + void operator "" _c(const char *); // expected-error {{must be in a namespace or global scope}} + + static void operator "" _c(unsigned long long); // expected-error {{must be in a namespace or global scope}} + + friend void operator "" _d(const char *); +}; + +int operator "" _e; // expected-error {{cannot be the name of a variable}} + +void f() { + int operator "" _f; // expected-error {{cannot be the name of a variable}} +} + +extern "C++" { + void operator "" _g(const char *); +} + +template<char...> void operator "" _h() {} + +template<> void operator "" _h<'a', 'b', 'c'>() {} + +template void operator "" _h<'a', 'b', 'c', 'd'>(); diff --git a/clang/test/CXX/over/over.oper/over.literal/p3.cpp b/clang/test/CXX/over/over.oper/over.literal/p3.cpp new file mode 100644 index 0000000..674ace9 --- /dev/null +++ b/clang/test/CXX/over/over.oper/over.literal/p3.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +using size_t = decltype(sizeof(int)); + +// Acceptable parameter declarations +char operator "" _a(const char *); +char operator "" _a(const char []); +char operator "" _a(unsigned long long); +char operator "" _a(long double); +char operator "" _a(char); +char operator "" _a(const volatile char); +char operator "" _a(wchar_t); +char operator "" _a(char16_t); +char operator "" _a(char32_t); +char operator "" _a(const char *, size_t); +char operator "" _a(const wchar_t *, size_t); +char operator "" _a(const char16_t *, size_t); +char operator "" _a(const char32_t *, size_t); +char operator "" _a(const char [32], size_t); + +// Unacceptable parameter declarations +char operator "" _b(); // expected-error {{parameter}} +char operator "" _b(const wchar_t *); // expected-error {{parameter}} +char operator "" _b(long long); // expected-error {{parameter}} +char operator "" _b(double); // expected-error {{parameter}} +char operator "" _b(short); // expected-error {{parameter}} +char operator "" _a(char, int = 0); // expected-error {{parameter}} +char operator "" _b(unsigned short); // expected-error {{parameter}} +char operator "" _b(signed char); // expected-error {{parameter}} +char operator "" _b(unsigned char); // expected-error {{parameter}} +char operator "" _b(const short *, size_t); // expected-error {{parameter}} +char operator "" _b(const unsigned short *, size_t); // expected-error {{parameter}} +char operator "" _b(const signed char *, size_t); // expected-error {{parameter}} +char operator "" _b(const unsigned char *, size_t); // expected-error {{parameter}} +char operator "" _a(const volatile char *, size_t); // expected-error {{parameter}} +char operator "" _a(volatile wchar_t *, size_t); // expected-error {{parameter}} +char operator "" _a(char16_t *, size_t); // expected-error {{parameter}} +char operator "" _a(const char32_t *, size_t, bool = false); // expected-error {{parameter}} +char operator "" _a(const char *, signed long); // expected-error {{parameter}} +char operator "" _a(const char *, size_t = 0); // expected-error {{default argument}} diff --git a/clang/test/CXX/over/over.oper/over.literal/p5.cpp b/clang/test/CXX/over/over.oper/over.literal/p5.cpp new file mode 100644 index 0000000..66f3f97 --- /dev/null +++ b/clang/test/CXX/over/over.oper/over.literal/p5.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +using size_t = decltype(sizeof(int)); +template<char...> struct S {}; + +template<char...> void operator "" _a(); +template<char... C> S<C...> operator "" _a(); + +template<typename T> struct U { + friend int operator "" _a(const char *, size_t); + // FIXME: It's not entirely clear whether this is intended to be legal. + friend U operator "" _a(const T *, size_t); // expected-error {{parameter}} +}; +template<char...> struct V { + friend void operator "" _b(); // expected-error {{parameter}} +}; + +template<char... C, int N = 0> void operator "" _b(); // expected-error {{parameter}} +template<char... C> void operator "" _b(int N = 0); // expected-error {{parameter}} +template<char, char...> void operator "" _b(); // expected-error {{parameter}} +template<typename T> T operator "" _b(const char *); // expected-error {{parameter}} +template<typename T> int operator "" _b(const T *, size_t); // expected-error {{parameter}} diff --git a/clang/test/CXX/over/over.oper/over.literal/p6.cpp b/clang/test/CXX/over/over.oper/over.literal/p6.cpp new file mode 100644 index 0000000..6bfb856 --- /dev/null +++ b/clang/test/CXX/over/over.oper/over.literal/p6.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +extern "C" void operator "" _a(const char *); // expected-error {{must have C++ linkage}} +extern "C" template<char...> void operator "" _b(); // expected-error {{must have C++ linkage}} + +extern "C" { + void operator "" _c(const char *); // expected-error {{must have C++ linkage}} + template<char...> void operator "" _d(); // expected-error {{must have C++ linkage}} + namespace N { + void operator "" _e(const char *); // expected-error {{must have C++ linkage}} + template<char...> void operator "" _f(); // expected-error {{must have C++ linkage}} + } +} diff --git a/clang/test/CXX/over/over.oper/over.literal/p7.cpp b/clang/test/CXX/over/over.oper/over.literal/p7.cpp new file mode 100644 index 0000000..72411b9 --- /dev/null +++ b/clang/test/CXX/over/over.oper/over.literal/p7.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +constexpr int operator "" _a(const char *c) { + return c[0]; +} + +static_assert(operator "" _a("foo") == 'f', ""); + +void puts(const char *); +static inline void operator "" _puts(const char *c) { + puts(c); +} +void f() { + operator "" _puts("foo"); + operator "" _puts("bar"); +} diff --git a/clang/test/CXX/over/over.oper/over.literal/p8.cpp b/clang/test/CXX/over/over.oper/over.literal/p8.cpp new file mode 100644 index 0000000..3f76082 --- /dev/null +++ b/clang/test/CXX/over/over.oper/over.literal/p8.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +struct string; +namespace std { + using size_t = decltype(sizeof(int)); +} + +void operator "" _km(long double); // ok +string operator "" _i18n(const char*, std::size_t); // ok +// FIXME: This should be accepted once we support UCNs +template<char...> int operator "" \u03C0(); // ok, UCN for lowercase pi // expected-error {{expected identifier}} +float operator ""E(const char *); // expected-error {{C++11 requires a space between literal and identifier}} expected-warning {{reserved}} +float operator " " B(const char *); // expected-error {{must be '""'}} expected-warning {{reserved}} +string operator "" 5X(const char *, std::size_t); // expected-error {{expected identifier}} +double operator "" _miles(double); // expected-error {{parameter}} +template<char...> int operator "" j(const char*); // expected-error {{parameter}} + +// FIXME: Accept this as an extension, with a fix-it to add the space +float operator ""_E(const char *); // expected-error {{C++11 requires a space between the "" and the user-defined suffix in a literal operator}} diff --git a/clang/test/CXX/over/over.over/p1.cpp b/clang/test/CXX/over/over.over/p1.cpp new file mode 100644 index 0000000..10c60da --- /dev/null +++ b/clang/test/CXX/over/over.over/p1.cpp @@ -0,0 +1,94 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template<typename T> T f0(T); +int f0(int); + +// -- an object or reference being initialized +struct S { + int (*f0)(int); + float (*f1)(float); +}; + +void test_init_f0() { + int (*f0a)(int) = f0; + int (*f0b)(int) = &f0; + int (*f0c)(int) = (f0); + float (*f0d)(float) = f0; + float (*f0e)(float) = &f0; + float (*f0f)(float) = (f0); + int (&f0g)(int) = f0; + int (&f0h)(int) = (f0); + float (&f0i)(float) = f0; + float (&f0j)(float) = (f0); + S s = { f0, f0 }; +} + +// -- the left side of an assignment (5.17), +void test_assign_f0() { + int (*f0a)(int) = 0; + float (*f0b)(float) = 0; + + f0a = f0; + f0a = &f0; + f0a = (f0); + f0b = f0; + f0b = &f0; + f0b = (f0); +} + +// -- a parameter of a function (5.2.2), +void eat_f0(int a(int), float (*b)(float), int (&c)(int), float (&d)(float)); + +void test_pass_f0() { + eat_f0(f0, f0, f0, f0); + eat_f0(&f0, &f0, (f0), (f0)); +} + +// -- a parameter of a user-defined operator (13.5), +struct X { }; +void operator+(X, int(int)); +void operator-(X, float(*)(float)); +void operator*(X, int (&)(int)); +void operator/(X, float (&)(float)); + +void test_operator_pass_f0(X x) { + x + f0; + x + &f0; + x - f0; + x - &f0; + x * f0; + x * (f0); + x / f0; + x / (f0); +} + +// -- the return value of a function, operator function, or conversion (6.6.3), +int (*test_return_f0_a())(int) { return f0; } +int (*test_return_f0_b())(int) { return &f0; } +int (*test_return_f0_c())(int) { return (f0); } +float (*test_return_f0_d())(float) { return f0; } +float (*test_return_f0_e())(float) { return &f0; } +float (*test_return_f0_f())(float) { return (f0); } + +// -- an explicit type conversion (5.2.3, 5.2.9, 5.4), or +void test_convert_f0() { + (void)((int (*)(int))f0); + (void)((int (*)(int))&f0); + (void)((int (*)(int))(f0)); + (void)((float (*)(float))f0); + (void)((float (*)(float))&f0); + (void)((float (*)(float))(f0)); +} + +// -- a non-type template-parameter(14.3.2). +template<int(int)> struct Y0 { }; +template<float(float)> struct Y1 { }; +template<int (&)(int)> struct Y2 { }; +template<float (&)(float)> struct Y3 { }; + +Y0<f0> y0; +Y0<&f0> y0a; +Y1<f0> y1; +Y1<&f0> y1a; +Y2<f0> y2; +Y3<f0> y3; diff --git a/clang/test/CXX/over/over.over/p2-resolve-single-template-id.cpp b/clang/test/CXX/over/over.over/p2-resolve-single-template-id.cpp new file mode 100644 index 0000000..e021711 --- /dev/null +++ b/clang/test/CXX/over/over.over/p2-resolve-single-template-id.cpp @@ -0,0 +1,191 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-bool-conversion %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 + +namespace DontAllowUnresolvedOverloadedExpressionInAnUnusedExpression +{ + void one() { } + template<class T> void oneT() { } + + void two() { } // expected-note 2 {{possible target for call}} + void two(int) { } // expected-note 2 {{possible target for call}} + template<class T> void twoT() { } // expected-note 2 {{possible target for call}} + template<class T> void twoT(T) { } // expected-note 2 {{possible target for call}} + + void check() + { + one; // expected-warning {{expression result unused}} + two; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} + oneT<int>; // expected-warning {{expression result unused}} + twoT<int>; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} + } + + // check the template function case + template<class T> void check() + { + one; // expected-warning {{expression result unused}} + two; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} + oneT<int>; // expected-warning {{expression result unused}} + twoT<int>; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} + + } + +} + + 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 function 'two' cannot be static_cast to type 'void'}} + { (void)(two); } // expected-error {{address of overloaded function 'two' cannot be cast to type 'void'}} + { 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>); } + { bool b = (twoT<int, int>); } + + { 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}} + +} + +namespace member_pointers { + struct S { + template <typename T> bool f(T) { return false; } + template <typename T> static bool g(T) { return false; } + + template <typename T> bool h(T) { return false; } // expected-note 3 {{possible target for call}} + template <int N> static bool h(int) { return false; } // expected-note 3 {{possible target for call}} + }; + + void test(S s) { + if (S::f<char>) return; // expected-error {{call to non-static member function without an object argument}} + if (S::f<int>) return; // expected-error {{call to non-static member function without an object argument}} + if (&S::f<char>) return; + if (&S::f<int>) return; + if (s.f<char>) return; // expected-error {{reference to non-static member function must be called}} + if (s.f<int>) return; // expected-error {{reference to non-static member function must be called}} + if (&s.f<char>) return; // expected-error {{cannot create a non-constant pointer to member function}} + if (&s.f<int>) return; // expected-error {{cannot create a non-constant pointer to member function}} + + if (S::g<char>) return; + if (S::g<int>) return; + if (&S::g<char>) return; + if (&S::g<int>) return; + if (s.g<char>) return; + if (s.g<int>) return; + if (&s.g<char>) return; + if (&s.g<int>) return; + + if (S::h<42>) return; + if (S::h<int>) return; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} + if (&S::h<42>) return; + if (&S::h<int>) return; + if (s.h<42>) return; + if (s.h<int>) return; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} + if (&s.h<42>) return; + if (&s.h<int>) return; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} + + { bool b = S::f<char>; } // expected-error {{call to non-static member function without an object argument}} + { bool b = S::f<int>; } // expected-error {{call to non-static member function without an object argument}} + { bool b = &S::f<char>; } + { bool b = &S::f<int>; } + // These next two errors are terrible. + { bool b = s.f<char>; } // expected-error {{reference to non-static member function must be called}} + { bool b = s.f<int>; } // expected-error {{reference to non-static member function must be called}} + { bool b = &s.f<char>; } // expected-error {{cannot create a non-constant pointer to member function}} + { bool b = &s.f<int>; } // expected-error {{cannot create a non-constant pointer to member function}} + + { bool b = S::g<char>; } + { bool b = S::g<int>; } + { bool b = &S::g<char>; } + { bool b = &S::g<int>; } + { bool b = s.g<char>; } + { bool b = s.g<int>; } + { bool b = &s.g<char>; } + { bool b = &s.g<int>; } + + { bool b = S::h<42>; } + { bool b = S::h<int>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}} + { bool b = &S::h<42>; } + { bool b = &S::h<int>; } + { bool b = s.h<42>; } + { bool b = s.h<int>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}} + { bool b = &s.h<42>; } + { bool b = &s.h<int>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}} + } +} diff --git a/clang/test/CXX/over/over.over/p2.cpp b/clang/test/CXX/over/over.over/p2.cpp new file mode 100644 index 0000000..3e8d0f1 --- /dev/null +++ b/clang/test/CXX/over/over.over/p2.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +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{{address of overloaded function 'f0' does not match required type 'int (int, float)'}} +} diff --git a/clang/test/CXX/over/over.over/p4.cpp b/clang/test/CXX/over/over.over/p4.cpp new file mode 100644 index 0000000..27d070e --- /dev/null +++ b/clang/test/CXX/over/over.over/p4.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> T f0(T); // expected-note{{candidate function}} +int f0(int); // expected-note{{candidate function}} + +void test_f0() { + int (*fp0)(int) = f0; + int (*fp1)(int) = &f0; + float (*fp2)(float) = &f0; +} + +namespace N { + int f0(int); // expected-note{{candidate function}} +} + +void test_f0_2() { + using namespace N; + int (*fp0)(int) = f0; // expected-error{{address of overloaded function 'f0' is ambiguous}} + float (*fp1)(float) = f0; +} diff --git a/clang/test/CXX/special/class.copy/implicit-move-def.cpp b/clang/test/CXX/special/class.copy/implicit-move-def.cpp new file mode 100644 index 0000000..5c54aea --- /dev/null +++ b/clang/test/CXX/special/class.copy/implicit-move-def.cpp @@ -0,0 +1,117 @@ +// RUN: %clang_cc1 -emit-llvm -o - -std=c++11 %s | FileCheck -check-prefix=CHECK-ASSIGN %s +// RUN: %clang_cc1 -emit-llvm -o - -std=c++11 %s | FileCheck -check-prefix=CHECK-ASSIGN %s +// RUN: %clang_cc1 -emit-llvm -o - -std=c++11 %s | FileCheck -check-prefix=CHECK-CTOR %s + +// construct + +struct E { + E(); + E(E&&); +}; + +struct F { + F(); + F(F&&); +}; + +struct G { + E e; +}; + +struct H : G { + F l; + E m; + F ar[2]; +}; + +void f() { + H s; + // CHECK: call void @_ZN1HC1EOS_ + H t(static_cast<H&&>(s)); +} + + +// assign + +struct A { + A &operator =(A&&); +}; + +struct B { + B &operator =(B&&); +}; + +struct C { + A a; +}; + +struct D : C { + A a; + B b; + A ar[2]; +}; + +void g() { + D d; + // CHECK: call {{.*}} @_ZN1DaSEOS_ + d = D(); +} + +// PR10822 +struct I { + unsigned var[1]; +}; + +// CHECK: define void @_Z1hv() nounwind { +void h() { + I i; + // CHECK: call void @llvm.memcpy. + i = I(); + // CHECK-NEXT: ret void +} + +// PR10860 +struct Empty { }; +struct VirtualWithEmptyBase : Empty { + virtual void f(); +}; + +// CHECK: define void @_Z25move_VirtualWithEmptyBaseR20VirtualWithEmptyBaseS0_ +void move_VirtualWithEmptyBase(VirtualWithEmptyBase &x, VirtualWithEmptyBase &y) { + // CHECK: call {{.*}} @_ZN20VirtualWithEmptyBaseaSEOS_ + x = static_cast<VirtualWithEmptyBase&&>(y); + // CHECK-NEXT: ret void +} + +// move assignment ops + +// CHECK-ASSIGN: define linkonce_odr {{.*}} @_ZN1DaSEOS_ +// CHECK-ASSIGN: call {{.*}} @_ZN1CaSEOS_ +// CHECK-ASSIGN: call {{.*}} @_ZN1AaSEOS_ +// CHECK-ASSIGN: call {{.*}} @_ZN1BaSEOS_ +// array loop +// CHECK-ASSIGN: br i1 +// CHECK-ASSIGN: call {{.*}} @_ZN1AaSEOS_ + +// VirtualWithEmptyBase move assignment operatpr +// CHECK-ASSIGN: define linkonce_odr {{.*}} @_ZN20VirtualWithEmptyBaseaSEOS_ +// CHECK-ASSIGN: store +// CHECK-ASSIGN-NEXT: store +// CHECK-ASSIGN-NOT: call +// CHECK-ASSIGN: ret + +// CHECK-ASSIGN: define linkonce_odr {{.*}} @_ZN1CaSEOS_ +// CHECK-ASSIGN: call {{.*}} @_ZN1AaSEOS_ + +// move ctors + +// CHECK-CTOR: define linkonce_odr {{.*}} @_ZN1HC2EOS_ +// CHECK-CTOR: call {{.*}} @_ZN1GC2EOS_ +// CHECK-CTOR: call {{.*}} @_ZN1FC1EOS_ +// CHECK-CTOR: call {{.*}} @_ZN1EC1EOS_ +// array loop +// CHECK-CTOR: br i1 +// CHECK-CTOR: call {{.*}} @_ZN1FC1EOS_ + +// CHECK-CTOR: define linkonce_odr {{.*}} @_ZN1GC2EOS_ +// CHECK-CTOR: call {{.*}} @_ZN1EC1EOS_ diff --git a/clang/test/CXX/special/class.copy/implicit-move.cpp b/clang/test/CXX/special/class.copy/implicit-move.cpp new file mode 100644 index 0000000..3e9accf --- /dev/null +++ b/clang/test/CXX/special/class.copy/implicit-move.cpp @@ -0,0 +1,236 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// Tests for implicit (non-)declaration of move constructor and +// assignment: p9, p11, p20, p23. + +// This class, used as a member, allows to distinguish move from copy because +// move operations are no-throw, copy operations aren't. +struct ThrowingCopy { + ThrowingCopy() noexcept; + ThrowingCopy(ThrowingCopy &&) noexcept; + ThrowingCopy(const ThrowingCopy &) noexcept(false); + ThrowingCopy & operator =(ThrowingCopy &&) noexcept; + ThrowingCopy & operator =(const ThrowingCopy &) noexcept(false); +}; + +struct HasCopyConstructor { + ThrowingCopy tc; + HasCopyConstructor() noexcept; + HasCopyConstructor(const HasCopyConstructor &) noexcept(false); +}; + +struct HasCopyAssignment { + ThrowingCopy tc; + HasCopyAssignment() noexcept; + HasCopyAssignment & operator =(const HasCopyAssignment &) noexcept(false); +}; + +struct HasMoveConstructor { + ThrowingCopy tc; + HasMoveConstructor() noexcept; + HasMoveConstructor(HasMoveConstructor &&) noexcept; // expected-note {{copy assignment operator is implicitly deleted because 'HasMoveConstructor' has a user-declared move constructor}} +}; + +struct HasMoveAssignment { // expected-note {{implicit copy constructor}} + ThrowingCopy tc; + HasMoveAssignment() noexcept; + HasMoveAssignment & operator =(HasMoveAssignment &&) noexcept; +}; + +struct HasDestructor { + ThrowingCopy tc; + HasDestructor() noexcept; + ~HasDestructor() noexcept; +}; + +void test_basic_exclusion() { + static_assert(!noexcept(HasCopyConstructor((HasCopyConstructor()))), ""); + HasCopyConstructor hcc; + static_assert(!noexcept(hcc = HasCopyConstructor()), ""); + + static_assert(!noexcept(HasCopyAssignment((HasCopyAssignment()))), ""); + HasCopyAssignment hca; + static_assert(!noexcept(hca = HasCopyAssignment()), ""); + + static_assert(noexcept(HasMoveConstructor((HasMoveConstructor()))), ""); + HasMoveConstructor hmc; + hmc = HasMoveConstructor(); // expected-error {{selected implicitly-deleted copy assignment}} + + (HasMoveAssignment(HasMoveAssignment())); // expected-error {{uses deleted function}} + HasMoveAssignment hma; + static_assert(noexcept(hma = HasMoveAssignment()), ""); + + static_assert(!noexcept(HasDestructor((HasDestructor()))), ""); + HasDestructor hd; + static_assert(!noexcept(hd = HasDestructor()), ""); +} + +struct PrivateMove { + PrivateMove() noexcept; + PrivateMove(const PrivateMove &) noexcept(false); + PrivateMove & operator =(const PrivateMove &) noexcept(false); +private: + PrivateMove(PrivateMove &&) noexcept; + PrivateMove & operator =(PrivateMove &&) noexcept; +}; + +struct InheritsPrivateMove : PrivateMove {}; +struct ContainsPrivateMove { + PrivateMove pm; +}; + +struct PrivateDestructor { + PrivateDestructor() noexcept; + PrivateDestructor(const PrivateDestructor &) noexcept(false); + PrivateDestructor(PrivateDestructor &&) noexcept; +private: + ~PrivateDestructor() noexcept; +}; + +struct InheritsPrivateDestructor : PrivateDestructor {}; // expected-note{{base class 'PrivateDestructor' has an inaccessible destructor}} +struct ContainsPrivateDestructor { + PrivateDestructor pd; // expected-note{{field 'pd' has an inaccessible destructor}} +}; + +struct NonTrivialCopyOnly { + NonTrivialCopyOnly() noexcept; + NonTrivialCopyOnly(const NonTrivialCopyOnly &) noexcept(false); + NonTrivialCopyOnly & operator =(const NonTrivialCopyOnly &) noexcept(false); +}; + +struct InheritsNonTrivialCopyOnly : NonTrivialCopyOnly {}; +struct ContainsNonTrivialCopyOnly { + NonTrivialCopyOnly ntco; +}; + +struct ContainsConst { + const int i; + ContainsConst() noexcept; + ContainsConst & operator =(ContainsConst &); // expected-note {{not viable}} +}; + +struct ContainsRef { + int &i; + ContainsRef() noexcept; + ContainsRef & operator =(ContainsRef &); // expected-note {{not viable}} +}; + +struct Base { + Base & operator =(Base &); +}; +struct DirectVirtualBase : virtual Base {}; // expected-note {{copy assignment operator) not viable}} +struct IndirectVirtualBase : DirectVirtualBase {}; // expected-note {{copy assignment operator) not viable}} + +void test_deletion_exclusion() { + // FIXME: How to test the union thing? + + static_assert(!noexcept(InheritsPrivateMove(InheritsPrivateMove())), ""); + static_assert(!noexcept(ContainsPrivateMove(ContainsPrivateMove())), ""); + InheritsPrivateMove ipm; + static_assert(!noexcept(ipm = InheritsPrivateMove()), ""); + ContainsPrivateMove cpm; + static_assert(!noexcept(cpm = ContainsPrivateMove()), ""); + + (InheritsPrivateDestructor(InheritsPrivateDestructor())); // expected-error {{call to implicitly-deleted default constructor}} + (ContainsPrivateDestructor(ContainsPrivateDestructor())); // expected-error {{call to implicitly-deleted default constructor}} + + static_assert(!noexcept(InheritsNonTrivialCopyOnly(InheritsNonTrivialCopyOnly())), ""); + static_assert(!noexcept(ContainsNonTrivialCopyOnly(ContainsNonTrivialCopyOnly())), ""); + InheritsNonTrivialCopyOnly intco; + static_assert(!noexcept(intco = InheritsNonTrivialCopyOnly()), ""); + ContainsNonTrivialCopyOnly cntco; + static_assert(!noexcept(cntco = ContainsNonTrivialCopyOnly()), ""); + + ContainsConst cc; + cc = ContainsConst(); // expected-error {{no viable}} + + ContainsRef cr; + cr = ContainsRef(); // expected-error {{no viable}} + + DirectVirtualBase dvb; + dvb = DirectVirtualBase(); // expected-error {{no viable}} + + IndirectVirtualBase ivb; + ivb = IndirectVirtualBase(); // expected-error {{no viable}} +} + +struct ContainsRValueRef { + int&& ri; + ContainsRValueRef() noexcept; +}; + +void test_contains_rref() { + (ContainsRValueRef(ContainsRValueRef())); +} + + +namespace DR1402 { + struct NonTrivialCopyCtor { + NonTrivialCopyCtor(const NonTrivialCopyCtor &); + }; + struct NonTrivialCopyAssign { + NonTrivialCopyAssign &operator=(const NonTrivialCopyAssign &); + }; + + struct NonTrivialCopyCtorVBase : virtual NonTrivialCopyCtor { + NonTrivialCopyCtorVBase(NonTrivialCopyCtorVBase &&); + NonTrivialCopyCtorVBase &operator=(NonTrivialCopyCtorVBase &&) = default; + }; + struct NonTrivialCopyAssignVBase : virtual NonTrivialCopyAssign { + NonTrivialCopyAssignVBase(NonTrivialCopyAssignVBase &&); + NonTrivialCopyAssignVBase &operator=(NonTrivialCopyAssignVBase &&) = default; + }; + + struct NonTrivialMoveAssign { + NonTrivialMoveAssign(NonTrivialMoveAssign&&); + NonTrivialMoveAssign &operator=(NonTrivialMoveAssign &&); + }; + struct NonTrivialMoveAssignVBase : virtual NonTrivialMoveAssign { + NonTrivialMoveAssignVBase(NonTrivialMoveAssignVBase &&); + NonTrivialMoveAssignVBase &operator=(NonTrivialMoveAssignVBase &&) = default; + }; + + // A non-movable, non-trivially-copyable class type as a subobject inhibits + // the declaration of a move operation. + struct NoMove1 { NonTrivialCopyCtor ntcc; }; // expected-note 2{{'const DR1402::NoMove1 &'}} + struct NoMove2 { NonTrivialCopyAssign ntcc; }; // expected-note 2{{'const DR1402::NoMove2 &'}} + struct NoMove3 : NonTrivialCopyCtor {}; // expected-note 2{{'const DR1402::NoMove3 &'}} + struct NoMove4 : NonTrivialCopyAssign {}; // expected-note 2{{'const DR1402::NoMove4 &'}} + struct NoMove5 : virtual NonTrivialCopyCtor {}; // expected-note 2{{'const DR1402::NoMove5 &'}} + struct NoMove6 : virtual NonTrivialCopyAssign {}; // expected-note 2{{'const DR1402::NoMove6 &'}} + struct NoMove7 : NonTrivialCopyCtorVBase {}; // expected-note 2{{'const DR1402::NoMove7 &'}} + struct NoMove8 : NonTrivialCopyAssignVBase {}; // expected-note 2{{'const DR1402::NoMove8 &'}} + + // A non-trivially-move-assignable virtual base class inhibits the declaration + // of a move assignment (which might move-assign the base class multiple + // times). + struct NoMove9 : NonTrivialMoveAssign {}; + struct NoMove10 : virtual NonTrivialMoveAssign {}; // expected-note {{'const DR1402::NoMove10 &'}} + struct NoMove11 : NonTrivialMoveAssignVBase {}; // expected-note {{'const DR1402::NoMove11 &'}} + + struct Test { + friend NoMove1::NoMove1(NoMove1 &&); // expected-error {{no matching function}} + friend NoMove2::NoMove2(NoMove2 &&); // expected-error {{no matching function}} + friend NoMove3::NoMove3(NoMove3 &&); // expected-error {{no matching function}} + friend NoMove4::NoMove4(NoMove4 &&); // expected-error {{no matching function}} + friend NoMove5::NoMove5(NoMove5 &&); // expected-error {{no matching function}} + friend NoMove6::NoMove6(NoMove6 &&); // expected-error {{no matching function}} + friend NoMove7::NoMove7(NoMove7 &&); // expected-error {{no matching function}} + friend NoMove8::NoMove8(NoMove8 &&); // expected-error {{no matching function}} + friend NoMove9::NoMove9(NoMove9 &&); + friend NoMove10::NoMove10(NoMove10 &&); + friend NoMove11::NoMove11(NoMove11 &&); + + friend NoMove1 &NoMove1::operator=(NoMove1 &&); // expected-error {{no matching function}} + friend NoMove2 &NoMove2::operator=(NoMove2 &&); // expected-error {{no matching function}} + friend NoMove3 &NoMove3::operator=(NoMove3 &&); // expected-error {{no matching function}} + friend NoMove4 &NoMove4::operator=(NoMove4 &&); // expected-error {{no matching function}} + friend NoMove5 &NoMove5::operator=(NoMove5 &&); // expected-error {{no matching function}} + friend NoMove6 &NoMove6::operator=(NoMove6 &&); // expected-error {{no matching function}} + friend NoMove7 &NoMove7::operator=(NoMove7 &&); // expected-error {{no matching function}} + friend NoMove8 &NoMove8::operator=(NoMove8 &&); // expected-error {{no matching function}} + friend NoMove9 &NoMove9::operator=(NoMove9 &&); + friend NoMove10 &NoMove10::operator=(NoMove10 &&); // expected-error {{no matching function}} + friend NoMove11 &NoMove11::operator=(NoMove11 &&); // expected-error {{no matching function}} + }; +} diff --git a/clang/test/CXX/special/class.copy/p11.0x.copy.cpp b/clang/test/CXX/special/class.copy/p11.0x.copy.cpp new file mode 100644 index 0000000..b2b4f6a --- /dev/null +++ b/clang/test/CXX/special/class.copy/p11.0x.copy.cpp @@ -0,0 +1,121 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct NonTrivial { + NonTrivial(const NonTrivial&); +}; + +// A defaulted copy constructor for a class X is defined as deleted if X has: + +// -- a variant member with a non-trivial corresponding constructor +union DeletedNTVariant { + NonTrivial NT; // expected-note{{copy constructor of union 'DeletedNTVariant' is implicitly deleted because field 'NT' has a non-trivial copy constructor}} + DeletedNTVariant(); +}; +DeletedNTVariant DVa; +DeletedNTVariant DVb(DVa); // expected-error{{call to implicitly-deleted copy constructor}} + +struct DeletedNTVariant2 { + union { + NonTrivial NT; // expected-note{{copy constructor of union 'DeletedNTVariant2' is implicitly deleted because field 'NT' has a non-trivial copy constructor}} + }; + DeletedNTVariant2(); +}; +DeletedNTVariant2 DV2a; +DeletedNTVariant2 DV2b(DV2a); // expected-error{{call to implicitly-deleted copy constructor}} + +// -- a non-static data member of class type M (or array thereof) that cannot be +// copied because overload resolution results in an ambiguity or a function +// that is deleted or inaccessible +struct NoAccess { + NoAccess() = default; +private: + NoAccess(const NoAccess&); + + friend struct HasAccess; +}; + +struct HasNoAccess { + NoAccess NA; // expected-note{{copy constructor of 'HasNoAccess' is implicitly deleted because field 'NA' has an inaccessible copy constructor}} +}; +HasNoAccess HNAa; +HasNoAccess HNAb(HNAa); // expected-error{{call to implicitly-deleted copy constructor}} + +struct HasAccess { + NoAccess NA; +}; + +HasAccess HAa; +HasAccess HAb(HAa); + +struct NonConst { + NonConst(NonConst&); +}; +struct Ambiguity { + Ambiguity(const Ambiguity&); + Ambiguity(volatile Ambiguity&); +}; + +struct IsAmbiguous { + NonConst NC; + Ambiguity A; // expected-note 2{{copy constructor of 'IsAmbiguous' is implicitly deleted because field 'A' has multiple copy constructors}} + IsAmbiguous(); +}; +IsAmbiguous IAa; +IsAmbiguous IAb(IAa); // expected-error{{call to implicitly-deleted copy constructor}} + +struct Deleted { + IsAmbiguous IA; // expected-note{{copy constructor of 'Deleted' is implicitly deleted because field 'IA' has a deleted copy constructor}} +}; +Deleted Da; +Deleted Db(Da); // expected-error{{call to implicitly-deleted copy constructor}} + +// -- a direct or virtual base class B that cannot be copied because overload +// resolution results in an ambiguity or a function that is deleted or +// inaccessible +struct AmbiguousCopyBase : Ambiguity { // expected-note 2{{copy constructor of 'AmbiguousCopyBase' is implicitly deleted because base class 'Ambiguity' has multiple copy constructors}} + NonConst NC; +}; +extern AmbiguousCopyBase ACBa; +AmbiguousCopyBase ACBb(ACBa); // expected-error {{deleted copy constructor}} + +struct DeletedCopyBase : AmbiguousCopyBase {}; // expected-note {{copy constructor of 'DeletedCopyBase' is implicitly deleted because base class 'AmbiguousCopyBase' has a deleted copy constructor}} +extern DeletedCopyBase DCBa; +DeletedCopyBase DCBb(DCBa); // expected-error {{deleted copy constructor}} + +struct InaccessibleCopyBase : NoAccess {}; // expected-note {{copy constructor of 'InaccessibleCopyBase' is implicitly deleted because base class 'NoAccess' has an inaccessible copy constructor}} +extern InaccessibleCopyBase ICBa; +InaccessibleCopyBase ICBb(ICBa); // expected-error {{deleted copy constructor}} + +// -- any direct or virtual base class or non-static data member of a type with +// a destructor that is deleted or inaccessible +struct NoAccessDtor { +private: + ~NoAccessDtor(); + friend struct HasAccessDtor; +}; + +struct HasNoAccessDtor { + NoAccessDtor NAD; // expected-note{{copy constructor of 'HasNoAccessDtor' is implicitly deleted because field 'NAD' has an inaccessible destructor}} + HasNoAccessDtor(); + ~HasNoAccessDtor(); +}; +HasNoAccessDtor HNADa; +HasNoAccessDtor HNADb(HNADa); // expected-error{{call to implicitly-deleted copy constructor}} + +struct HasAccessDtor { + NoAccessDtor NAD; +}; +HasAccessDtor HADa; +HasAccessDtor HADb(HADa); + +struct HasNoAccessDtorBase : NoAccessDtor { // expected-note{{copy constructor of 'HasNoAccessDtorBase' is implicitly deleted because base class 'NoAccessDtor' has an inaccessible destructor}} +}; +extern HasNoAccessDtorBase HNADBa; +HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}} + +// -- a non-static data member of rvalue reference type +struct RValue { + int && ri = 1; // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}} +}; +RValue RVa; +RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy constructor}} diff --git a/clang/test/CXX/special/class.copy/p11.0x.move.cpp b/clang/test/CXX/special/class.copy/p11.0x.move.cpp new file mode 100644 index 0000000..ff9478b --- /dev/null +++ b/clang/test/CXX/special/class.copy/p11.0x.move.cpp @@ -0,0 +1,164 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct NonTrivial { + NonTrivial(NonTrivial&&); +}; + +// A defaulted move constructor for a class X is defined as deleted if X has: + +// -- a variant member with a non-trivial corresponding constructor +union DeletedNTVariant { + NonTrivial NT; + DeletedNTVariant(DeletedNTVariant&&); +}; +DeletedNTVariant::DeletedNTVariant(DeletedNTVariant&&) = default; // expected-error{{would delete}} + +struct DeletedNTVariant2 { + union { + NonTrivial NT; + }; + DeletedNTVariant2(DeletedNTVariant2&&); +}; +DeletedNTVariant2::DeletedNTVariant2(DeletedNTVariant2&&) = default; // expected-error{{would delete}} + +// -- a non-static data member of class type M (or array thereof) that cannot be +// copied because overload resolution results in an ambiguity or a function +// that is deleted or inaccessible +struct NoAccess { + NoAccess() = default; +private: + NoAccess(NoAccess&&); + + friend struct HasAccess; +}; + +struct HasNoAccess { + NoAccess NA; + HasNoAccess(HasNoAccess&&); +}; +HasNoAccess::HasNoAccess(HasNoAccess&&) = default; // expected-error{{would delete}} + +struct HasAccess { + NoAccess NA; + HasAccess(HasAccess&&); +}; +HasAccess::HasAccess(HasAccess&&) = default; + +struct Ambiguity { + Ambiguity(const Ambiguity&&); + Ambiguity(volatile Ambiguity&&); +}; + +struct IsAmbiguous { + Ambiguity A; + IsAmbiguous(IsAmbiguous&&); +}; +IsAmbiguous::IsAmbiguous(IsAmbiguous&&) = default; // expected-error{{would delete}} + +struct Deleted { + IsAmbiguous IA; + Deleted(Deleted&&); +}; +Deleted::Deleted(Deleted&&) = default; // expected-error{{would delete}} + +// -- a direct or virtual base class B that cannot be moved because overload +// resolution results in an ambiguity or a function that is deleted or +// inaccessible +struct AmbiguousMoveBase : Ambiguity { + AmbiguousMoveBase(AmbiguousMoveBase&&); +}; +AmbiguousMoveBase::AmbiguousMoveBase(AmbiguousMoveBase&&) = default; // expected-error{{would delete}} + +struct DeletedMoveBase : AmbiguousMoveBase { + DeletedMoveBase(DeletedMoveBase&&); +}; +DeletedMoveBase::DeletedMoveBase(DeletedMoveBase&&) = default; // expected-error{{would delete}} + +struct InaccessibleMoveBase : NoAccess { + InaccessibleMoveBase(InaccessibleMoveBase&&); +}; +InaccessibleMoveBase::InaccessibleMoveBase(InaccessibleMoveBase&&) = default; // expected-error{{would delete}} + +// -- any direct or virtual base class or non-static data member of a type with +// a destructor that is deleted or inaccessible +struct NoAccessDtor { + NoAccessDtor(NoAccessDtor&&); // expected-note{{copy constructor is implicitly deleted because 'NoAccessDtor' has a user-declared move constructor}} +private: + ~NoAccessDtor(); + friend struct HasAccessDtor; +}; + +struct HasNoAccessDtor { + NoAccessDtor NAD; + HasNoAccessDtor(HasNoAccessDtor&&); +}; +HasNoAccessDtor::HasNoAccessDtor(HasNoAccessDtor&&) = default; // expected-error{{would delete}} + +struct HasAccessDtor { + NoAccessDtor NAD; + HasAccessDtor(HasAccessDtor&&); +}; +HasAccessDtor::HasAccessDtor(HasAccessDtor&&) = default; + +struct HasNoAccessDtorBase : NoAccessDtor { // expected-note{{copy constructor of 'HasNoAccessDtorBase' is implicitly deleted because base class 'NoAccessDtor' has a deleted copy constructor}} +}; +extern HasNoAccessDtorBase HNADBa; +HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}} + +// The restriction on rvalue reference members applies to only the copy +// constructor. +struct RValue { + int &&ri = 1; + RValue(RValue&&); +}; +RValue::RValue(RValue&&) = default; + +// -- a non-static data member or direct or virtual base class with a type that +// does not have a move constructor and is not trivially copyable +struct CopyOnly { + CopyOnly(const CopyOnly&); +}; + +struct NonMove { + CopyOnly CO; + NonMove(NonMove&&); +}; +NonMove::NonMove(NonMove&&) = default; // ok under DR1402 + +struct Moveable { + Moveable(); + Moveable(Moveable&&); +}; + +struct HasMove { + Moveable M; + HasMove(HasMove&&); +}; +HasMove::HasMove(HasMove&&) = default; + +namespace DR1402 { + struct member { + member(); + member(const member&); + member& operator=(const member&); + ~member(); + }; + + struct A { + member m_; + + A() = default; + A(const A&) = default; + A& operator=(const A&) = default; + A(A&&) = default; + A& operator=(A&&) = default; + ~A() = default; + }; + + // ok, A's explicitly-defaulted move operations copy m_. + void f() { + A a, b(a), c(static_cast<A&&>(a)); + a = b; + b = static_cast<A&&>(c); + } +} diff --git a/clang/test/CXX/special/class.copy/p13-0x.cpp b/clang/test/CXX/special/class.copy/p13-0x.cpp new file mode 100644 index 0000000..0a9aa62 --- /dev/null +++ b/clang/test/CXX/special/class.copy/p13-0x.cpp @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// If the implicitly-defined constructor would satisfy the requirements of a +// constexpr constructor, the implicitly-defined constructor is constexpr. +struct Constexpr1 { + constexpr Constexpr1() : n(0) {} + int n; +}; +constexpr Constexpr1 c1a = Constexpr1(Constexpr1()); // ok +constexpr Constexpr1 c1b = Constexpr1(Constexpr1(c1a)); // ok + +struct Constexpr2 { + Constexpr1 ce1; + constexpr Constexpr2() = default; + constexpr Constexpr2(const Constexpr2 &o) : ce1(o.ce1) {} + // no move constructor +}; + +constexpr Constexpr2 c2a = Constexpr2(Constexpr2()); // ok +constexpr Constexpr2 c2b = Constexpr2(Constexpr2(c2a)); // ok + +struct Constexpr3 { + Constexpr2 ce2; + // all special constructors are constexpr, move ctor calls ce2's copy ctor +}; + +constexpr Constexpr3 c3a = Constexpr3(Constexpr3()); // ok +constexpr Constexpr3 c3b = Constexpr3(Constexpr3(c3a)); // ok + +struct NonConstexprCopy { + constexpr NonConstexprCopy() = default; + NonConstexprCopy(const NonConstexprCopy &); + constexpr NonConstexprCopy(NonConstexprCopy &&) = default; + + int n = 42; +}; + +NonConstexprCopy::NonConstexprCopy(const NonConstexprCopy &) = default; // expected-note {{here}} + +constexpr NonConstexprCopy ncc1 = NonConstexprCopy(NonConstexprCopy()); // ok +constexpr NonConstexprCopy ncc2 = ncc1; // expected-error {{constant expression}} expected-note {{non-constexpr constructor}} + +struct NonConstexprDefault { + NonConstexprDefault() = default; + constexpr NonConstexprDefault(int n) : n(n) {} + int n; +}; +struct Constexpr4 { + NonConstexprDefault ncd; +}; + +constexpr NonConstexprDefault ncd = NonConstexprDefault(NonConstexprDefault(1)); +constexpr Constexpr4 c4a = { ncd }; +constexpr Constexpr4 c4b = Constexpr4(c4a); +constexpr Constexpr4 c4c = Constexpr4(static_cast<Constexpr4&&>(const_cast<Constexpr4&>(c4b))); + +struct Constexpr5Base {}; +struct Constexpr5 : Constexpr5Base { constexpr Constexpr5() {} }; +constexpr Constexpr5 ce5move = Constexpr5(); +constexpr Constexpr5 ce5copy = ce5move; diff --git a/clang/test/CXX/special/class.copy/p15-0x.cpp b/clang/test/CXX/special/class.copy/p15-0x.cpp new file mode 100644 index 0000000..fff8844 --- /dev/null +++ b/clang/test/CXX/special/class.copy/p15-0x.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +namespace PR10622 { + struct foo { + const int first; + foo(const foo&) = default; + }; + void find_or_insert(const foo& __obj) { + foo x(__obj); + } + + struct bar : foo { + bar(const bar&) = default; + }; + void test_bar(const bar &obj) { + bar obj2(obj); + } +} + +namespace PR11418 { + template<typename T> + T may_throw() { + return T(); + } + + template<typename T> T &&declval() noexcept; + + struct NonPOD { + NonPOD(); + NonPOD(const NonPOD &) noexcept; + NonPOD(NonPOD &&) noexcept; + }; + + struct X { + NonPOD np = may_throw<NonPOD>(); + }; + + static_assert(noexcept(declval<X>()), "noexcept isn't working at all"); + static_assert(noexcept(X(declval<X&>())), "copy constructor can't throw"); + static_assert(noexcept(X(declval<X>())), "move constructor can't throw"); +} diff --git a/clang/test/CXX/special/class.copy/p15-inclass.cpp b/clang/test/CXX/special/class.copy/p15-inclass.cpp new file mode 100644 index 0000000..c4f8eaf --- /dev/null +++ b/clang/test/CXX/special/class.copy/p15-inclass.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s | FileCheck %s + +namespace PR11418 { + struct NonPOD { + NonPOD(); + NonPOD(const NonPOD &); + NonPOD(NonPOD &&); + }; + + struct X { + NonPOD np; + int a = 17; + }; + + void check_copy(X x) { + X x2(x); + } + + void check_move(X x) { + X x3(static_cast<X&&>(x)); + } + + // CHECK: define linkonce_odr void @_ZN7PR114181XC2EOS0_ + // CHECK-NOT: 17 + // CHECK: call void @_ZN7PR114186NonPODC1EOS0_ + // CHECK-NOT: 17 + // CHECK: load i32* + // CHECK-NOT: 17 + // CHECK: store i32 + // CHECK-NOT: 17 + // CHECK: ret + + // CHECK: define linkonce_odr void @_ZN7PR114181XC2ERKS0_ + // CHECK-NOT: 17 + // CHECK: call void @_ZN7PR114186NonPODC1ERKS0_ + // CHECK-NOT: 17 + // CHECK: load i32* + // CHECK-NOT: 17 + // CHECK: store i32 + // CHECK-NOT: 17 + // CHECK: ret +} diff --git a/clang/test/CXX/special/class.copy/p20.cpp b/clang/test/CXX/special/class.copy/p20.cpp new file mode 100644 index 0000000..8dfb7ca --- /dev/null +++ b/clang/test/CXX/special/class.copy/p20.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct ConstCopy { + ConstCopy(); + ConstCopy &operator=(const ConstCopy&); +}; + +struct NonConstCopy { + NonConstCopy(); + NonConstCopy &operator=(NonConstCopy&); +}; + +struct VirtualInheritsNonConstCopy : virtual NonConstCopy { + VirtualInheritsNonConstCopy(); + VirtualInheritsNonConstCopy &operator=(const VirtualInheritsNonConstCopy&); +}; + +struct ImplicitNonConstCopy1 : NonConstCopy { // expected-note{{the implicit copy assignment operator}} + ImplicitNonConstCopy1(); +}; + +struct ImplicitNonConstCopy2 { // expected-note{{the implicit copy assignment operator}} + ImplicitNonConstCopy2(); + NonConstCopy ncc; +}; + +struct ImplicitNonConstCopy3 { // expected-note{{the implicit copy assignment operator}} + ImplicitNonConstCopy3(); + NonConstCopy ncc_array[2][3]; +}; + +struct ImplicitNonConstCopy4 : VirtualInheritsNonConstCopy { + ImplicitNonConstCopy4(); +}; + +void test_non_const_copy(const ImplicitNonConstCopy1 &cincc1, + const ImplicitNonConstCopy2 &cincc2, + const ImplicitNonConstCopy3 &cincc3, + const ImplicitNonConstCopy4 &cincc4, + const VirtualInheritsNonConstCopy &vincc) { + (void)sizeof(ImplicitNonConstCopy1() = cincc1); // expected-error{{no viable overloaded '='}} + (void)sizeof(ImplicitNonConstCopy2() = cincc2); // expected-error{{no viable overloaded '='}} + (void)sizeof(ImplicitNonConstCopy3() = cincc3); // expected-error{{no viable overloaded '='}} + (void)sizeof(ImplicitNonConstCopy4() = cincc4); // okay + (void)sizeof(VirtualInheritsNonConstCopy() = vincc); +} diff --git a/clang/test/CXX/special/class.copy/p3.cpp b/clang/test/CXX/special/class.copy/p3.cpp new file mode 100644 index 0000000..3d87266 --- /dev/null +++ b/clang/test/CXX/special/class.copy/p3.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s + +// PR6141 +template<typename T> +struct X { + X(); + template<typename U> X(X<U>); + X(const X<T>&); +}; + +void f(X<int>) { } + +struct Y : X<int> { }; +struct Z : X<float> { }; + +// CHECK: define i32 @main() +int main() { + // CHECK: call void @_ZN1YC1Ev + // CHECK: call void @_ZN1XIiEC1ERKS0_ + // CHECK: call void @_Z1f1XIiE + f(Y()); + // CHECK: call void @_ZN1ZC1Ev + // CHECK: call void @_ZN1XIfEC1ERKS0_ + // CHECK: call void @_ZN1XIiEC1IfEES_IT_E + // CHECK: call void @_Z1f1XIiE + f(Z()); +} diff --git a/clang/test/CXX/special/class.copy/p33-0x.cpp b/clang/test/CXX/special/class.copy/p33-0x.cpp new file mode 100644 index 0000000..b66e19a --- /dev/null +++ b/clang/test/CXX/special/class.copy/p33-0x.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++11 -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; +} + +namespace PR10142 { + struct X { + X(); + X(X&&); + X(const X&) = delete; // expected-note 2{{function has been explicitly marked deleted here}} + }; + + void f(int i) { + X x; + try { + X x2; + if (i) + throw x2; // okay + throw x; // expected-error{{call to deleted constructor of 'PR10142::X'}} + } catch (...) { + } + } + + template<typename T> + void f2(int i) { + T x; + try { + T x2; + if (i) + throw x2; // okay + throw x; // expected-error{{call to deleted constructor of 'PR10142::X'}} + } catch (...) { + } + } + + template void f2<X>(int); // expected-note{{in instantiation of function template specialization 'PR10142::f2<PR10142::X>' requested here}} +} diff --git a/clang/test/CXX/special/class.copy/p8-cxx11.cpp b/clang/test/CXX/special/class.copy/p8-cxx11.cpp new file mode 100644 index 0000000..02e6cd1 --- /dev/null +++ b/clang/test/CXX/special/class.copy/p8-cxx11.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +// C++98 [class.copy]p5 / C++11 [class.copy]p8. + +// The implicitly-declared copy constructor for a class X will have the form +// X::X(const X&) +// if [every direct subobject] has a copy constructor whose first parameter is +// of type 'const volatile[opt] T &'. Otherwise, it will have the form +// X::X(X&) + +struct ConstCopy { + ConstCopy(const ConstCopy &); +}; + +struct NonConstCopy { + NonConstCopy(NonConstCopy &); +}; + +struct DeletedConstCopy { + DeletedConstCopy(const DeletedConstCopy &) = delete; +}; + +struct DeletedNonConstCopy { + DeletedNonConstCopy(DeletedNonConstCopy &) = delete; +}; + +struct ImplicitlyDeletedConstCopy { + ImplicitlyDeletedConstCopy(ImplicitlyDeletedConstCopy &&); +}; + + +struct A : ConstCopy {}; +struct B : NonConstCopy { ConstCopy a; }; +struct C : ConstCopy { NonConstCopy a; }; +struct D : DeletedConstCopy {}; +struct E : DeletedNonConstCopy {}; +struct F { ImplicitlyDeletedConstCopy a; }; +struct G : virtual B {}; + +struct Test { + friend A::A(const A &); + friend B::B(B &); + friend C::C(C &); + friend D::D(const D &); + friend E::E(E &); + friend F::F(const F &); + friend G::G(G &); +}; diff --git a/clang/test/CXX/special/class.copy/p9.cpp b/clang/test/CXX/special/class.copy/p9.cpp new file mode 100644 index 0000000..77ab19e --- /dev/null +++ b/clang/test/CXX/special/class.copy/p9.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct ConstCopy { + ConstCopy(); + ConstCopy(const ConstCopy&); +}; + +struct NonConstCopy { + NonConstCopy(); + NonConstCopy(NonConstCopy&); +}; + +struct VirtualInheritsNonConstCopy : virtual NonConstCopy { + VirtualInheritsNonConstCopy(); + VirtualInheritsNonConstCopy(const VirtualInheritsNonConstCopy&); +}; + +struct ImplicitNonConstCopy1 : NonConstCopy { // expected-note {{candidate constructor}} + ImplicitNonConstCopy1(); // expected-note {{candidate constructor}} +}; + +struct ImplicitNonConstCopy2 { // expected-note {{candidate constructor}} + ImplicitNonConstCopy2(); // expected-note {{candidate constructor}} + NonConstCopy ncc; +}; + +struct ImplicitNonConstCopy3 { // expected-note {{candidate constructor}} + ImplicitNonConstCopy3(); // expected-note {{candidate constructor}} + NonConstCopy ncc_array[2][3]; +}; + +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{{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/clang/test/CXX/special/class.ctor/p1.cpp b/clang/test/CXX/special/class.ctor/p1.cpp new file mode 100644 index 0000000..9500a7d --- /dev/null +++ b/clang/test/CXX/special/class.ctor/p1.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct X0 { + struct type { }; + + X0(); + X0(int); + (X0)(float); + X0 (f0)(int); + X0 (f0)(type); + + X0 f1(); + X0 f1(double); +}; + +X0::X0() { } +(X0::X0)(int) { } + +X0 (X0::f0)(int) { return X0(); } + +template<typename T> +struct X1 { + struct type { }; + + X1<T>(); + X1<T>(int); + (X1<T>)(float); + X1(float, float); + (X1)(double); + X1<T> (f0)(int); + X1<T> (f0)(type); + X1 (f1)(int); + X1 (f1)(type); + + template<typename U> X1(U); + X1 f2(); + X1 f2(int); +}; + +template<typename T> X1<T>::X1() { } +template<typename T> (X1<T>::X1)(double) { } +template<typename T> X1<T> X1<T>::f1(int) { return 0; } +template<typename T> X1<T> (X1<T>::f1)(type) { return 0; } diff --git a/clang/test/CXX/special/class.ctor/p4-0x.cpp b/clang/test/CXX/special/class.ctor/p4-0x.cpp new file mode 100644 index 0000000..509beb4 --- /dev/null +++ b/clang/test/CXX/special/class.ctor/p4-0x.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/special/class.ctor/p5-0x.cpp b/clang/test/CXX/special/class.ctor/p5-0x.cpp new file mode 100644 index 0000000..694ab5b --- /dev/null +++ b/clang/test/CXX/special/class.ctor/p5-0x.cpp @@ -0,0 +1,182 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +struct DefaultedDefCtor1 {}; +struct DefaultedDefCtor2 { DefaultedDefCtor2() = default; }; +struct DeletedDefCtor { DeletedDefCtor() = delete; DeletedDefCtor(int); }; // expected-note {{explicitly marked deleted here}} +class PrivateDefCtor { PrivateDefCtor() = default; public: PrivateDefCtor(int); }; +struct DeletedDtor { ~DeletedDtor() = delete; }; // expected-note 4{{explicitly marked deleted here}} +class PrivateDtor { ~PrivateDtor() = default; }; +class Friend { + Friend() = default; ~Friend() = default; + friend struct NotDeleted6c; + friend struct NotDeleted7i; + friend struct NotDeleted7j; + friend struct NotDeleted7k; +}; +struct UserProvidedDefCtor { UserProvidedDefCtor() {} }; +int n; + + +// A defaulted default constructor for a class X is defined as deleted if: + +// - X is a union-like class that has a variant member with a non-trivial +// default constructor, +union Deleted1a { UserProvidedDefCtor u; }; // expected-note {{default constructor of union 'Deleted1a' is implicitly deleted because field 'u' has a non-trivial default constructor}} +Deleted1a d1a; // expected-error {{implicitly-deleted default constructor}} +union NotDeleted1a { DefaultedDefCtor1 nu; }; +NotDeleted1a nd1a; +union NotDeleted1b { DefaultedDefCtor2 nu; }; +NotDeleted1b nd1b; + +// - any non-static data member with no brace-or-equal-initializer is of +// reference type, +class Deleted2a { + Deleted2a() = default; // expected-note 4{{implicitly deleted here}} + int &a; // expected-note 4{{because field 'a' of reference type 'int &' would not be initialized}} +}; +Deleted2a d2a; // expected-error {{implicitly-deleted default constructor}} +struct Deleted2b { + int &&b; // expected-note {{default constructor of 'Deleted2b' is implicitly deleted because field 'b' of reference type 'int &&' would not be initialized}} +}; +Deleted2b d2b; // expected-error {{deleted default constructor}} +class NotDeleted2a { int &a = n; }; +NotDeleted2a nd2a; +class NotDeleted2b { int &a = error; }; // expected-error {{undeclared identifier}} +NotDeleted2b nd2b; +class NotDeleted2c { int &&a = 0; }; +NotDeleted2c nd2c; + +// - any non-variant non-static data member of const qualified type (or array +// thereof) with no brace-or-equal-initializer does not have a user-provided +// default constructor, +class Deleted3a { const int a; }; // expected-note {{because field 'a' of const-qualified type 'const int' would not be initialized}} \ + expected-warning {{does not declare any constructor}} \ + expected-note {{will never be initialized}} +Deleted3a d3a; // expected-error {{implicitly-deleted default constructor}} +class Deleted3b { const DefaultedDefCtor1 a[42]; }; // expected-note {{because field 'a' of const-qualified type 'const DefaultedDefCtor1' would not be initialized}} +Deleted3b d3b; // expected-error {{implicitly-deleted default constructor}} +class Deleted3c { const DefaultedDefCtor2 a; }; // expected-note {{because field 'a' of const-qualified type 'const DefaultedDefCtor2' would not be initialized}} +Deleted3c d3c; // expected-error {{implicitly-deleted default constructor}} +class NotDeleted3a { const int a = 0; }; +NotDeleted3a nd3a; +class NotDeleted3b { const DefaultedDefCtor1 a[42] = {}; }; +NotDeleted3b nd3b; +class NotDeleted3c { const DefaultedDefCtor2 a = DefaultedDefCtor2(); }; +NotDeleted3c nd3c; +union NotDeleted3d { const int a; int b; }; +NotDeleted3d nd3d; +union NotDeleted3e { const DefaultedDefCtor1 a[42]; int b; }; +NotDeleted3e nd3e; +union NotDeleted3f { const DefaultedDefCtor2 a; int b; }; +NotDeleted3f nd3f; +struct NotDeleted3g { union { const int a; int b; }; }; +NotDeleted3g nd3g; + +// - X is a union and all of its variant members are of const-qualified type (or +// array thereof), +union Deleted4a { + const int a; + const int b; + const UserProvidedDefCtor c; // expected-note {{because field 'c' has a non-trivial default constructor}} +}; +Deleted4a d4a; // expected-error {{implicitly-deleted default constructor}} +union NotDeleted4a { const int a; int b; }; +NotDeleted4a nd4a; + +// - X is a non-union class and all members of any anonymous union member are of +// const-qualified type (or array thereof), +struct Deleted5a { + union { const int a; }; // expected-note {{because all data members of an anonymous union member are const-qualified}} + union { int b; }; +}; +Deleted5a d5a; // expected-error {{implicitly-deleted default constructor}} +struct NotDeleted5a { union { const int a; int b; }; union { const int c; int d; }; }; +NotDeleted5a nd5a; + +// - any direct or virtual base class, or non-static data member with no +// brace-or-equal-initializer, has class type M (or array thereof) and either +// M has no default constructor or overload resolution as applied to M's default +// constructor results in an ambiguity or in a function that is deleted or +// inaccessible from the defaulted default constructor, or +struct Deleted6a : Deleted2a {}; // expected-note {{because base class 'Deleted2a' has a deleted default constructor}} +Deleted6a d6a; // expected-error {{implicitly-deleted default constructor}} +struct Deleted6b : virtual Deleted2a {}; // expected-note {{because base class 'Deleted2a' has a deleted default constructor}} +Deleted6b d6b; // expected-error {{implicitly-deleted default constructor}} +struct Deleted6c { Deleted2a a; }; // expected-note {{because field 'a' has a deleted default constructor}} +Deleted6c d6c; // expected-error {{implicitly-deleted default constructor}} +struct Deleted6d { DeletedDefCtor a; }; // expected-note {{because field 'a' has a deleted default constructor}} +Deleted6d d6d; // expected-error {{implicitly-deleted default constructor}} +struct NotDeleted6a { DeletedDefCtor a = 0; }; +NotDeleted6a nd6a; +struct Deleted6e { PrivateDefCtor a; }; // expected-note {{because field 'a' has an inaccessible default constructor}} +Deleted6e d6e; // expected-error {{implicitly-deleted default constructor}} +struct NotDeleted6b { PrivateDefCtor a = 0; }; +NotDeleted6b nd6b; +struct NotDeleted6c { Friend a; }; +NotDeleted6c nd6c; + +// - any direct or virtual base class or non-static data member has a type with +// a destructor that is deleted or inaccessible from the defaulted default +// constructor. +struct Deleted7a : DeletedDtor {}; // expected-note {{because base class 'DeletedDtor' has a deleted destructor}} +Deleted7a d7a; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7b : virtual DeletedDtor {}; // expected-note {{because base class 'DeletedDtor' has a deleted destructor}} +Deleted7b d7b; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7c { DeletedDtor a; }; // expected-note {{because field 'a' has a deleted destructor}} +Deleted7c d7c; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7d { DeletedDtor a = {}; }; // expected-note {{because field 'a' has a deleted destructor}} +Deleted7d d7d; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7e : PrivateDtor {}; // expected-note {{base class 'PrivateDtor' has an inaccessible destructor}} +Deleted7e d7e; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7f : virtual PrivateDtor {}; // expected-note {{base class 'PrivateDtor' has an inaccessible destructor}} +Deleted7f d7f; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7g { PrivateDtor a; }; // expected-note {{field 'a' has an inaccessible destructor}} +Deleted7g d7g; // expected-error {{implicitly-deleted default constructor}} +struct Deleted7h { PrivateDtor a = {}; }; // expected-note {{field 'a' has an inaccessible destructor}} +Deleted7h d7h; // expected-error {{implicitly-deleted default constructor}} +struct NotDeleted7i : Friend {}; +NotDeleted7i d7i; +struct NotDeleted7j : virtual Friend {}; +NotDeleted7j d7j; +struct NotDeleted7k { Friend a; }; +NotDeleted7k d7k; + + +class Trivial { static const int n = 42; }; +static_assert(__has_trivial_constructor(Trivial), "Trivial is nontrivial"); + +// A default constructor is trivial if it is not user-provided and if: +class NonTrivialDefCtor1 { NonTrivialDefCtor1(); }; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor1), "NonTrivialDefCtor1 is trivial"); + +// - its class has no virtual functions (10.3) and no virtual base classes (10.1), and +class NonTrivialDefCtor2 { virtual void f(); }; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor2), "NonTrivialDefCtor2 is trivial"); +class NonTrivialDefCtor3 : virtual Trivial {}; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor3), "NonTrivialDefCtor3 is trivial"); + +// - no non-static data member of its class has a brace-or-equal-initializer, and +class NonTrivialDefCtor4 { int m = 52; }; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor4), "NonTrivialDefCtor4 is trivial"); + +// - all the direct base classes of its class have trivial default constructors, and +class NonTrivialDefCtor5 : NonTrivialDefCtor1 {}; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor5), "NonTrivialDefCtor5 is trivial"); + +// - for all the non-static data members of its class that are of class type (or array thereof), each such class +// has a trivial default constructor. +class NonTrivialDefCtor6 { NonTrivialDefCtor1 t; }; +static_assert(!__has_trivial_constructor(NonTrivialDefCtor6), "NonTrivialDefCtor5 is trivial"); + +// Otherwise, the default constructor is non-trivial. +class Trivial2 { Trivial2() = delete; }; +static_assert(__has_trivial_constructor(Trivial2), "Trivial2 is trivial"); + +class Trivial3 { Trivial3() = default; }; +static_assert(__has_trivial_constructor(Trivial3), "Trivial3 is trivial"); + +template<typename T> class Trivial4 { Trivial4() = default; }; +static_assert(__has_trivial_constructor(Trivial4<int>), "Trivial4 is trivial"); + +template<typename T> class Trivial5 { Trivial5() = delete; }; +static_assert(__has_trivial_constructor(Trivial5<int>), "Trivial5 is trivial"); diff --git a/clang/test/CXX/special/class.ctor/p6-0x.cpp b/clang/test/CXX/special/class.ctor/p6-0x.cpp new file mode 100644 index 0000000..8c8800f --- /dev/null +++ b/clang/test/CXX/special/class.ctor/p6-0x.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 + +// Implicitly-defined default constructors are constexpr if the implicit +// definition would be. +struct NonConstexpr1 { // expected-note {{here}} + int a; +}; +struct NonConstexpr2 { // expected-note {{here}} + NonConstexpr1 nl; +}; +struct NonConstexpr2a : NonConstexpr1 { }; +constexpr NonConstexpr1 nc1 = NonConstexpr1(); // ok, does not call constructor +constexpr NonConstexpr2 nc2 = NonConstexpr2(); // ok, does not call constructor +constexpr NonConstexpr2a nc2a = NonConstexpr2a(); // ok, does not call constructor +constexpr int nc2_a = NonConstexpr2().nl.a; // ok +constexpr int nc2a_a = NonConstexpr2a().a; // ok +struct Helper { + friend constexpr NonConstexpr1::NonConstexpr1(); // expected-error {{follows non-constexpr declaration}} + friend constexpr NonConstexpr2::NonConstexpr2(); // expected-error {{follows non-constexpr declaration}} +}; + +struct Constexpr1 {}; +constexpr Constexpr1 c1 = Constexpr1(); // ok +struct NonConstexpr3 : virtual Constexpr1 {}; // expected-note {{struct with virtual base}} expected-note {{declared here}} +constexpr NonConstexpr3 nc3 = NonConstexpr3(); // expected-error {{non-literal type 'const NonConstexpr3'}} + +struct Constexpr2 { + int a = 0; +}; +constexpr Constexpr2 c2 = Constexpr2(); // ok + +int n; +struct Member { + Member() : a(n) {} + constexpr Member(int&a) : a(a) {} + int &a; +}; +struct NonConstexpr4 { // expected-note {{here}} + Member m; +}; +constexpr NonConstexpr4 nc4 = NonConstexpr4(); // expected-error {{constant expression}} expected-note {{non-constexpr constructor 'NonConstexpr4'}} +struct Constexpr3 { + constexpr Constexpr3() : m(n) {} + Member m; +}; +constexpr Constexpr3 c3 = Constexpr3(); // ok +struct Constexpr4 { + Constexpr3 m; +}; +constexpr Constexpr4 c4 = Constexpr4(); // ok + + +// This rule breaks some legal C++98 programs! +struct A {}; // expected-note {{here}} +struct B { + friend A::A(); // expected-error {{non-constexpr declaration of 'A' follows constexpr declaration}} +}; diff --git a/clang/test/CXX/special/class.dtor/p10-0x.cpp b/clang/test/CXX/special/class.dtor/p10-0x.cpp new file mode 100644 index 0000000..e10afb5 --- /dev/null +++ b/clang/test/CXX/special/class.dtor/p10-0x.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// PR10127/N3031 +struct A { ~A(); }; +struct B {}; +template<typename T> +void b(const T *x, const A *y) { + x->~decltype(T())(); + x->~decltype(*x)(); // expected-error{{the type of object expression ('const int') does not match the type being destroyed ('decltype(*x)' (aka 'const int &')) in pseudo-destructor expression}} \ + expected-error{{no member named '~const struct A &' in 'A'}} + x->~decltype(int())(); // expected-error{{no member named '~int' in 'A'}} + + y->~decltype(*y)(); // expected-error{{destructor type 'decltype(*y)' (aka 'const A &') in object destruction expression does not match the type 'const A' of the object being destroyed}} + y->~decltype(T())(); // expected-error{{destructor type 'decltype(T())' in object destruction expression does not match the type 'const A' of the object being destroyed}} + y->~decltype(A())(); +} +template void b(const int*, const A*); // expected-note{{in instantiation of function template specialization 'b<int>' requested here}} +template void b(const A*,const A*); // expected-note{{in instantiation of function template specialization 'b<A>' requested here}} +void a(const A *x, int i, int *pi) { + x->~decltype(A())(); + x->~decltype(*x)(); // expected-error{{destructor type 'decltype(*x)' (aka 'const A &') in object destruction expression does not match the type 'const A' of the object being destroyed}} + x->~decltype()(); // expected-error{{expected expression}} + x->~decltype(B())(); // expected-error{{destructor type 'decltype(B())' (aka 'B') in object destruction expression does not match the type 'const A' of the object being destroyed}} + x->~decltype(x)(); // expected-error{{destructor type 'decltype(x)' (aka 'const A *') in object destruction expression does not match the type 'const A' of the object being destroyed}} + // this last one could be better, mentioning that the nested-name-specifier could be removed or a type name after the ~ + x->::A::~decltype(*x)(); // expected-error{{expected a class name after '~' to name a destructor}} + y->~decltype(A())(); // expected-error{{use of undeclared identifier 'y'}} + + typedef int *intp; + i->~decltype(int())(); // expected-error{{member reference type 'int' is not a pointer; maybe you meant to use '.'?}} + i.~decltype(int())(); + i->~decltype(intp())(); // expected-error{{member reference type 'int' is not a pointer; maybe you meant to use '.'?}} \ + expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}} + i.~decltype(intp())(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}} + pi->~decltype(int())(); + pi.~decltype(int())(); // expected-error{{the type of object expression ('int *') does not match the type being destroyed ('decltype(int())' (aka 'int')) in pseudo-destructor expression}} + pi.~decltype(intp())(); + pi->~decltype(intp())(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}} +} diff --git a/clang/test/CXX/special/class.dtor/p2-0x.cpp b/clang/test/CXX/special/class.dtor/p2-0x.cpp new file mode 100644 index 0000000..c7b1b58 --- /dev/null +++ b/clang/test/CXX/special/class.dtor/p2-0x.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/special/class.dtor/p2.cpp b/clang/test/CXX/special/class.dtor/p2.cpp new file mode 100644 index 0000000..b05c992 --- /dev/null +++ b/clang/test/CXX/special/class.dtor/p2.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5548 +struct A {~A();}; +void a(const A* x) { + x->~A(); +} diff --git a/clang/test/CXX/special/class.dtor/p3-0x.cpp b/clang/test/CXX/special/class.dtor/p3-0x.cpp new file mode 100644 index 0000000..44bf5aa --- /dev/null +++ b/clang/test/CXX/special/class.dtor/p3-0x.cpp @@ -0,0 +1,177 @@ +// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s + +struct A { + ~A(); +}; + +struct B { + ~B() throw(int); +}; + +struct C { + B b; + ~C() {} +}; + +struct D { + ~D() noexcept(false); +}; + +struct E { + D d; + ~E() {} +}; + +void foo() { + A a; + C c; + E e; + // CHECK: invoke {{.*}} @_ZN1ED1Ev + // CHECK: invoke {{.*}} @_ZN1CD1Ev + // CHECK: call {{.*}} @_ZN1AD1Ev +} + +struct F { + D d; + ~F(); +}; +F::~F() noexcept(false) {} + +struct G { + D d; + ~G(); +}; +G::~G() {} + +struct H { + B b; + ~H(); +}; +H::~H() throw(int) {} + +struct I { + B b; + ~I(); +}; +I::~I() {} + +// Template variants. + +template <typename T> +struct TA { + ~TA(); +}; + +template <typename T> +struct TB { + ~TB() throw(int); +}; + +template <typename T> +struct TC { + TB<T> b; + ~TC() {} +}; + +template <typename T> +struct TD { + ~TD() noexcept(false); +}; + +template <typename T> +struct TE { + TD<T> d; + ~TE() {} +}; + +void tfoo() { + TA<int> a; + TC<int> c; + TE<int> e; + // CHECK: invoke {{.*}} @_ZN2TEIiED1Ev + // CHECK: invoke {{.*}} @_ZN2TCIiED1Ev + // CHECK: call {{.*}} @_ZN2TAIiED1Ev +} + +template <typename T> +struct TF { + TD<T> d; + ~TF(); +}; +template <typename T> +TF<T>::~TF() noexcept(false) {} + +template <typename T> +struct TG { + TD<T> d; + ~TG(); +}; +template <typename T> +TG<T>::~TG() {} + +template <typename T> +struct TH { + TB<T> b; + ~TH(); +}; +template <typename T> +TH<T>::~TH() {} + +void tinst() { + TF<int> f; + TG<int> g; + TH<int> h; +} +// CHECK: define linkonce_odr {{.*}} @_ZN2THIiED1Ev +// CHECK: _ZTIi +// CHECK: __cxa_call_unexpected + +struct VX +{ virtual ~VX() {} }; + +struct VY : VX +{ virtual ~VY() {} }; + +template<typename T> +struct TVY : VX +{ virtual ~TVY() {} }; + + +struct VA { + B b; + virtual ~VA() {} +}; + +struct VB : VA +{ virtual ~VB() {} }; + +template<typename T> +struct TVB : VA +{ virtual ~TVB() {} }; + +void tinst2() { + TVY<int> tvy; + TVB<int> tvb; +} + +template <typename T> +struct Sw { + T t; + ~Sw() {} +}; + +void tsw() { + Sw<int> swi; + Sw<B> swb; +} +// CHECK-NOT: define linkonce_odr {{.*}} @_ZN2SwI1BED1Ev({{.*}} nounwind +// CHECK: define linkonce_odr {{.*}} @_ZN2SwI1BED1Ev({{.*}} +// CHECK: _ZTIi +// CHECK: __cxa_call_unexpected +// CHECK: define linkonce_odr {{.*}} @_ZN2SwIiED1Ev({{.*}} nounwind + +template <typename T> +struct TVC : VX +{ virtual ~TVC(); }; +template <typename T> +TVC<T>::~TVC() {} diff --git a/clang/test/CXX/special/class.dtor/p5-0x.cpp b/clang/test/CXX/special/class.dtor/p5-0x.cpp new file mode 100644 index 0000000..dbfa004 --- /dev/null +++ b/clang/test/CXX/special/class.dtor/p5-0x.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -verify -std=c++11 %s + +struct NonTrivDtor { + ~NonTrivDtor(); +}; +struct DeletedDtor { + ~DeletedDtor() = delete; // expected-note 5 {{deleted here}} +}; +class InaccessibleDtor { + ~InaccessibleDtor() = default; +}; + +// A defaulted destructor for a class X is defined as deleted if: + +// -- X is a union-like class that has a variant member with a non-trivial +// destructor. +union A1 { + A1(); + NonTrivDtor n; // expected-note {{destructor of union 'A1' is implicitly deleted because field 'n' has a non-trivial destructor}} +}; +A1 a1; // expected-error {{deleted function}} +struct A2 { + A2(); + union { + NonTrivDtor n; // expected-note {{because field 'n' has a non-trivial destructor}} + }; +}; +A2 a2; // expected-error {{deleted function}} +union A3 { + A3(); + NonTrivDtor n[3]; // expected-note {{because field 'n' has a non-trivial destructor}} +}; +A3 a3; // expected-error {{deleted function}} +struct A4 { + A4(); + union { + NonTrivDtor n[3]; // expected-note {{because field 'n' has a non-trivial destructor}} + }; +}; +A4 a4; // expected-error {{deleted function}} + +// -- any of the non-static data members has class type M (or array thereof) and +// M has a deleted or inaccessible destructor. +struct B1 { + B1(); + DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}} +}; +B1 b1; // expected-error {{deleted function}} +struct B2 { + B2(); + InaccessibleDtor a; // expected-note {{because field 'a' has an inaccessible destructor}} +}; +B2 b2; // expected-error {{deleted function}} +struct B3 { + B3(); + DeletedDtor a[4]; // expected-note {{because field 'a' has a deleted destructor}} +}; +B3 b3; // expected-error {{deleted function}} +struct B4 { + B4(); + InaccessibleDtor a[4]; // expected-note {{because field 'a' has an inaccessible destructor}} +}; +B4 b4; // expected-error {{deleted function}} +union B5 { + B5(); + // FIXME: Describe the anonymous union member better than ''. + union { // expected-note {{because field '' has a deleted destructor}} + DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}} + }; +}; +B5 b5; // expected-error {{deleted function}} +union B6 { + B6(); + union { // expected-note {{because field '' has a deleted destructor}} + InaccessibleDtor a; // expected-note {{because field 'a' has an inaccessible destructor}} + }; +}; +B6 b6; // expected-error {{deleted function}} + +// -- any direct or virtual base class has a deleted or inaccessible destructor. +struct C1 : DeletedDtor { C1(); } c1; // expected-error {{deleted function}} expected-note {{base class 'DeletedDtor' has a deleted destructor}} +struct C2 : InaccessibleDtor { C2(); } c2; // expected-error {{deleted function}} expected-note {{base class 'InaccessibleDtor' has an inaccessible destructor}} +struct C3 : virtual DeletedDtor { C3(); } c3; // expected-error {{deleted function}} expected-note {{base class 'DeletedDtor' has a deleted destructor}} +struct C4 : virtual InaccessibleDtor { C4(); } c4; // expected-error {{deleted function}} expected-note {{base class 'InaccessibleDtor' has an inaccessible destructor}} + +// -- for a virtual destructor, lookup of the non-array deallocation function +// results in an ambiguity or a function that is deleted or inaccessible. +class D1 { + void operator delete(void*); +public: + virtual ~D1() = default; +} d1; // ok +struct D2 : D1 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} + // implicitly-virtual destructor +} d2; // expected-error {{deleted function}} +struct D3 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} + virtual ~D3() = default; // expected-note {{explicitly defaulted function was implicitly deleted here}} + void operator delete(void*, double = 0.0); + void operator delete(void*, char = 0); +} d3; // expected-error {{deleted function}} +struct D4 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} + virtual ~D4() = default; // expected-note {{implicitly deleted here}} + void operator delete(void*) = delete; +} d4; // expected-error {{deleted function}} diff --git a/clang/test/CXX/special/class.dtor/p9.cpp b/clang/test/CXX/special/class.dtor/p9.cpp new file mode 100644 index 0000000..8b76a15 --- /dev/null +++ b/clang/test/CXX/special/class.dtor/p9.cpp @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +typedef typeof(sizeof(int)) size_t; + +// PR7803 +namespace test0 { + class A { + public: + static void operator delete(void *p) {}; + virtual ~A(); + }; + + class B : protected A { + public: + ~B(); + }; + + class C : protected B { + public: + using B::operator delete; + ~C(); + }; + + // Shouldn't have an error. + C::~C() {} +} + +namespace test1 { + class A { + public: + static void operator delete(void *p) {}; // expected-note {{member 'operator delete' declared here}} + virtual ~A(); + }; + + class B : protected A { + public: + static void operator delete(void *, size_t) {}; // expected-note {{member 'operator delete' declared here}} + ~B(); + }; + + class C : protected B { + public: + using A::operator delete; + using B::operator delete; + + ~C(); + }; + + C::~C() {} // expected-error {{multiple suitable 'operator delete' functions in 'C'}} +} + +// ...at the point of definition of a virtual destructor... +namespace test2 { + struct A { + virtual ~A(); + static void operator delete(void*, const int &); + }; + + struct B { + virtual ~B(); + static void operator delete(void*, const int &); // expected-note {{declared here}} + }; + B::~B() {} // expected-error {{no suitable member 'operator delete' in 'B'}} + + struct CBase { virtual ~CBase(); }; + struct C : CBase { // expected-error {{no suitable member 'operator delete' in 'C'}} + static void operator delete(void*, const int &); // expected-note {{declared here}} + }; + void test() { + C c; // expected-note {{first required here}} + } +} + +// PR7346 +namespace test3 { + struct A { + virtual ~A(); + static void operator delete(void*, const int &); + }; + + struct B : A { + virtual ~B() {} + static void operator delete(void*); + }; +} diff --git a/clang/test/CXX/special/class.free/p1.cpp b/clang/test/CXX/special/class.free/p1.cpp new file mode 100644 index 0000000..5c0240b --- /dev/null +++ b/clang/test/CXX/special/class.free/p1.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +#include <stddef.h> + +struct A { + void *operator new(size_t) { + return this; // expected-error {{invalid use of 'this' outside of a non-static member function}} + } + void *operator new[](size_t) { + return this; // expected-error {{invalid use of 'this' outside of a non-static member function}} + } +}; diff --git a/clang/test/CXX/special/class.free/p6.cpp b/clang/test/CXX/special/class.free/p6.cpp new file mode 100644 index 0000000..fc4b2ae --- /dev/null +++ b/clang/test/CXX/special/class.free/p6.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +#include <stddef.h> + +struct A { + void operator delete(void*) { + (void)this; // expected-error {{invalid use of 'this' outside of a non-static member function}} + } + void operator delete[](void*) { + (void)this; // expected-error {{invalid use of 'this' outside of a non-static member function}} + } +}; diff --git a/clang/test/CXX/special/class.inhctor/elsewhere.cpp b/clang/test/CXX/special/class.inhctor/elsewhere.cpp new file mode 100644 index 0000000..09fd3d5 --- /dev/null +++ b/clang/test/CXX/special/class.inhctor/elsewhere.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -std=c++11 -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}} expected-error {{not supported}} + +// 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}} expected-error {{not supported}} + using B1::B1; // expected-error {{redeclaration of using decl}} expected-error {{not supported}} +}; + +// 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}} expected-error {{not supported}} +}; + +template<typename T> struct A {}; + +template<typename T> struct B : A<bool>, A<char> { + using A<T>::A; // expected-error {{'A<double>::', which is not a base class of 'B<double>'}} expected-error {{not supported}} +}; +B<bool> bb; +B<char> bc; +B<double> bd; // expected-note {{here}} + +template<typename T> struct C : A<T> { + using A<bool>::A; // expected-error {{'A<bool>::', which is not a base class of 'C<char>'}} expected-error {{not supported}} +}; +C<bool> cb; +C<char> cc; // expected-note {{here}} + +template<typename T> struct D : A<T> {}; +template<typename T> struct E : D<T> { + using A<bool>::A; // expected-error {{'A<bool>' is not a direct base of 'E<bool>', can not inherit}} expected-error {{not supported}} +}; +E<bool> eb; // expected-note {{here}} + +template<typename T> struct F : D<bool> { + using A<T>::A; // expected-error {{'A<bool>' is not a direct base of 'F<bool>'}} expected-error {{not supported}} +}; +F<bool> fb; // expected-note {{here}} diff --git a/clang/test/CXX/special/class.inhctor/p3.cpp b/clang/test/CXX/special/class.inhctor/p3.cpp new file mode 100644 index 0000000..d7093fb --- /dev/null +++ b/clang/test/CXX/special/class.inhctor/p3.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct B1 { + B1(int); + B1(int, int); +}; +struct D1 : B1 { + using B1::B1; // expected-error {{not supported}} +}; +D1 d1a(1), d1b(1, 1); + +D1 fd1() { return 1; } + +struct B2 { + explicit B2(int, int = 0, int = 0); +}; +struct D2 : B2 { // expected-note 2 {{candidate constructor}} + using B2::B2; // expected-error {{not supported}} +}; +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 2 {{candidate constructor}} + using B3::B3; // expected-note {{candidate constructor (inherited)}} expected-error {{not supported}} +}; +D3 fd3() { return 1; } // expected-error {{no viable conversion}} + +template<typename T> struct T1 : B1 { + using B1::B1; // expected-error {{not supported}} +}; +template<typename T> struct T2 : T1<T> { + using T1<int>::T1; // expected-error {{not supported}} +}; +template<typename T> struct T3 : T1<int> { + using T1<T>::T1; // expected-error {{not supported}} +}; +struct U { + friend T1<int>::T1(int); + friend T1<int>::T1(int, int); + friend T2<int>::T2(int); + friend T2<int>::T2(int, int); + friend T3<int>::T3(int); + friend T3<int>::T3(int, int); +}; diff --git a/clang/test/CXX/special/class.inhctor/p7.cpp b/clang/test/CXX/special/class.inhctor/p7.cpp new file mode 100644 index 0000000..bfaa3ac --- /dev/null +++ b/clang/test/CXX/special/class.inhctor/p7.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Straight from the standard +struct B1 { + B1(int); // expected-note {{previous constructor}} expected-note {{conflicting constructor}} +}; +struct B2 { + B2(int); // expected-note {{conflicting constructor}} +}; +struct D1 : B1, B2 { + using B1::B1; // expected-note {{inherited here}} expected-error {{not supported}} + using B2::B2; // expected-error {{already inherited constructor with the same signature}} expected-error {{not supported}} +}; +struct D2 : B1, B2 { + using B1::B1; // expected-error {{not supported}} + using B2::B2; // expected-error {{not supported}} + D2(int); +}; + +template<typename T> struct B3 { + B3(T); // expected-note {{previous constructor}} +}; +template<typename T> struct B4 : B3<T>, B1 { + B4(); + using B3<T>::B3; // expected-note {{inherited here}} expected-error {{not supported}} + using B1::B1; // expected-error {{already inherited}} expected-error {{not supported}} +}; +B4<char> b4c; +B4<int> b4i; // expected-note {{here}} diff --git a/clang/test/CXX/special/class.init/class.base.init/p8-0x.cpp b/clang/test/CXX/special/class.init/class.base.init/p8-0x.cpp new file mode 100644 index 0000000..a108533 --- /dev/null +++ b/clang/test/CXX/special/class.init/class.base.init/p8-0x.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +int n; +struct S { + int &a; // expected-note 2{{here}} + int &b = n; + + union { + const int k = 42; + }; + + S() {} // expected-error {{constructor for 'S' must explicitly initialize the reference member 'a'}} + S(int) : a(n) {} // ok + S(char) : b(n) {} // expected-error {{constructor for 'S' must explicitly initialize the reference member 'a'}} + S(double) : a(n), b(n) {} // ok +} s(0); + +union U { + int a = 0; // desired-note 5 {{previous initialization is here}} + char b = 'x'; + + // FIXME: these should all be rejected + U() {} // desired-error {{initializing multiple members of union}} + U(int) : a(1) {} // desired-error {{initializing multiple members of union}} + U(char) : b('y') {} // desired-error {{initializing multiple members of union}} + // this expected note should be removed & the note should appear on the + // declaration of 'a' when this set of cases is handled correctly. + U(double) : a(1), // expected-note{{previous initialization is here}} desired-error {{initializing multiple members of union}} + b('y') {} // expected-error{{initializing multiple members of union}} +}; + +// PR10954: variant members do not acquire an implicit initializer. +namespace VariantMembers { + struct NoDefaultCtor { + NoDefaultCtor(int); + }; + union V { + NoDefaultCtor ndc; + int n; + + V() {} + V(int n) : n(n) {} + V(int n, bool) : ndc(n) {} + }; + struct K { + union { + NoDefaultCtor ndc; + int n; + }; + K() {} + K(int n) : n(n) {} + K(int n, bool) : ndc(n) {} + }; + struct Nested { + Nested() {} + union { + struct { + NoDefaultCtor ndc; + }; + }; + }; +} diff --git a/clang/test/CXX/special/class.init/class.base.init/p9-0x.cpp b/clang/test/CXX/special/class.init/class.base.init/p9-0x.cpp new file mode 100644 index 0000000..ca5e807 --- /dev/null +++ b/clang/test/CXX/special/class.init/class.base.init/p9-0x.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -std=c++11 %s -O1 -emit-llvm -o - | FileCheck %s + +struct S { + int n = 10; + int m = 2 * n; + + S() {} + S(int a) : n(a) {} + S(int a, int b) : n(a), m(b) {} + + struct T { + T *that = this; + }; +}; + +template<typename T> +struct U { + T *r = &q; + T q = 42; + U *p = this; +}; + +S a; +// CHECK: @a = {{.*}} { i32 10, i32 20 } + +S b(5); +// CHECK: @b = {{.*}} { i32 5, i32 10 } + +S c(3, 9); +// CHECK: @c = {{.*}} { i32 3, i32 9 } + +S::T d; +// CHECK: @d = {{.*}} { {{.*}} @d } + +U<S> e; +// CHECK: @e = {{.*}} { {{.*}} { i32 42, i32 84 }, {{.*}} @e } diff --git a/clang/test/CXX/special/class.temporary/p1.cpp b/clang/test/CXX/special/class.temporary/p1.cpp new file mode 100644 index 0000000..4f6ac0a --- /dev/null +++ b/clang/test/CXX/special/class.temporary/p1.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +namespace test0 { + struct A { + A() = default; + int x; + int y; + + A(const A&) = delete; // expected-note {{function has been explicitly marked deleted here}} + }; + + void foo(...); + + void test() { + A a; + foo(a); // expected-error {{call to deleted constructor of 'test0::A'}} + } +} + +namespace test1 { + struct A { + A() = default; + int x; + int y; + + private: + A(const A&) = default; // expected-note {{declared private here}} + }; + + void foo(...); + + void test() { + A a; + foo(a); // expected-error {{calling a private constructor of class 'test1::A'}} + } +} + +// Don't enforce this in an unevaluated context. +namespace test2 { + struct A { + A(const A&) = delete; // expected-note {{marked deleted here}} + }; + + typedef char one[1]; + typedef char two[2]; + + one &meta(bool); + two &meta(...); + + void a(A &a) { + char check[sizeof(meta(a)) == 2 ? 1 : -1]; + } + + void b(A &a) { + meta(a); // expected-error {{call to deleted constructor}} + } +} diff --git a/clang/test/CXX/stmt.stmt/stmt.ambig/p1-0x.cpp b/clang/test/CXX/stmt.stmt/stmt.ambig/p1-0x.cpp new file mode 100644 index 0000000..81e8e25 --- /dev/null +++ b/clang/test/CXX/stmt.stmt/stmt.ambig/p1-0x.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +struct T { + struct x { + int m; + }; + x* operator->(); + void operator++(int); + void operator<<(int); + T(); + T(int); + T(int, int); +}; + +template<typename A, typename B, typename C, typename D, typename E> +void func(A, B, C, D, E); + +void func(int a, int c) { + T(a)->m = 7; + T(a)++; + T(a,5)<<c; + + T(*d)(int); + T(e)[5]; + T(f) = {1, 2}; + T(*g)(double(3)); // expected-error{{cannot initialize a variable of type 'T (*)' with an rvalue of type 'double'}} + func(a, d, e, f, g); +} + +void func2(int a, int c) { + decltype(T())(a)->m = 7; + decltype(T())(a)++; + decltype(T())(a,5)<<c; + + decltype(T())(*d)(int); + decltype(T())(e)[5]; + decltype(T())(f) = {1, 2}; + decltype(T())(*g)(double(3)); // expected-error{{cannot initialize a variable of type 'decltype(T()) (*)' (aka 'T *') with an rvalue of type 'double'}} + func(a, d, e, f, g); +} diff --git a/clang/test/CXX/stmt.stmt/stmt.dcl/p3-0x.cpp b/clang/test/CXX/stmt.stmt/stmt.dcl/p3-0x.cpp new file mode 100644 index 0000000..574cb40 --- /dev/null +++ b/clang/test/CXX/stmt.stmt/stmt.dcl/p3-0x.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// PR10034 +struct X {}; + +void exx(X) {} + +int test_ptr10034(int argc, char **argv) +{ + if (argc > 3) + goto end; + + X x; + X xs[16]; + exx(x); + + end: + if (argc > 1) { + for (int i = 0; i < argc; ++i) + { + + } + } + return 0; +} + +struct Y { + ~Y(); +}; + +void f(); +void test_Y() { + goto end; // expected-error{{goto into protected scope}} + Y y; // expected-note{{jump bypasses variable with a non-trivial destructor}} + end: + f(); + goto inner; // expected-error{{goto into protected scope}} + { + Y y2; // expected-note{{jump bypasses variable with a non-trivial destructor}} + inner: + f(); + } + return; +} + +struct Z { + Z operator=(const Z&); +}; + +void test_Z() { + goto end; + Z z; + end: + return; +} diff --git a/clang/test/CXX/stmt.stmt/stmt.dcl/p3.cpp b/clang/test/CXX/stmt.stmt/stmt.dcl/p3.cpp new file mode 100644 index 0000000..f52e3b6 --- /dev/null +++ b/clang/test/CXX/stmt.stmt/stmt.dcl/p3.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR10034 +struct X {}; + +void exx(X) {} + +int test_ptr10034(int argc, char **argv) +{ + if (argc > 3) + goto end; + + X x; + X xs[16]; + exx(x); + + end: + if (argc > 1) { + for (int i = 0; i < argc; ++i) + { + + } + } + return 0; +} + +struct Y { + ~Y(); +}; + +void test_Y() { + goto end; // expected-error{{goto into protected scope}} + Y y; // expected-note{{jump bypasses variable with a non-trivial destructor}} + end: + return; +} + +struct Z { + Z operator=(const Z&); +}; + +void test_Z() { + goto end; // expected-error{{goto into protected scope}} + Z z; // expected-note{{jump bypasses initialization of non-POD variable}} + end: + return; +} diff --git a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp new file mode 100644 index 0000000..a45b35f --- /dev/null +++ b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp @@ -0,0 +1,209 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +namespace std { + template<typename T> + auto begin(T &&t) -> decltype(t.begin()) { return t.begin(); } // expected-note 4{{ignored: substitution failure}} + template<typename T> + auto end(T &&t) -> decltype(t.end()) { return t.end(); } // expected-note {{candidate template ignored: substitution failure [with T = }} + + template<typename T> + auto begin(T &&t) -> decltype(t.alt_begin()) { return t.alt_begin(); } // expected-note {{selected 'begin' template [with T = }} \ + expected-note 4{{candidate template ignored: substitution failure [with T = }} + template<typename T> + auto end(T &&t) -> decltype(t.alt_end()) { return t.alt_end(); } // expected-note {{candidate template ignored: substitution failure [with T = }} + + namespace inner { + // These should never be considered. + int begin(int); + int end(int); + } + + using namespace inner; +} + +struct A { // expected-note 2 {{candidate constructor}} + A(); + int *begin(); // expected-note 3{{selected 'begin' function with iterator type 'int *'}} expected-note {{'begin' declared here}} + int *end(); +}; + +struct B { + B(); + int *alt_begin(); + int *alt_end(); +}; + +void f(); +void f(int); + +void g() { + for (int a : A()) + A __begin; + for (char *a : A()) { // expected-error {{cannot initialize a variable of type 'char *' with an lvalue of type 'int'}} + } + for (char *a : B()) { // expected-error {{cannot initialize a variable of type 'char *' with an lvalue of type 'int'}} + } + // FIXME: Terrible diagnostic here. auto deduction should fail, but does not! + for (double a : f) { // expected-error {{cannot use type '<overloaded function type>' as a range}} + } + for (auto a : A()) { + } + for (auto a : B()) { + } + for (auto *a : A()) { // expected-error {{variable 'a' with type 'auto *' has incompatible initializer of type 'int'}} + } + // : is not a typo for :: here. + for (A NS:A()) { // expected-error {{no viable conversion from 'int' to 'A'}} + } + for (auto not_in_scope : not_in_scope) { // expected-error {{use of undeclared identifier 'not_in_scope'}} + } + + for (auto a : A()) + for (auto b : A()) { + __range.begin(); // expected-error {{use of undeclared identifier '__range'}} + ++__begin; // expected-error {{use of undeclared identifier '__begin'}} + --__end; // expected-error {{use of undeclared identifier '__end'}} + } + + for (char c : "test") + ; + for (auto a : f()) // expected-error {{cannot use type 'void' as a range}} + ; + + extern int incomplete[]; + for (auto a : incomplete) // expected-error {{cannot use incomplete type 'int []' as a range}} + ; + extern struct Incomplete also_incomplete[2]; // expected-note {{forward declaration}} + for (auto &a : also_incomplete) // expected-error {{cannot use incomplete type 'struct Incomplete [2]' as a range}} + ; + + struct VoidBegin { + void begin(); // expected-note {{selected 'begin' function with iterator type 'void'}} + void end(); + }; + for (auto a : VoidBegin()) // expected-error {{cannot use type 'void' as an iterator}} + ; + + struct null_t { + operator int*(); + }; + struct Differ { + int *begin(); // expected-note {{selected 'begin' function with iterator type 'int *'}} + null_t end(); // expected-note {{selected 'end' function with iterator type 'null_t'}} + }; + for (auto a : Differ()) // expected-error {{'begin' and 'end' must return the same type (got 'int *' and 'null_t')}} + ; + + for (void f() : "error") // expected-error {{for range declaration must declare a variable}} + ; + + for (extern int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'extern'}} + for (static int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'static'}} + for (register int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'register'}} + for (constexpr int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'constexpr'}} + + struct NoBeginADL { + null_t alt_end(); + }; + struct NoEndADL { + null_t alt_begin(); + }; + for (auto u : NoBeginADL()) { // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type 'NoBeginADL'}} + } + for (auto u : NoEndADL()) { // expected-error {{no matching function for call to 'end'}} expected-note {{range has type 'NoEndADL'}} + } + + struct NoBegin { + null_t end(); + }; + struct NoEnd { + null_t begin(); + }; + for (auto u : NoBegin()) { // expected-error {{range type 'NoBegin' has 'end' member but no 'begin' member}} + } + for (auto u : NoEnd()) { // expected-error {{range type 'NoEnd' has 'begin' member but no 'end' member}} + } + + struct NoIncr { + void *begin(); // expected-note {{selected 'begin' function with iterator type 'void *'}} + void *end(); + }; + for (auto u : NoIncr()) { // expected-error {{arithmetic on a pointer to void}} + } + + struct NoNotEq { + NoNotEq begin(); // expected-note {{selected 'begin' function with iterator type 'NoNotEq'}} + NoNotEq end(); + void operator++(); + }; + for (auto u : NoNotEq()) { // expected-error {{invalid operands to binary expression}} + } + + struct NoCopy { + NoCopy(); + NoCopy(const NoCopy &) = delete; + int *begin(); + int *end(); + }; + for (int n : NoCopy()) { // ok + } + + for (int n : 42) { // expected-error {{no matching function for call to 'begin'}} \ + expected-note {{range has type 'int'}} + } + + for (auto a : *also_incomplete) { // expected-error {{cannot use incomplete type 'struct Incomplete' as a range}} + } +} + +template<typename T, typename U> +void h(T t) { + for (U u : t) { // expected-error {{no viable conversion from 'A' to 'int'}} + } + for (auto u : t) { + } +} + +template void h<A, int>(A); +template void h<A(&)[4], A &>(A(&)[4]); +template void h<A(&)[13], A>(A(&)[13]); +template void h<A(&)[13], int>(A(&)[13]); // expected-note {{requested here}} + +template<typename T> +void i(T t) { + for (auto u : t) { // expected-error {{no matching function for call to 'begin'}} \ + expected-error {{member function 'begin' not viable}} \ + expected-note {{range has type}} + } +} +template void i<A[13]>(A*); // expected-note {{requested here}} +template void i<const A>(const A); // expected-note {{requested here}} + +namespace NS { + class ADL {}; + int *begin(ADL); // expected-note {{no known conversion from 'NS::NoADL' to 'NS::ADL'}} + int *end(ADL); + + class NoADL {}; +} +int *begin(NS::NoADL); +int *end(NS::NoADL); + +struct VoidBeginADL {}; +void begin(VoidBeginADL); // expected-note {{selected 'begin' function with iterator type 'void'}} +void end(VoidBeginADL); + +void j() { + for (auto u : NS::ADL()) { + } + for (auto u : NS::NoADL()) { // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type}} + } + for (auto a : VoidBeginADL()) { // expected-error {{cannot use type 'void' as an iterator}} + } +} + +void example() { + int array[5] = { 1, 2, 3, 4, 5 }; + for (int &x : array) + x *= 2; +} diff --git a/clang/test/CXX/stmt.stmt/stmt.label/p1.cpp b/clang/test/CXX/stmt.stmt/stmt.label/p1.cpp new file mode 100644 index 0000000..90367f8 --- /dev/null +++ b/clang/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/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp b/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp new file mode 100644 index 0000000..35e5c91 --- /dev/null +++ b/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int f(); + +void g() { + if (int x = f()) { // expected-note 2{{previous definition}} + int x; // expected-error{{redefinition of 'x'}} + } else { + int x; // expected-error{{redefinition of 'x'}} + } +} + + +void h() { + if (int x = f()) // expected-note 2{{previous definition}} + int x; // expected-error{{redefinition of 'x'}} + else + int x; // expected-error{{redefinition of 'x'}} +} diff --git a/clang/test/CXX/stmt.stmt/stmt.select/stmt.switch/p2-0x.cpp b/clang/test/CXX/stmt.stmt/stmt.select/stmt.switch/p2-0x.cpp new file mode 100644 index 0000000..000c870 --- /dev/null +++ b/clang/test/CXX/stmt.stmt/stmt.select/stmt.switch/p2-0x.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +struct Value { + constexpr Value(int n) : n(n) {} + constexpr operator short() { return n; } + int n; +}; +enum E { E0, E1 }; +struct Alt { + constexpr operator E() { return E0; } +}; + +constexpr short s = Alt(); + +void test(Value v) { + switch (v) { + case Alt(): + case E1: + case Value(2): + case 3: + break; + } + switch (Alt a = Alt()) { + case Alt(): + case E1: + case Value(2): + case 3: + break; + } + switch (E0) { + case Alt(): + case E1: + // FIXME: These should produce a warning that 2 and 3 are not values of the + // enumeration. + case Value(2): + case 3: + break; + } +} diff --git a/clang/test/CXX/temp/p3.cpp b/clang/test/CXX/temp/p3.cpp new file mode 100644 index 0000000..c146bc4 --- /dev/null +++ b/clang/test/CXX/temp/p3.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -verify %s + +template<typename T> struct S { + static int a, b; +}; + +template<typename T> int S<T>::a, S<T>::b; // expected-error {{can only declare a single entity}} + +template<typename T> struct A { static A a; } A<T>::a; // expected-error {{expected ';' after struct}} \ + expected-error {{use of undeclared identifier 'T'}} \ + expected-warning{{extra qualification}} + +template<typename T> struct B { } f(); // expected-error {{expected ';' after struct}} \ + expected-error {{requires a type specifier}} + +template<typename T> struct C { } // expected-error {{expected ';' after struct}} + +A<int> c; diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp new file mode 100644 index 0000000..59ce8b6 --- /dev/null +++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -std=c++11 %s -verify + +namespace std { + typedef decltype(nullptr) nullptr_t; +} + +template<int *ip> struct IP { // expected-note 4 {{template parameter is declared here}} + IP<ip> *ip2; +}; + +constexpr std::nullptr_t get_nullptr() { return nullptr; } + +constexpr std::nullptr_t np = nullptr; + +std::nullptr_t nonconst_np; // expected-note{{declared here}} + +IP<0> ip0; // expected-error{{null non-type template argument must be cast to template parameter type 'int *'}} +IP<(0)> ip1; // expected-error{{null non-type template argument must be cast to template parameter type 'int *'}} +IP<nullptr> ip2; +IP<get_nullptr()> ip3; +IP<(int*)0> ip4; +IP<np> ip5; +IP<nonconst_np> ip5; // expected-error{{non-type template argument of type 'std::nullptr_t' (aka 'nullptr_t') is not a constant expression}} \ +// expected-note{{read of non-constexpr variable 'nonconst_np' is not allowed in a constant expression}} +IP<(float*)0> ip6; // expected-error{{null non-type template argument of type 'float *' does not match template parameter of type 'int *'}} + +struct X { }; +template<int X::*pm> struct PM { // expected-note 2 {{template parameter is declared here}} + PM<pm> *pm2; +}; + +PM<0> pm0; // expected-error{{null non-type template argument must be cast to template parameter type 'int X::*'}} +PM<(0)> pm1; // expected-error{{null non-type template argument must be cast to template parameter type 'int X::*'}} +PM<nullptr> pm2; +PM<get_nullptr()> pm3; +PM<(int X::*)0> pm4; +PM<np> pm5; + +template<int (X::*pmf)(int)> struct PMF { // expected-note 2 {{template parameter is declared here}} + PMF<pmf> *pmf2; +}; + +PMF<0> pmf0; // expected-error{{null non-type template argument must be cast to template parameter type 'int (X::*)(int)'}} +PMF<(0)> pmf1; // expected-error{{null non-type template argument must be cast to template parameter type 'int (X::*)(int)'}} +PMF<nullptr> pmf2; +PMF<get_nullptr()> pmf3; +PMF<(int (X::*)(int))0> pmf4; +PMF<np> pmf5; + + +template<std::nullptr_t np> struct NP { // expected-note 2{{template parameter is declared here}} + NP<np> *np2; +}; + +NP<nullptr> np1; +NP<np> np2; +NP<get_nullptr()> np3; +NP<0> np4; // expected-error{{null non-type template argument must be cast to template parameter type 'std::nullptr_t' (aka 'nullptr_t')}} +constexpr int i = 7; +NP<i> np5; // expected-error{{non-type template argument of type 'const int' cannot be converted to a value of type 'std::nullptr_t'}} diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp new file mode 100644 index 0000000..c4db002 --- /dev/null +++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -triple=x86_64-linux-gnu %s + +// C++11 [temp.arg.nontype]p1: +// +// A template-argument for a non-type, non-template template-parameter shall +// be one of: +// -- an integral constant expression; or +// -- the name of a non-type template-parameter ; or +namespace non_type_tmpl_param { + template <int N> struct X0 { X0(); }; + template <int N> X0<N>::X0() { } + template <int* N> struct X1 { X1(); }; + template <int* N> X1<N>::X1() { } + template <int& N> struct X3 { X3(); }; + template <int& N> X3<N>::X3() { } + template <int (*F)(int)> struct X4 { X4(); }; + template <int (*F)(int)> X4<F>::X4() { } + template <typename T, int (T::* M)(int)> struct X5 { X5(); }; + template <typename T, int (T::* M)(int)> X5<T, M>::X5() { } +} + +// -- a constant expression that designates the address of an object with +// static storage duration and external or internal linkage or a function +// with external or internal linkage, including function templates and +// function template-ids, but excluting non-static class members, expressed +// (ignoring parentheses) as & id-expression, except that the & may be +// omitted if the name refers to a function or array and shall be omitted +// if the corresopnding template-parameter is a reference; or +namespace addr_of_obj_or_func { + template <int* p> struct X0 { }; // expected-note 4{{here}} + template <int (*fp)(int)> struct X1 { }; + template <int &p> struct X2 { }; // expected-note 4{{here}} + template <const int &p> struct X2k { }; // expected-note {{here}} + template <int (&fp)(int)> struct X3 { }; // expected-note 4{{here}} + + int i = 42; + int iarr[10]; + int f(int i); + const int ki = 9; // expected-note 5{{here}} + __thread int ti = 100; // expected-note 2{{here}} + static int f_internal(int); // expected-note 4{{here}} + template <typename T> T f_tmpl(T t); + + void test() { + X0<i> x0a; // expected-error {{must have its address taken}} + X0<&i> x0a_addr; + X0<iarr> x0b; + X0<&iarr> x0b_addr; // expected-error {{cannot be converted to a value of type 'int *'}} + X0<ki> x0c; // expected-error {{must have its address taken}} expected-warning {{internal linkage is a C++11 extension}} + X0<&ki> x0c_addr; // expected-error {{cannot be converted to a value of type 'int *'}} expected-warning {{internal linkage is a C++11 extension}} + X0<&ti> x0d_addr; // expected-error {{refers to thread-local object}} + X1<f> x1a; + X1<&f> x1a_addr; + X1<f_tmpl> x1b; + X1<&f_tmpl> x1b_addr; + X1<f_tmpl<int> > x1c; + X1<&f_tmpl<int> > x1c_addr; + X1<f_internal> x1d; // expected-warning {{internal linkage is a C++11 extension}} + X1<&f_internal> x1d_addr; // expected-warning {{internal linkage is a C++11 extension}} + X2<i> x2a; + X2<&i> x2a_addr; // expected-error {{address taken}} + X2<iarr> x2b; // expected-error {{cannot bind to template argument of type 'int [10]'}} + X2<&iarr> x2b_addr; // expected-error {{address taken}} + X2<ki> x2c; // expected-error {{ignores qualifiers}} expected-warning {{internal linkage is a C++11 extension}} + X2k<ki> x2kc; // expected-warning {{internal linkage is a C++11 extension}} + X2k<&ki> x2kc_addr; // expected-error {{address taken}} expected-warning {{internal linkage is a C++11 extension}} + X2<ti> x2d_addr; // expected-error {{refers to thread-local object}} + X3<f> x3a; + X3<&f> x3a_addr; // expected-error {{address taken}} + X3<f_tmpl> x3b; + X3<&f_tmpl> x3b_addr; // expected-error {{address taken}} + X3<f_tmpl<int> > x3c; + X3<&f_tmpl<int> > x3c_addr; // expected-error {{address taken}} + X3<f_internal> x3d; // expected-warning {{internal linkage is a C++11 extension}} + X3<&f_internal> x3d_addr; // expected-error {{address taken}} expected-warning {{internal linkage is a C++11 extension}} + + int n; // expected-note {{here}} + X0<&n> x0_no_linkage; // expected-error {{non-type template argument refers to object 'n' that does not have linkage}} + struct Local { static int f() {} }; // expected-note {{here}} + X1<&Local::f> x1_no_linkage; // expected-error {{non-type template argument refers to function 'f' that does not have linkage}} + } +} + +// -- a constant expression that evaluates to a null pointer value (4.10); or +// -- a constant expression that evaluates to a null member pointer value +// (4.11); or +// -- a pointer to member expressed as described in 5.3.1. + +namespace bad_args { + template <int* N> struct X0 { }; // expected-note 2{{template parameter is declared here}} + int i = 42; + X0<&i + 2> x0a; // expected-error{{non-type template argument does not refer to any declaration}} + int* iptr = &i; + X0<iptr> x0b; // expected-error{{non-type template argument for template parameter of pointer type 'int *' must have its address taken}} +} diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp new file mode 100644 index 0000000..9b9b532 --- /dev/null +++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp @@ -0,0 +1,205 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [temp.arg.nontype] p5: +// The following conversions are performed on each expression used as +// a non-type template-argument. If a non-type template-argument cannot be +// converted to the type of the corresponding template-parameter then the +// program is ill-formed. +// -- for a non-type template-parameter of integral or enumeration type, +// integral promotions (4.5) and integral conversions (4.7) are applied. +namespace integral_parameters { + template<short s> struct X0 { }; + X0<17> x0i; + X0<'a'> x0c; + template<char c> struct X1 { }; + X1<100l> x1l; +} + +// -- for a non-type template-parameter of type pointer to object, +// qualification conversions (4.4) and the array-to-pointer conversion +// (4.2) are applied; if the template-argument is of type +// std::nullptr_t, the null pointer conversion (4.10) is applied. +namespace pointer_to_object_parameters { + // PR6226 + struct Str { + Str(const char *); + }; + + template<const char *s> + struct A { + Str get() { return s; } + }; + + char hello[6] = "Hello"; + extern const char world[6]; + const char world[6] = "world"; + void test() { + (void)A<hello>().get(); + (void)A<world>().get(); + } + + class X { + public: + X(); + X(int, int); + operator int() const; + }; + + template<X const *Ptr> struct A2; // expected-note{{template parameter is declared here}} + + X *X_ptr; + X an_X; + X array_of_Xs[10]; + 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-warning{{address non-type template argument cannot be surrounded by parentheses}} + + // PR6244 + struct X1 {} X1v; + template <X1*> struct X2 { }; + template <X1* Value> struct X3 : X2<Value> { }; + struct X4 : X3<&X1v> { }; + + // PR6563 + int *bar; + template <int *> struct zed {}; // expected-note 2{{template parameter is declared here}} + void g(zed<bar>*); // expected-error{{must have its address taken}} + + int baz; + void g2(zed<baz>*); // expected-error{{must have its address taken}} + + void g3(zed<&baz>*); // okay +} + +// -- For a non-type template-parameter of type reference to object, no +// conversions apply. The type referred to by the reference may be more +// cv-qualified than the (otherwise identical) type of the +// template-argument. The template-parameter is bound directly to the +// template-argument, which shall be an lvalue. +namespace reference_parameters { + template <int& N> struct S0 { }; // expected-note 3 {{template parameter is declared here}} + template <const int& N> struct S1 { }; // expected-note 2 {{template parameter is declared here}} + template <volatile int& N> struct S2 { }; // expected-note 2 {{template parameter is declared here}} + template <const volatile int& N> struct S3 { }; + int i; + extern const int ci; + volatile int vi; + 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 '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 '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 '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 'volatile int &' to template argument of type 'const volatile int' ignores qualifiers}} + + S3<i> s3; + S3<ci> s3c; + S3<vi> s3v; + S3<cvi> s3cv; + } + + namespace PR6250 { + template <typename T, const T &ref> void inc() { + ref++; // expected-error{{read-only variable is not assignable}} + } + + template<typename T, const T &ref> void bind() { + T &ref2 = ref; // expected-error{{drops qualifiers}} + } + + int counter; + void test() { + inc<int, counter>(); // expected-note{{instantiation of}} + bind<int, counter>(); // expected-note{{instantiation of}} + } + } + + namespace PR6749 { + template <int& i> struct foo {}; // expected-note{{template parameter is declared here}} + int x, &y = x; + foo<y> f; // expected-error{{is not an object}} + } +} + +// -- For a non-type template-parameter of type pointer to function, the +// function-to-pointer conversion (4.3) is applied; if the +// template-argument is of type std::nullptr_t, the null pointer +// conversion (4.10) is applied. If the template-argument represents +// a set of overloaded functions (or a pointer to such), the matching +// function is selected from the set (13.4). +namespace pointer_to_function { + template<int (*)(int)> struct X0 { }; // expected-note 3{{template parameter is declared here}} + int f(int); + int f(float); + int g(float); + int (*funcptr)(int); + void x0a(X0<f>); + void x0b(X0<&f>); + void x0c(X0<g>); // expected-error{{non-type template argument of type 'int (float)' cannot be converted to a value of type 'int (*)(int)'}} + void x0d(X0<&g>); // expected-error{{non-type template argument of type 'int (*)(float)' cannot be converted to a value of type 'int (*)(int)'}} + void x0e(X0<funcptr>); // expected-error{{must have its address taken}} +} + +// -- For a non-type template-parameter of type reference to function, no +// conversions apply. If the template-argument represents a set of +// overloaded functions, the matching function is selected from the set +// (13.4). +namespace reference_to_function { + template<int (&)(int)> struct X0 { }; // expected-note 4{{template parameter is declared here}} + int f(int); + int f(float); + int g(float); + int (*funcptr)(int); + void x0a(X0<f>); + void x0b(X0<&f>); // expected-error{{address taken in non-type template argument for template parameter of reference type 'int (&)(int)'}} + void x0c(X0<g>); // expected-error{{non-type template parameter of reference type 'int (&)(int)' cannot bind to template argument of type 'int (float)'}} + void x0d(X0<&g>); // expected-error{{address taken in non-type template argument for template parameter of reference type 'int (&)(int)'}} + void x0e(X0<funcptr>); // expected-error{{non-type template parameter of reference type 'int (&)(int)' cannot bind to template argument of type 'int (*)(int)'}} +} +// -- For a non-type template-parameter of type pointer to member function, +// if the template-argument is of type std::nullptr_t, the null member +// pointer conversion (4.11) is applied; otherwise, no conversions +// apply. If the template-argument represents a set of overloaded member +// functions, the matching member function is selected from the set +// (13.4). +namespace pointer_to_member_function { + struct X { }; + struct Y : X { + int f(int); + int g(int); + int g(float); + float h(float); + }; + + template<int (Y::*)(int)> struct X0 {}; // expected-note{{template parameter is declared here}} + X0<&Y::f> x0a; + X0<&Y::g> x0b; + X0<&Y::h> x0c; // expected-error{{non-type template argument of type 'float (pointer_to_member_function::Y::*)(float)' cannot be converted to a value of type 'int (pointer_to_member_function::Y::*)(int)'}} +} + +// -- For a non-type template-parameter of type pointer to data member, +// qualification conversions (4.4) are applied; if the template-argument +// is of type std::nullptr_t, the null member pointer conversion (4.11) +// is applied. +namespace pointer_to_member_data { + struct X { int x; }; + struct Y : X { int y; }; + + template<int Y::*> struct X0 {}; // expected-note{{template parameter is declared here}} + X0<&Y::y> x0a; + X0<&Y::x> x0b; // expected-error{{non-type template argument of type 'int pointer_to_member_data::X::*' cannot be converted to a value of type 'int pointer_to_member_data::Y::*'}} + + // Test qualification conversions + template<const int Y::*> struct X1 {}; + X1<&Y::y> x1a; +} diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp new file mode 100644 index 0000000..1c13bff --- /dev/null +++ b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp new file mode 100644 index 0000000..b03ed46 --- /dev/null +++ b/clang/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +// C++03 imposed restrictions in this paragraph that were lifted with 0x, so we +// just test that the example given now parses cleanly. + +template <class T> class X { }; +template <class T> void f(T t) { } +struct { } unnamed_obj; +void f() { + struct A { }; + enum { e1 }; + typedef struct { } B; + B b; + X<A> x1; + X<A*> x2; + X<B> x3; + f(e1); + f(unnamed_obj); + f(b); +} diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp new file mode 100644 index 0000000..0fd9a7e --- /dev/null +++ b/clang/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/clang/test/CXX/temp/temp.decls/p3.cpp b/clang/test/CXX/temp/temp.decls/p3.cpp new file mode 100644 index 0000000..41811ff --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/p3.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<typename T> using A = int; +template<typename T> using A<T*> = char; // expected-error {{partial specialization of alias templates is not permitted}} +template<> using A<char> = char; // expected-error {{explicit specialization of alias templates is not permitted}} +template using A<char> = char; // expected-error {{explicit instantiation of alias templates is not permitted}} +using A<char> = char; // expected-error {{name defined in alias declaration must be an identifier}} diff --git a/clang/test/CXX/temp/temp.decls/temp.alias/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.alias/p1.cpp new file mode 100644 index 0000000..966e3c1 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.alias/p1.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<typename T> using U = T; + +// The name of the alias template is a template-name. +U<char> x; +void f(U<int>); +typedef U<U<U<U<int>>>> I; diff --git a/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp new file mode 100644 index 0000000..a5b39fe --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.alias/p2.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template<typename T> using U = T; + +using I = U<U<U<U<int>>>>; +using I = int; + +template<typename A, typename B> using Fst = A; +template<typename A, typename B> using Snd = B; + +using I = Fst<Snd<char,int>,double>; + +namespace StdExample { + // Prerequisites for example. + template<class T, class A> struct vector { /* ... */ }; + + + template<class T> struct Alloc {}; + template<class T> using Vec = vector<T, Alloc<T>>; + Vec<int> v; + + template<class T> + void process(Vec<T>& v) // expected-note {{previous definition is here}} + { /* ... */ } + + template<class T> + void process(vector<T, Alloc<T>>& w) // expected-error {{redefinition of 'process'}} + { /* ... */ } + + template<template<class> class TT> + void f(TT<int>); // expected-note {{candidate template ignored}} + + template<template<class,class> class TT> + void g(TT<int, Alloc<int>>); + + int h() { + f(v); // expected-error {{no matching function for call to 'f'}} + g(v); // OK: TT = vector + } + + + // v's type is same as vector<int, Alloc<int>>. + using VTest = vector<int, Alloc<int>>; + using VTest = decltype(v); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp b/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp new file mode 100644 index 0000000..afd9b4b --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// The example given in the standard (this is rejected for other reasons anyway). +template<class T> struct A; +template<class T> using B = typename A<T>::U; // expected-error {{no type named 'U' in 'A<T>'}} +template<class T> struct A { + typedef B<T> U; // expected-note {{in instantiation of template type alias 'B' requested here}} +}; +B<short> b; + +template<typename T> using U = int; +// FIXME: This is illegal, but probably only because CWG1044 missed this paragraph. +template<typename T> using U = U<T>; diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp new file mode 100644 index 0000000..d0fc797 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp @@ -0,0 +1,76 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Test class template partial specializations of member templates. +template<typename T> +struct X0 { + template<typename U> struct Inner0 { + static const unsigned value = 0; + }; + + template<typename U> struct Inner0<U*> { + static const unsigned value = 1; + }; +}; + +template<typename T> template<typename U> +struct X0<T>::Inner0<const U*> { + static const unsigned value = 2; +}; + +int array0[X0<int>::Inner0<int>::value == 0? 1 : -1]; +int array1[X0<int>::Inner0<int*>::value == 1? 1 : -1]; +int array2[X0<int>::Inner0<const int*>::value == 2? 1 : -1]; + +// Make sure we can provide out-of-line class template partial specializations +// for member templates (and instantiate them). +template<class T> struct A { + struct C { + template<class T2> struct B; + }; +}; + +// partial specialization of A<T>::C::B<T2> +template<class T> template<class T2> struct A<T>::C::B<T2*> { }; + +A<short>::C::B<int*> absip; + +// Check for conflicts during template instantiation. +template<typename T, typename U> +struct Outer { + template<typename X, typename Y> struct Inner; + template<typename Y> struct Inner<T, Y> {}; // expected-note{{previous}} + template<typename Y> struct Inner<U, Y> {}; // expected-error{{cannot be redeclared}} +}; + +Outer<int, int> outer; // expected-note{{instantiation}} + +// Test specialization of class template partial specialization members. +template<> template<typename Z> +struct X0<float>::Inner0<Z*> { + static const unsigned value = 3; +}; + +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/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp new file mode 100644 index 0000000..aa1e2d4 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp new file mode 100644 index 0000000..b754368 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/p9-0x.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.decls/temp.class.spec/p9.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/p9.cpp new file mode 100644 index 0000000..2a3e914 --- /dev/null +++ b/clang/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/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.order/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.order/p2.cpp new file mode 100644 index 0000000..97457ea --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.order/p2.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<int I, int J, class T> struct X { + static const int value = 0; +}; + +template<int I, int J> struct X<I, J, int> { + static const int value = 1; +}; + +template<int I> struct X<I, I, int> { + static const int value = 2; +}; + +int array0[X<0, 0, float>::value == 0? 1 : -1]; +int array1[X<0, 1, int>::value == 1? 1 : -1]; +int array2[X<0, 0, int>::value == 2? 1 : -1]; + +namespace DependentSubstPartialOrdering { + template<typename T, typename U = void, typename V = void> + struct X { + static const unsigned value = 1; + }; + + template<typename T, typename U> + struct X<T, U, typename T::is_b> { + static const unsigned value = 2; + }; + + template<typename T> + struct X<T, typename T::is_a, typename T::is_b> { + static const unsigned value = 3; + }; + + struct X1 { }; + + struct X2 { + typedef void is_b; + }; + + struct X3 { + typedef void is_a; + typedef void is_b; + }; + + int check_X1[X<X1, void, void>::value == 1? 1 : -1]; + int check_X2[X<X2, void, void>::value == 2? 1 : -1]; + int check_X3[X<X3, void, void>::value == 3? 1 : -1]; +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp new file mode 100644 index 0000000..59253db --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T, int N> +struct A; + +template<typename T> // expected-note{{previous template declaration}} +struct A<T*, 2> { + void f0(); + void f1(); + void f2(); +}; + +template<> +struct A<int, 1> { + void g0(); +}; + +// FIXME: We should probably give more precise diagnostics here, but the +// diagnostics we give aren't terrible. +// FIXME: why not point to the first parameter that's "too many"? +template<typename T, int N> // expected-error{{too many template parameters}} +void A<T*, 2>::f0() { } + +template<typename T, int N> +void A<T, N>::f1() { } // expected-error{{out-of-line definition}} diff --git a/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp new file mode 100644 index 0000000..87e21e4 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T, int N> +struct A; + +template<typename T> +struct A<T*, 2> { + A(T); + ~A(); + + void f(T*); + + operator T*(); + + static T value; +}; + +template<class X> void A<X*, 2>::f(X*) { } + +template<class X> X A<X*, 2>::value; + +template<class X> A<X*, 2>::A(X) { value = 0; } + +template<class X> A<X*, 2>::~A() { } + +template<class X> A<X*, 2>::operator X*() { return 0; } diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp new file mode 100644 index 0000000..b65e1d0 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T, typename U> +struct X0 { + struct Inner; +}; + +template<typename T, typename U> +struct X0<T, U>::Inner { + T x; + U y; + + void f() { x = y; } // expected-error{{incompatible}} +}; + + +void test(int i, float f) { + X0<int, float>::Inner inner; + inner.x = 5; + inner.y = 3.4; + inner.f(); + + X0<int*, float *>::Inner inner2; + inner2.x = &i; + inner2.y = &f; + inner2.f(); // expected-note{{instantiation}} +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.enum/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.enum/p1.cpp new file mode 100644 index 0000000..f8cc009 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.enum/p1.cpp @@ -0,0 +1,152 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +template<typename T> struct A { + enum E : T; // expected-note {{here}} + E v; + E f() { return A::e1; } // expected-error {{no member named 'e1' in 'A<T>'}} + E g() { return E::e1; } + E h(); +}; + +A<int> a; +A<int>::E a0 = A<int>().v; +int n = A<int>::E::e1; // expected-error {{implicit instantiation of undefined member}} + +template<typename T> enum A<T>::E : T { e1, e2 }; + +// FIXME: Now that A<T>::E is defined, we are supposed to inject its enumerators +// into the already-instantiated class A<T>. This seems like a really bad idea, +// though, so we don't implement that, but what we do implement is inconsistent. +// +// Either do as the standard says, or only include enumerators lexically defined +// within the class in its scope. +A<int>::E a1 = A<int>::e1; // expected-error {{no member named 'e1' in 'A<int>'}} + +A<char>::E a2 = A<char>::e2; + +template<typename T> typename A<T>::E A<T>::h() { return e2; } +A<short>::E a3 = A<short>().h(); + + +template<typename T> struct B { + enum class E; + E v; + E f() { return E::e1; } + E g(); +}; + +B<int> b; +B<int>::E b0 = B<int>().v; + +template<typename T> enum class B<T>::E { e1, e2 }; +B<int>::E b1 = B<int>::E::e1; + +B<char>::E b2 = B<char>::E::e2; + +template<typename T> typename B<T>::E B<T>::g() { return e2; } +B<short>::E b3 = B<short>().g(); + + +// Enumeration members of class templates can be explicitly specialized. For +// unscoped enumerations, specializations must be defined before the primary +// template is, since otherwise the primary template will be implicitly +// instantiated when we parse the nested name specifier. +template<> enum A<long long>::E : long long { e3, e4 }; // expected-error {{explicit specialization of 'E' after instantiation}} expected-note {{first required here}} + +template<> enum class B<long long>::E { e3, e4 }; +B<long long>::E b4 = B<long long>::E::e4; + +B<long>::E b5; +template<> enum class B<long>::E { e5 }; +void fb5() { b5 = decltype(b5)::e5; } +B<long>::E b6 = B<long>::E::e5; + + +template<typename T> struct C { + enum class E : T; +}; + +template<> enum class C<long long>::E : long long { e3, e4 }; +C<long long>::E c0 = C<long long>::E::e3; + +C<long>::E c1; +template<> enum class C<long>::E : long { e5 }; +void fc1() { c1 = decltype(c1)::e5; } +C<long>::E c2 = C<long>::E::e5; + +template<> enum class C<int>::E : int { e6 }; +template<typename T> enum class C<T>::E : T { e0 }; +C<int>::E c3 = C<int>::E::e6; +C<int>::E c4 = C<int>::E::e0; // expected-error {{no member named 'e0' in 'C<int>::E'}} + + +// Enumeration members can't be partially-specialized. +template<typename T> enum class B<T*>::E { e5, e6 }; // expected-error {{nested name specifier for a declaration cannot depend on a template parameter}} + + +// Explicit specializations can be forward-declared. +template<typename T> +struct D { + enum class E { e1 }; +}; +template<> enum class D<int>::E; +D<int>::E d1 = D<int>::E::e1; // expected-error {{incomplete type 'D<int>::E'}} +template<> enum class D<int>::E { e2 }; +D<int>::E d2 = D<int>::E::e2; +D<char>::E d3 = D<char>::E::e1; // expected-note {{first required here}} +D<char>::E d4 = D<char>::E::e2; // expected-error {{no member named 'e2'}} +template<> enum class D<char>::E { e3 }; // expected-error {{explicit specialization of 'E' after instantiation}} + +template<> enum class D<short>::E; +struct F { + // Per C++11 [class.friend]p3, these friend declarations have no effect. + // Only classes and functions can be friends. + template<typename T> friend enum D<T>::E; + template<> friend enum D<short>::E; + + template<> friend enum D<double>::E { e3 }; // expected-error {{cannot define a type in a friend declaration}} + +private: + static const int n = 1; // expected-note {{private here}} +}; +template<> enum class D<short>::E { + e = F::n // expected-error {{private member}} +}; + +class Access { + friend class X; + + template<typename T> + class Priv { + friend class X; + + enum class E : T; + }; + + class S { + typedef int N; // expected-note {{here}} + static const int k = 3; // expected-note {{here}} + + friend class Priv<char>; + }; + + static const int k = 5; +}; + +template<> enum class Access::Priv<Access::S::N>::E + : Access::S::N { // expected-error {{private member}} + a = Access::k, // ok + b = Access::S::k // expected-error {{private member}} +}; + +template<typename T> enum class Access::Priv<T>::E : T { + c = Access::k, + d = Access::S::k +}; + +class X { + Access::Priv<int>::E a = Access::Priv<int>::E::a; + Access::Priv<char>::E c = Access::Priv<char>::E::d; + // FIXME: We should see an access error for this enumerator. + Access::Priv<short>::E b = Access::Priv<short>::E::d; +}; diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1-retmem.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1-retmem.cpp new file mode 100644 index 0000000..4c05c62 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1-retmem.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> struct X1 { }; + +template<typename T> +struct X0 { + typedef int size_type; + typedef T value_type; + + size_type f0() const; + value_type *f1(); + X1<value_type*> f2(); +}; + +template<typename T> +typename X0<T>::size_type X0<T>::f0() const { + return 0; +} + +template<typename U> +typename X0<U>::value_type *X0<U>::f1() { + return 0; +}; + +template<typename U> +X1<typename X0<U>::value_type*> X0<U>::f2() { + return 0; +}; diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp new file mode 100644 index 0000000..1764563 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp @@ -0,0 +1,100 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T, typename U> // expected-note{{previous template}} +class X0 { +public: + typedef int size_type; + + X0(int); + ~X0(); + + void f0(const T&, const U&); + + T& operator[](int i) const; + + void f1(size_type) const; + void f2(size_type) const; + void f3(size_type) const; + void f4() ; + + operator T*() const; + + T value; +}; + +template<typename T, typename U> +void X0<T, U>::f0(const T&, const U&) { // expected-note{{previous definition}} +} + +template<class X, class Y> +X& X0<X, Y>::operator[](int i) const { + (void)i; + return value; +} + +template<class X, class Y> +void X0<X, Y>::f1(int) const { } + +template<class X, class Y> +void X0<X, Y>::f2(size_type) const { } + +template<class X, class Y, class Z> // expected-error{{too many template parameters}} +void X0<X, Y>::f3(size_type) const { +} + +template<class X, class Y> +void X0<Y, X>::f4() { } // expected-error{{does not refer}} + +// FIXME: error message should probably say, "redefinition of 'X0<T, U>::f0'" +// rather than just "redefinition of 'f0'" +template<typename T, typename U> +void X0<T, U>::f0(const T&, const U&) { // expected-error{{redefinition}} +} + +// Test out-of-line constructors, destructors +template<typename T, typename U> +X0<T, U>::X0(int x) : value(x) { } + +template<typename T, typename U> +X0<T, U>::~X0() { } + +// Test out-of-line conversion functions. +template<typename T, typename U> +X0<T, U>::operator T*() const { + return &value; +} + +namespace N { template <class X> class A {void a();}; } +namespace N { template <class X> void A<X>::a() {} } + +// PR5566 +template<typename T> +struct X1 { + template<typename U> + struct B { void f(); }; +}; + +template<typename T> +template<typename U> +void X1<T>::template B<U>::f() { } + +// PR5527 +template <template <class> class T> +class X2 { + template <class F> + class Bar { + void Func(); + }; +}; + +template <template <class> class T> +template <class F> +void X2<T>::Bar<F>::Func() {} + +// PR5528 +template <template <class> class T> +class X3 { + void F(); +}; + +template <template <class> class T> +void X3<T>::F() {} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp new file mode 100644 index 0000000..f09faa9 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// Test instantiation of member functions of class templates defined out-of-line +template<typename T, typename U> +struct X0 { + void f(T *t, const U &u); + void f(T *); +}; + +template<typename T, typename U> +void X0<T, U>::f(T *t, const U &u) { + *t = u; // expected-error{{not assignable}} +} + +void test_f(X0<float, int> xfi, X0<void, int> xvi, float *fp, void *vp, int i) { + xfi.f(fp, i); + xvi.f(vp, i); // expected-note{{instantiation}} +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/pr5056.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/pr5056.cpp new file mode 100644 index 0000000..70c9c70 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.mem.func/pr5056.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +extern "C" void * malloc(int); + +template <typename T> struct A { + void *malloc(int); +}; + +template <typename T> +inline void *A<T>::malloc(int) +{ + return 0; +} + +void f() { + malloc(10); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1-inst.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1-inst.cpp new file mode 100644 index 0000000..9fc4a58 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1-inst.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Test instantiation of static data members declared out-of-line. + +template<typename T> +struct X { + static T value; +}; + +template<typename T> + T X<T>::value = 17; // expected-error{{no viable conversion}} + +struct InitOkay { + InitOkay(int) { } +}; + +struct CannotInit { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}} + +int &returnInt() { return X<int>::value; } +float &returnFloat() { return X<float>::value; } + +InitOkay &returnInitOkay() { return X<InitOkay>::value; } + +unsigned long sizeOkay() { return sizeof(X<CannotInit>::value); } + +CannotInit &returnError() { + return X<CannotInit>::value; // expected-note{{instantiation}} +} diff --git a/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp new file mode 100644 index 0000000..2eae112 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X0 { + static T value; +}; + +template<typename T> +T X0<T>::value = 0; // expected-error{{no viable conversion}} + +struct X1 { + X1(int); +}; + +struct X2 { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}} + +int& get_int() { return X0<int>::value; } +X1& get_X1() { return X0<X1>::value; } + +double*& get_double_ptr() { return X0<int*>::value; } // expected-error{{non-const lvalue reference to type 'double *' cannot bind to a value of unrelated type 'int *'}} + +X2& get_X2() { + return X0<X2>::value; // expected-note{{instantiation}} +} + +template<typename T> T x; // expected-error{{variable 'x' declared as a template}} diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3-0x.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3-0x.cpp new file mode 100644 index 0000000..63909fb --- /dev/null +++ b/clang/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++11 %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/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p3.cpp new file mode 100644 index 0000000..2ffdd95 --- /dev/null +++ b/clang/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/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p4.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p4.cpp new file mode 100644 index 0000000..b2a6219 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p4.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class T> struct A { A(); }; +template<class T> int &f(T); +template<class T> float &f(T*); +template<class T> double &f(const T*); + +template<class T> void g(T); // expected-note{{candidate}} +template<class T> void g(T&); // expected-note{{candidate}} + +template<class T> int &h(const T&); +template<class T> float &h(A<T>&); + +void m() { + const int *p; + double &dr1 = f(p); + float x; + g(x); // expected-error{{ambiguous}} + A<int> z; + float &fr1 = h(z); + const A<int> z2; + int &ir1 = h(z2); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p5.cpp new file mode 100644 index 0000000..4d34968 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p5.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T> int &f(T); +template<class T> float &f(T*, int=1); + +template<class T> int &g(T); +template<class T> float &g(T*, ...); + +int main() { + int* ip; + float &fr1 = f(ip); + float &fr2 = g(ip); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp new file mode 100644 index 0000000..e9a3eaa --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> void f0(T) { } // expected-note{{previous}} +template<class U> void f0(U) { } // expected-error{{redefinition}} + +template<int I> void f0() { } // expected-note{{previous}} +template<int> void f0() { } // expected-error{{redefinition}} + +typedef int INT; + +template<template<class T, T Value1, INT> class X> + void f0() { } // expected-note{{previous}} +template<template<typename T, T Value1, int> class> + void f0() { } // expected-error{{redefinition}} + +template<typename T> +struct MetaFun; + +template<typename T> + typename MetaFun<T*>::type f0(const T&) { while (1) {} } // expected-note{{previous}} +template<class U> + typename MetaFun<U*>::type f0(const U&) { while (1) {} } // expected-error{{redefinition}} + +// FIXME: We need canonicalization of expressions for this to work +// template<int> struct A { }; +// template<int I> void f0(A<I>) { } // Xpected-note{{previous}} +// template<int J> void f0(A<J>) { } // Xpected-error{{redefinition}} diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4.cpp new file mode 100644 index 0000000..f42b94a --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// All of these function templates are distinct. +template<typename T> void f0(T) { } +template<typename T, typename U> void f0(T) { } +template<typename T, typename U> void f0(U) { } +void f0(); +template<typename T> void f0(T*); +void f0(int); +template<int I> void f0(); +template<typename T> void f0(); + + diff --git a/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp new file mode 100644 index 0000000..a668ada --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<int N, int M> +struct A0 { + void g0(); +}; + +template<int X, int Y> void f0(A0<X, Y>) { } // expected-note{{previous}} +template<int N, int M> void f0(A0<M, N>) { } +template<int V1, int V2> void f0(A0<V1, V2>) { } // expected-error{{redefinition}} + +template<int X, int Y> void f1(A0<0, (X + Y)>) { } // expected-note{{previous}} +template<int X, int Y> void f1(A0<0, (X - Y)>) { } +template<int A, int B> void f1(A0<0, (A + B)>) { } // expected-error{{redefinition}} + +template<int X, int Y> void A0<X, Y>::g0() { } diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp new file mode 100644 index 0000000..63f569b --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp @@ -0,0 +1,358 @@ +// RUN: %clang_cc1 -verify -emit-llvm-only %s + +namespace test0 { +template <typename T> struct Num { + T value_; + +public: + Num(T value) : value_(value) {} + T get() const { return value_; } + + template <typename U> struct Rep { + U count_; + Rep(U count) : count_(count) {} + + friend Num operator*(const Num &a, const Rep &n) { + Num x = 0; + for (U count = n.count_; count; --count) + x += a; + return x; + } + }; + + friend Num operator+(const Num &a, const Num &b) { + return a.value_ + b.value_; + } + + Num& operator+=(const Num& b) { + value_ += b.value_; + return *this; + } + + class Representation {}; + friend class Representation; +}; + +class A { + template <typename T> friend bool iszero(const A &a) throw(); +}; + +template <class T> class B_iterator; +template <class T> class B { + friend class B_iterator<T>; +}; + +int calc1() { + Num<int> left = -1; + Num<int> right = 1; + Num<int> result = left + right; + return result.get(); +} + +int calc2() { + Num<int> x = 3; + Num<int>::Rep<char> n = (char) 10; + Num<int> result = x * n; + return result.get(); +} +} + +// Reduced from GNU <locale> +namespace test1 { + class A { + bool b; // expected-note {{declared private here}} + template <typename T> friend bool has(const A&); + }; + template <typename T> bool has(const A &x) { + return x.b; + } + template <typename T> bool hasnot(const A &x) { + return x.b; // expected-error {{'b' is a private member of 'test1::A'}} + } +} + +namespace test2 { + class A { + bool b; // expected-note {{declared private here}} + template <typename T> friend class HasChecker; + }; + template <typename T> class HasChecker { + bool check(A *a) { + return a->b; + } + }; + template <typename T> class HasNotChecker { + bool check(A *a) { + return a->b; // expected-error {{'b' is a private member of 'test2::A'}} + } + }; +} + +namespace test3 { + class Bool; + template <class T> class User; + template <class T> T transform(class Bool, T); + + class Bool { + friend class User<bool>; + friend bool transform<>(Bool, bool); + + bool value; // expected-note 2 {{declared private here}} + }; + + template <class T> class User { + static T compute(Bool b) { + return b.value; // expected-error {{'value' is a private member of 'test3::Bool'}} + } + }; + + template <class T> T transform(Bool b, T value) { + if (b.value) // expected-error {{'value' is a private member of 'test3::Bool'}} + return value; + return value + 1; + } + + template bool transform(Bool, bool); + template int transform(Bool, int); // expected-note {{requested here}} + + template class User<bool>; + template class User<int>; // expected-note {{requested here}} +} + +namespace test4 { + template <class T> class A { + template <class T0> friend class B; + bool foo(const A<T> *) const; + }; + + template <class T> class B { + bool bar(const A<T> *a, const A<T> *b) { + return a->foo(b); + } + }; + + template class B<int>; +} + +namespace test5 { + template <class T, class U=int> class A {}; + template <class T> class B { + template <class X, class Y> friend class A; + }; + template class B<int>; + template class A<int>; +} + +namespace Dependent { + template<typename T, typename Traits> class X; + template<typename T, typename Traits> + X<T, Traits> operator+(const X<T, Traits>&, const T*); + + template<typename T, typename Traits> class X { + typedef typename Traits::value_type value_type; + friend X operator+<>(const X&, const value_type*); + }; +} + +namespace test7 { + template <class T> class A { // expected-note {{declared here}} + friend class B; + int x; // expected-note {{declared private here}} + }; + + class B { + int foo(A<int> &a) { + return a.x; + } + }; + + class C { + int foo(A<int> &a) { + return a.x; // expected-error {{'x' is a private member of 'test7::A<int>'}} + } + }; + + // This shouldn't crash. + template <class T> class D { + friend class A; // expected-error {{elaborated type refers to a template}} + }; + template class D<int>; +} + +namespace test8 { + template <class N> class A { + static int x; + template <class T> friend void foo(); + }; + template class A<int>; + + template <class T> void foo() { + A<int>::x = 0; + } + template void foo<int>(); +} + +namespace test9 { + template <class T> class A { + class B; class C; + + int foo(B *b) { + return b->x; + } + + int foo(C *c) { + return c->x; // expected-error {{'x' is a private member}} + } + + class B { + int x; + friend int A::foo(B*); + }; + + class C { + int x; // expected-note {{declared private here}} + }; + }; + + template class A<int>; // expected-note {{in instantiation}} +} + +namespace test10 { + template <class T> class A; + template <class T> A<T> bar(const T*, const A<T>&); + template <class T> class A { + private: + void foo(); // expected-note {{declared private here}} + friend A bar<>(const T*, const A<T>&); + }; + + template <class T> A<T> bar(const T *l, const A<T> &r) { + A<T> l1; + l1.foo(); + + A<char> l2; + l2.foo(); // expected-error {{'foo' is a private member of 'test10::A<char>'}} + + return l1; + } + + template A<int> bar<int>(const int *, const A<int> &); // expected-note {{in instantiation}} +} + +// PR6752: this shouldn't crash. +namespace test11 { + struct Foo { + template<class A> + struct IteratorImpl { + template<class T> friend class IteratorImpl; + }; + }; + + template struct Foo::IteratorImpl<int>; + template struct Foo::IteratorImpl<long>; +} + +// PR6827 +namespace test12 { + template <typename T> class Foo; + template <typename T> Foo<T> foo(T* t){ return Foo<T>(t, true); } + + template <typename T> class Foo { + public: + Foo(T*); + friend Foo<T> foo<T>(T*); + private: + Foo(T*, bool); // expected-note {{declared private here}} + }; + + // Should work. + int globalInt; + Foo<int> f = foo(&globalInt); + + // Shouldn't work. + long globalLong; + template <> Foo<long> foo(long *t) { + Foo<int> s(&globalInt, false); // expected-error {{calling a private constructor}} + return Foo<long>(t, true); + } +} + +// PR6514 +namespace test13 { + template <int N, template <int> class Temp> + class Role : public Temp<N> { + friend class Temp<N>; + int x; + }; + + template <int N> class Foo { + void foo(Role<N, test13::Foo> &role) { + (void) role.x; + } + }; + + 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}} +} + +namespace PR10913 { + template<class T> class X; + + template<class T> void f(X<T> *x) { + x->member = 0; + } + + template<class U, class T> void f2(X<T> *x) { + x->member = 0; // expected-error{{'member' is a protected member of 'PR10913::X<int>'}} + } + + template<class T> class X { + friend void f<T>(X<T> *x); + friend void f2<T>(X<int> *x); + + protected: + int member; // expected-note{{declared protected here}} + }; + + template void f(X<int> *); + template void f2<int>(X<int> *); + template void f2<float>(X<int> *); // expected-note{{in instantiation of function template specialization 'PR10913::f2<float, int>' requested here}} +} diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p3.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p3.cpp new file mode 100644 index 0000000..0b2a25e --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.friend/p3.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <class T> class A { + typedef int Member; +}; + +class B { + template <class T> friend class A; + template <class T> friend class Undeclared; + + template <class T> friend typename A<T>::Member; // expected-error {{friend type templates must use an elaborated type}} +}; diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p4.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p4.cpp new file mode 100644 index 0000000..e036cef --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.friend/p4.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X1 { + friend void f6(int) { } // expected-error{{redefinition of}} \ + // expected-note{{previous definition}} +}; + +X1<int> x1a; +X1<float> x1b; // expected-note {{in instantiation of}} + +template<typename T> +struct X2 { + operator int(); + + friend void f(int x) { } // expected-error{{redefinition}} \ + // expected-note{{previous definition}} +}; + +int array0[sizeof(X2<int>)]; +int array1[sizeof(X2<float>)]; // expected-note{{instantiation of}} + +void g() { + X2<int> xi; + f(xi); + X2<float> xf; + f(xf); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp new file mode 100644 index 0000000..63fd3df --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp @@ -0,0 +1,103 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test0 { + template <class T> class A { + class 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(); + }; + + template <class> struct B {}; + template class A<B>; +} diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p8.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p8.cpp new file mode 100644 index 0000000..d0221a3 --- /dev/null +++ b/clang/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/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp new file mode 100644 index 0000000..f5f1205 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.mem/p1.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <class T> struct A { + static T cond; + + template <class U> struct B { + static T twice(U value) { + return (cond ? value + value : value); + } + }; +}; + +int foo() { + A<bool>::cond = true; + return A<bool>::B<int>::twice(4); +} + +namespace PR6376 { + template<typename T> + struct X { + template<typename Y> + struct Y1 { }; // + }; + + template<> + struct X<float> { + template<typename Y> + struct Y1 { }; + }; + + template<typename T, typename U> + struct Z : public X<T>::template Y1<U> { }; + + Z<float, int> z0; +} diff --git a/clang/test/CXX/temp/temp.decls/temp.mem/p3.cpp b/clang/test/CXX/temp/temp.decls/temp.mem/p3.cpp new file mode 100644 index 0000000..0eb747b --- /dev/null +++ b/clang/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/clang/test/CXX/temp/temp.decls/temp.mem/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.mem/p5.cpp new file mode 100644 index 0000000..8bcd773 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.mem/p5.cpp @@ -0,0 +1,79 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A { + template <class T> operator T*(); +}; + +template <class T> A::operator T*() { return 0; } +template <> A::operator char*(){ return 0; } // specialization +template A::operator void*(); // explicit instantiation + +int main() { + A a; + int *ip; + ip = a.operator int*(); +} + +// PR5742 +namespace PR5742 { + template <class T> struct A { }; + template <class T> struct B { }; + + struct S { + template <class T> operator T(); + } s; + + void f() { + s.operator A<A<int> >(); + s.operator A<B<int> >(); + s.operator A<B<A<int> > >(); + } +} + +// PR5762 +class Foo { + public: + template <typename T> operator T(); + + template <typename T> + T As() { + return this->operator T(); + } + + template <typename T> + T As2() { + return operator T(); + } + + int AsInt() { + return this->operator int(); + } +}; + +template float Foo::As(); +template double Foo::As2(); + +// Partial ordering with conversion function templates. +struct X0 { + template<typename T> operator T*() { + T x = 1; + x = 17; // expected-error{{read-only variable is not assignable}} + } + + template<typename T> operator T*() const; // expected-note{{explicit instantiation refers here}} + + template<typename T> operator const T*() const { + T x = T(); + return x; // expected-error{{cannot initialize return object of type 'const char *' with an lvalue of type 'char'}} \ + // expected-error{{cannot initialize return object of type 'const int *' with an lvalue of type 'int'}} + } +}; + +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) { + x0.operator const int*(); // expected-note{{in instantiation of function template specialization}} + x0.operator float *(); + x0c.operator const char*(); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp new file mode 100644 index 0000000..fec8060 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp new file mode 100644 index 0000000..db28eea --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/example-bind.cpp @@ -0,0 +1,352 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.decls/temp.variadic/example-function.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/example-function.cpp new file mode 100644 index 0000000..e15203a --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/example-function.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp new file mode 100644 index 0000000..9de5fa8 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/example-tuple.cpp @@ -0,0 +1,260 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp new file mode 100644 index 0000000..6d9d8c5 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/ext-blocks.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -std=c++11 -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); + +template<typename ...Args> +int PR9953(Args ...args) { + return ^(Args *...block_args) { + return f1(block_args); // expected-error{{expression contains unexpanded parameter pack 'block_args'}} + }(&args...); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp new file mode 100644 index 0000000..fb72754 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp @@ -0,0 +1,127 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +template<typename T, typename U> struct pair { }; +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; +}; + +namespace ExpandIntoFixed { + template<typename T, + typename U, + typename V = pair<T, U>, + typename W = V*> + class X0 { }; + + template<typename ...Ts> + class X1 { + public: + typedef X0<Ts...> type; + }; + + static_assert(is_same<X1<int, int>::type, + X0<int, int, pair<int, int>, pair<int, int>*>>::value, + "fails with two default arguments"); + + static_assert(is_same<X1<int, int, float>::type, + X0<int, int, float, float*>>::value, + "fails with one default argument"); + + static_assert(is_same<X1<int, int, float, double>::type, + X0<int, int, float, double>>::value, + "fails with no default arguments"); +} + +namespace ExpandIntoFixedShifted { + template<typename T, + typename U, + typename V = pair<T, U>, + typename W = V*> + class X0 { }; + + template<typename ...Ts> + class X1 { + public: + typedef X0<char, Ts...> type; + }; + + static_assert(is_same<X1<int>::type, + X0<char, int, pair<char, int>, pair<char, int>*>>::value, + "fails with two default arguments"); + + static_assert(is_same<X1<int, float>::type, + X0<char, int, float, float*>>::value, + "fails with one default argument"); + + static_assert(is_same<X1<int, float, double>::type, + X0<char, int, float, double>>::value, + "fails with no default arguments"); +} + +namespace Deduction { + template <typename X, typename Y = double> struct Foo {}; + template <typename ...Args> tuple<Args...> &foo(Foo<Args...>); + + void call_foo(Foo<int, float> foo_if, Foo<int> foo_i) { + tuple<int, float> &t1 = foo(foo_if); + tuple<int, double> &t2 = foo(foo_i); + } +} + +namespace PR9021a { + template<typename, typename> + struct A { }; + + template<typename ...T> + struct B { + A<T...> a1; + }; + + void test() { + B<int, int> c; + } +} + +namespace PR9021b { + template<class, class> + struct t2 + { + + }; + + template<template<class...> class M> + struct m + { + template<class... B> + using inner = M<B...>; + }; + + m<t2> sta2; +} + +namespace PartialSpecialization { + template<typename T, typename U, typename V = U> + struct X0; // expected-note{{template is declared here}} + + template<typename ...Ts> + struct X0<Ts...> { + }; + + X0<int> x0i; // expected-error{{too few template arguments for class template 'X0'}} + X0<int, float> x0if; + X0<int, float, double> x0ifd; +} + +namespace FixedAliasTemplate { + template<typename,typename,typename> struct S {}; + template<typename T, typename U> using U = S<T, int, U>; + template<typename...Ts> U<Ts...> &f(U<Ts...>, Ts...); + S<int, int, double> &s1 = f({}, 0, 0.0); +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp new file mode 100644 index 0000000..b5786ac --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp new file mode 100644 index 0000000..73cbd07 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp @@ -0,0 +1,274 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp new file mode 100644 index 0000000..21aa24f --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp @@ -0,0 +1,251 @@ +// RUN: %clang_cc1 -std=c++11 -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'}} +} + +namespace ExpandingFunctionParameters { + template<typename ...T> + struct X0 { + typedef int type; + }; + + template<typename ...T> + struct X1 { + template<typename ... U> + typename X0<T(T, U...)...>::type f(U...); + }; + + void test() { + X1<float> x1; + x1.f(17, 3.14159); + } +} + +namespace PR10230 { + template<typename> + struct s + { + template<typename... Args> + auto f() -> int(&)[sizeof...(Args)]; + }; + + void main() + { + int (&ir1)[1] = s<int>().f<int>(); + int (&ir3)[3] = s<int>().f<int, float, double>(); + } +} diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p1.cpp new file mode 100644 index 0000000..daff9d1 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p1.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.decls/temp.variadic/p2.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p2.cpp new file mode 100644 index 0000000..ce19582 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p2.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp new file mode 100644 index 0000000..d8294a1 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp @@ -0,0 +1,193 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fexceptions -fcxx-exceptions -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 a function parameter pack, the pattern is the parameter-declaration +// without the ellipsis. +namespace PR11850 { + template<typename ...T> struct S { + int f(T...a, int b) { return b; } + }; + S<> s; + S<int*, char, const double&> t; + int k = s.f(0); + int l = t.f(&k, 'x', 5.9, 4); + + template<typename ...As> struct A { + template<typename ...Bs> struct B { + template<typename ...Cs> struct C { + C(As..., Bs..., int &k, Cs...); + }; + }; + }; + A<>::B<>::C<> c000(k); + A<int>::B<>::C<int> c101(1, k, 3); + A<>::B<int>::C<int> c011(1, k, 3); + A<int>::B<int>::C<> c110(1, 2, k); + A<int, int>::B<int, int>::C<int, int> c222(1, 2, 3, 4, k, 5, 6); + A<int, int, int>::B<>::C<> c300(1, 2, 3, k); + + int &f(); + char &f(void*); + template<typename ...A> struct U { + template<typename ...B> struct V { + auto g(A...a, B...b) -> decltype(f(a...)); + }; + }; + U<>::V<int*> v0; + U<int*>::V<> v1; + int &v0f = v0.g(0); + char &v1f = v1.g(0); +} +namespace PR12096 { + void Foo(int) {} + void Foo(int, int) = delete; + template<typename ...Args> struct Var { + Var(const Args &...args, int *) { Foo(args...); } + }; + Var<int> var(1, 0); +} + +// 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) { + // An empty expression-list performs value initialization. + constexpr 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 move constructor) not viable: no known conversion from 'int' to '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'}} +}; + +// There was a bug in the delayed parsing code for the +// following case. +template<typename ...T> +struct DelayedParseTest : T... +{ + int a; + DelayedParseTest(T... i) : T{i}..., a{10} {} +}; + + +// 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/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp new file mode 100644 index 0000000..726e222 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp @@ -0,0 +1,403 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++11 -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. +template<typename T, typename... Types> +// FIXME: this should test that the diagnostic reads "type contains..." +struct alignas(Types) TestUnexpandedDecls : T{ // expected-error{{expression contains unexpanded parameter pack 'Types'}} + void member_function(Types); // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + void member_function () throw(Types); // expected-error{{exception 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{{initializer contains unexpanded parameter pack 'Types'}} + T list_init = { static_cast<Types>(0) }; // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + } + + T in_class_member_init = static_cast<Types>(0); // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + TestUnexpandedDecls() : + Types(static_cast<Types>(0)), // expected-error{{initializer contains unexpanded parameter pack 'Types'}} + Types(static_cast<Types>(0))..., + in_class_member_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'}} + T a[] = { T(), T(), T() }; + for (Types t : a) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + switch(Types *t = 0) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + while(Types *t = 0) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + if (Types *t = 0) { } // expected-error{{declaration type contains unexpanded parameter pack 'Types'}} + 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 + + for (auto t : values) { } // expected-error{{expression contains unexpanded parameter pack 'values'}} +} + +// 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/clang/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp new file mode 100644 index 0000000..79340c3 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/parameter-matching.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// Check for template type parameter pack (mis-)matches with template +// type parameters. +template<typename ...T> struct X0t; +template<typename ...T> struct X0t; + +template<typename ...T> struct X1t; // expected-note{{previous template type parameter pack declared here}} +template<typename T> struct X1t; // expected-error{{template type parameter conflicts with previous template type parameter pack}} + +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 X0t_intt; +template<template<typename ...T> class> struct X0t_intt; + +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 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/clang/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp new file mode 100644 index 0000000..71bd6aa --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/partial-ordering.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp new file mode 100644 index 0000000..0aef6ad --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template<typename T> struct A { }; + +template<typename T> T make(); +template<typename T> T make2(const T&); + +void test_make() { + int& ir0 = make<int&>(); + A<int> a0 = make< A<int> >(); + A<int> a1 = make2< A<int> >(A<int>()); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp new file mode 100644 index 0000000..4d29b74 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-0x.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp new file mode 100644 index 0000000..de3b44f --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5811 +template <class F> void Call(F f) { f(1); } +template <typename T> void f(T); +void a() { Call(f<int>); } + +// Check the conversion of a template-id to a pointer +template<typename T, T* Address> struct Constant { }; +Constant<void(int), &f<int> > constant0; + +template<typename T, T* Address> void constant_func(); +void test_constant_func() { + constant_func<void(int), &f<int> >(); +} + + +// Check typeof() on a template-id referring to a single function +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; +}; + +int typeof0[is_same<__typeof__(f<int>), void (int)>::value? 1 : -1]; +int typeof1[is_same<__typeof__(&f<int>), void (*)(int)>::value? 1 : -1]; + +template <typename T> void g(T); // expected-note{{possible target for call}} +template <typename T> void g(T, T); // expected-note{{possible target for call}} + +int typeof2[is_same<__typeof__(g<float>), void (int)>::value? 1 : -1]; // \ + // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp new file mode 100644 index 0000000..5556f35 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class X, class Y, class Z> X f(Y,Z); // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} + +void g() { + f<int,char*,double>("aa",3.0); // expected-warning{{conversion from string literal to 'char *' is deprecated}} + f<int,char*>("aa",3.0); // Z is deduced to be double \ + // expected-warning{{conversion from string literal to 'char *' is deprecated}} + f<int>("aa",3.0); // Y is deduced to be char*, and + // Z is deduced to be double + f("aa",3.0); // expected-error{{no matching}} +} + +// PR5910 +namespace PR5910 { + template <typename T> + void Func() {} + + template <typename R> + void Foo(R (*fp)()); + + void Test() { + Foo(Func<int>); + } +} + +// PR5949 +namespace PR5949 { + struct Bar; + + template <class Container> + void quuz(const Container &cont) { + } + + template<typename T> + int Foo(Bar *b, void (*Baz)(const T &t), T * = 0) { + return 0; + } + + template<typename T> + int Quux(Bar *b, T * = 0) + { + return Foo<T>(b, quuz); + } +} + +// PR7641 +namespace PR7641 { + namespace N2 + { + template<class> + int f0(int); + } + namespace N + { + using N2::f0; + } + + template<class R,class B1> + int + f1(R(a)(B1)); + + void f2() + { f1(N::f0<int>); } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp new file mode 100644 index 0000000..81addfe --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.fct.spec/temp.deduct/cwg1170.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/cwg1170.cpp new file mode 100644 index 0000000..c14b063 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/cwg1170.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +#if !__has_feature(cxx_access_control_sfinae) +# error No support for access control as part of SFINAE? +#endif + +typedef char yes_type; +typedef char (&no_type)[2]; + +template<unsigned N> struct unsigned_c { }; + +template<typename T> +class has_copy_constructor { + static T t; + + template<typename U> static yes_type check(unsigned_c<sizeof(U(t))> * = 0); + template<typename U> static no_type check(...); + +public: + static const bool value = (sizeof(check<T>(0)) == sizeof(yes_type)); +}; + +struct HasCopy { }; + +struct HasNonConstCopy { + HasNonConstCopy(HasNonConstCopy&); +}; + +struct HasDeletedCopy { + HasDeletedCopy(const HasDeletedCopy&) = delete; +}; + +struct HasPrivateCopy { +private: + HasPrivateCopy(const HasPrivateCopy&); +}; + +int check0[has_copy_constructor<HasCopy>::value? 1 : -1]; +int check1[has_copy_constructor<HasNonConstCopy>::value? 1 : -1]; +int check2[has_copy_constructor<HasDeletedCopy>::value? -1 : 1]; +int check3[has_copy_constructor<HasPrivateCopy>::value? -1 : 1]; diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp new file mode 100644 index 0000000..c27261c --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <int> int f(int); // expected-note 2{{candidate}} +template <signed char> int f(int); // expected-note 2{{candidate}} +int i1 = f<1>(0); // expected-error{{ambiguous}} +int i2 = f<1000>(0); // expected-error{{ambiguous}} + +namespace PR6707 { + template<typename T, T Value> + struct X { }; + + template<typename T, T Value> + void f(X<T, Value>); + + void g(X<int, 10> x) { + f(x); + } + + static const unsigned char ten = 10; + template<typename T, T Value, typename U> + void f2(X<T, Value>, X<U, Value>); + + void g2() { + f2(X<int, 10>(), X<char, ten>()); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp new file mode 100644 index 0000000..6481485 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -verify %s + +typedef char one_byte; +struct two_bytes { char data[2]; }; + +template<typename T> one_byte __is_class_check(int T::*); +template<typename T> two_bytes __is_class_check(...); + +template<typename T> struct is_class { + static const bool value = sizeof(__is_class_check<T>(0)) == 1; +}; + +struct X { }; + +int array0[is_class<X>::value? 1 : -1]; +int array1[is_class<int>::value? -1 : 1]; +int array2[is_class<char[3]>::value? -1 : 1]; + +namespace instantiation_order1 { + template<typename T> + struct it_is_a_trap { + typedef typename T::trap type; + }; + + template<bool, typename T = void> + struct enable_if { + typedef T type; + }; + + template<typename T> + struct enable_if<false, T> { }; + + template<typename T> + typename enable_if<sizeof(T) == 17>::type + f(const T&, typename it_is_a_trap<T>::type* = 0); + + void f(...); + + void test_f() { + f('a'); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp new file mode 100644 index 0000000..90d2949 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> struct A { }; + +template<typename T> A<T> f0(T*); + +void test_f0(int *ip, float const *cfp) { + A<int> a0 = f0(ip); + A<const float> a1 = f0(cfp); +} + +template<typename T> void f1(T*, int); + +void test_f1(int *ip, float fv) { + f1(ip, fv); +} + +// TODO: this diagnostic can and should improve +template<typename T> void f2(T*, T*); // expected-note {{candidate template ignored: failed template argument deduction}} \ +// expected-note{{candidate template ignored: deduced conflicting types for parameter 'T' ('int' vs. 'float')}} + +struct ConvToIntPtr { + operator int*() const; +}; + +void test_f2(int *ip, float *fp) { + f2(ip, ConvToIntPtr()); // expected-error{{no matching function}} + f2(ip, ip); // okay + f2(ip, fp); // expected-error{{no matching function}} +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp new file mode 100644 index 0000000..8b192fa --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp @@ -0,0 +1,88 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p2.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p2.cpp new file mode 100644 index 0000000..c165c45 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p2.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> struct A { }; + +// bullet 1 +template<typename T> A<T> f0(T* ptr); + +void test_f0_bullet1() { + int arr0[6]; + A<int> a0 = f0(arr0); + const int arr1[] = { 1, 2, 3, 4, 5 }; + A<const int> a1 = f0(arr1); +} + +// bullet 2 +int g0(int, int); +float g1(float); + +void test_f0_bullet2() { + A<int(int, int)> a0 = f0(g0); + A<float(float)> a1 = f0(g1); +} + +// bullet 3 +struct X { }; +const X get_X(); + +template<typename T> A<T> f1(T); + +void test_f1_bullet3() { + A<X> a0 = f1(get_X()); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp new file mode 100644 index 0000000..e470dd0 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp new file mode 100644 index 0000000..295f080 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp @@ -0,0 +1,148 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> struct A { }; + +// Top-level cv-qualifiers of P's type are ignored for type deduction. +template<typename T> A<T> f0(const T); + +void test_f0(int i, const int ci) { + A<int> a0 = f0(i); + A<int> a1 = f0(ci); +} + +// If P is a reference type, the type referred to by P is used for type +// deduction. +template<typename T> A<T> f1(T&); + +void test_f1(int i, const int ci, volatile int vi) { + A<int> a0 = f1(i); + A<const int> a1 = f1(ci); + A<volatile int> a2 = f1(vi); +} + +template<typename T, unsigned N> struct B { }; +template<typename T, unsigned N> B<T, N> g0(T (&array)[N]); +template<typename T, unsigned N> B<T, N> g0b(const T (&array)[N]); + +void test_g0() { + int array0[5]; + B<int, 5> b0 = g0(array0); + const int array1[] = { 1, 2, 3}; + B<const int, 3> b1 = g0(array1); + B<int, 3> b2 = g0b(array1); +} + +template<typename T> B<T, 0> g1(const A<T>&); + +void test_g1(A<float> af) { + B<float, 0> b0 = g1(af); + B<int, 0> b1 = g1(A<int>()); +} + +// - If the original P is a reference type, the deduced A (i.e., the type +// referred to by the reference) can be more cv-qualified than the +// transformed A. +template<typename T> A<T> f2(const T&); + +void test_f2(int i, const int ci, volatile int vi) { + A<int> a0 = f2(i); + A<int> a1 = f2(ci); + A<volatile int> a2 = f2(vi); +} + +// PR5913 +template <typename T, int N> +void Foo(const T (&a)[N]) { + T x; + x = 0; +} + +const int a[1] = { 0 }; + +void Test() { + Foo(a); +} + +// - The transformed A can be another pointer or pointer to member type that +// can be converted to the deduced A via a qualification conversion (4.4). +template<typename T> A<T> f3(T * * const * const); + +void test_f3(int ***ip, volatile int ***vip) { + A<int> a0 = f3(ip); + A<volatile int> a1 = f3(vip); +} + +// Also accept conversions for pointer types which require removing +// [[noreturn]]. +namespace noreturn_stripping { + template <class R> + void f(R (*function)()); + + void g() __attribute__ ((__noreturn__)); + void h(); + void test() { + f(g); + f(h); + } +} + +// - If P is a class, and P has the form template-id, then A can be a +// derived class of the deduced A. Likewise, if P is a pointer to a class +// of the form template-id, A can be a pointer to a derived class pointed +// to by the deduced A. +template<typename T, int I> struct C { }; + +struct D : public C<int, 1> { }; +struct E : public D { }; +struct F : A<float> { }; +struct G : A<float>, C<int, 1> { }; + +template<typename T, int I> + C<T, I> *f4a(const C<T, I>&); +template<typename T, int I> + C<T, I> *f4b(C<T, I>); +template<typename T, int I> + C<T, I> *f4c(C<T, I>*); +int *f4c(...); + +void test_f4(D d, E e, F f, G g) { + C<int, 1> *ci1a = f4a(d); + C<int, 1> *ci2a = f4a(e); + C<int, 1> *ci1b = f4b(d); + C<int, 1> *ci2b = f4b(e); + C<int, 1> *ci1c = f4c(&d); + C<int, 1> *ci2c = f4c(&e); + 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 + } +} + +namespace PR9233 { + template<typename T> void f(const T **q); // expected-note{{candidate template ignored: substitution failure [with T = int]}} + + void g(int **p) { + f(p); // expected-error{{no matching function for call to 'f'}} + } + +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp new file mode 100644 index 0000000..83b5f23 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR8598 { + template<class T> struct identity { typedef T type; }; + + template<class T, class C> + void f(T C::*, typename identity<T>::type*){} + + struct X { void f() {}; }; + + void g() { (f)(&X::f, 0); } +} + +namespace PR12132 { + template<typename S> void fun(const int* const S::* member) {} + struct A { int* x; }; + void foo() { + fun(&A::x); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp new file mode 100644 index 0000000..8b18189 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp @@ -0,0 +1,128 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace test0 { + template<class T> void apply(T x, void (*f)(T)) { f(x); } // expected-note 2 {{candidate template ignored: deduced conflicting types for parameter 'T'}}\ + // expected-note {{no overload of 'temp2' matching 'void (*)(int)'}} + + template<class A> void temp(A); + void test0() { + // okay: deduce T=int from first argument, A=int during overload + apply(0, &temp); + apply(0, &temp<>); + + // okay: deduce T=int from first and second arguments + apply(0, &temp<int>); + + // deduction failure: T=int from first, T=long from second + apply(0, &temp<long>); // expected-error {{no matching function for call to 'apply'}} + } + + void over(int); + int over(long); + + void test1() { + // okay: deductions match + apply(0, &over); + + // deduction failure: deduced T=long from first argument, T=int from second + apply(0L, &over); // expected-error {{no matching function for call to 'apply'}} + } + + void over(short); + + void test2() { + // deduce T=int from first arg, second arg is undeduced context, + // pick correct overload of 'over' during overload resolution for 'apply' + apply(0, &over); + } + + template<class A, class B> B temp2(A); + void test3() { + // deduce T=int from first arg, A=int B=void during overload resolution + apply(0, &temp2); + apply(0, &temp2<>); + apply(0, &temp2<int>); + + // overload failure + apply(0, &temp2<long>); // expected-error {{no matching function for call to 'apply'}} + } +} + +namespace test1 { + template<class T> void invoke(void (*f)(T)) { f(T()); } // expected-note 6 {{couldn't infer template argument}} \ + // expected-note {{candidate template ignored: couldn't infer template argument 'T'}} + + template<class T> void temp(T); + void test0() { + // deduction failure: overload has template => undeduced context + invoke(&temp); // expected-error {{no matching function for call to 'invoke'}} + invoke(&temp<>); // expected-error {{no matching function for call to 'invoke'}} + + // okay: full template-id + invoke(&temp<int>); + } + + void over(int); + int over(long); + + void test1() { + // okay: only one overload matches + invoke(&over); + } + + void over(short); + + void test2() { + // deduction failure: overload has multiple matches => undeduced context + invoke(&over); // expected-error {{no matching function for call to 'invoke'}} + } + + template<class A, class B> B temp2(A); + void test3() { + // deduction failure: overload has template => undeduced context + // (even though partial application temp2<int> could in theory + // let us infer T=int) + invoke(&temp2); // expected-error {{no matching function for call to 'invoke'}} + invoke(&temp2<>); // expected-error {{no matching function for call to 'invoke'}} + invoke(&temp2<int>); // expected-error {{no matching function for call to 'invoke'}} + + // okay: full template-id + invoke(&temp2<int, void>); + + // overload failure + invoke(&temp2<int, int>); // expected-error {{no matching function for call to 'invoke'}} + } +} + +namespace rdar8360106 { + template<typename R, typename T> void f0(R (*)(T), T); + template<typename R, typename T> void f1(R (&)(T) , T); // expected-note{{candidate template ignored: couldn't infer template argument 'R'}} + template<typename R, typename T> void f2(R (* const&)(T), T); // expected-note{{candidate template ignored: couldn't infer template argument 'R'}} + + int g(int); + int g(int, int); + + void h() { + f0(g, 1); + f0(&g, 1); + f1(g, 1); + f1(&g, 1); // expected-error{{no matching function for call to 'f1'}} + f2(g, 1); // expected-error{{no matching function for call to 'f2'}} + f2(&g, 1); + } +} + +namespace PR11713 { + template<typename T> + int f(int, int, int); + + template<typename T> + float f(float, float); + + template<typename R, typename B1, typename B2, typename A1, typename A2> + R& g(R (*)(B1, B2), A1, A2); + + void h() { + float &fr = g(f<int>, 1, 2); + } +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p2.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p2.cpp new file mode 100644 index 0000000..5a9ea08 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p2.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// FIXME: [temp.deduct.conv]p2 bullets 1 and 2 can't actually happen without +// references? +// struct ConvertibleToArray { +// // template<typename T, unsigned N> +// // operator T(()[]) const; + +// private: +// typedef int array[17]; + +// operator array() const; +// }; + +// void test_array(ConvertibleToArray cta) { +// int *ip = cta; +// ip = cta; +// const float *cfp = cta; +// } + +// bullet 2 +// struct ConvertibleToFunction { +// template<typename T, typename A1, typename A2> +// operator T(A1, A2) const () { }; +// }; + +// bullet 3 +struct ConvertibleToCVQuals { + template<typename T> + operator T* const() const; +}; + +void test_cvqual_conv(ConvertibleToCVQuals ctcv) { + int *ip = ctcv; + const int *icp = ctcv; +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p3.cpp new file mode 100644 index 0000000..e23e98a --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p3.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct AnyPtr { + template<typename T> + operator T*() const; +}; + +// If A is a cv-qualified type, the top level cv-qualifiers of A's type +// are ignored for type deduction. +void test_cvquals(AnyPtr ap) { + int* const ip = ap; + const float * const volatile fp = ap; +} + +// If A is a reference type, the type referred to by A is used for +// type deduction. +void test_ref_arg(AnyPtr ap) { + const int* const &ip = ap; + double * const &dp = ap; +} + +struct AnyRef { + template<typename T> + operator T&() const; +}; + +void test_ref_param(AnyRef ar) { + int &ir = ar; + const float &fr = ar; + int i = ar; +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp new file mode 100644 index 0000000..4dca820 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +struct AnyT { + template<typename T> + operator T(); +}; + +void test_cvqual_ref(AnyT any) { + const int &cir = any; +} + +struct AnyThreeLevelPtr { + template<typename T> + operator T***() const + { + T x = 0; + // FIXME: looks like we get this wrong, too! + // x = 0; // will fail if T is deduced to a const type + // (EDG and GCC get this wrong) + return 0; + } +}; + +struct X { }; + +void test_deduce_with_qual(AnyThreeLevelPtr a3) { + int * const * const * const ip = a3; +} + +struct AnyPtrMem { + template<typename Class, typename T> + operator T Class::*() const + { + T x = 0; + // FIXME: looks like we get this wrong, too! + // x = 0; // will fail if T is deduced to a const type. + // (EDG and GCC get this wrong) + return 0; + } +}; + +void test_deduce_ptrmem_with_qual(AnyPtrMem apm) { + const float X::* pm = apm; +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp new file mode 100644 index 0000000..99a265a --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template<typename T> + T f0(T, int); + +void test_f0() { + int (*f0a)(int, int) = f0; + int (*f0b)(int, int) = &f0; + float (*f0c)(float, int) = &f0; +} + +template<typename T> T f1(T, int); +template<typename T> T f1(T); + +void test_f1() { + float (*f1a)(float, int) = f1; + float (*f1b)(float, int) = &f1; + float (*f1c)(float) = f1; + float (*f1d)(float) = (f1); + float (*f1e)(float) = &f1; + float (*f1f)(float) = (&f1); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp new file mode 100644 index 0000000..01155e1 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +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<typename T> +struct identity { + typedef T type; +}; + +template <class T> + T* f2(int, typename identity<T>::type = 0); +template <class T, class U> + T& f2(U, typename identity<T>::type = 0); + +void g2() { + 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/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p12.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p12.cpp new file mode 100644 index 0000000..b965300 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p12.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp new file mode 100644 index 0000000..f204caf --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp new file mode 100644 index 0000000..8183061 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p10-0x.cpp @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +template<typename T> void f(T&&); +template<> void f(int&) { } +void (*fp)(int&) = &f; diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp new file mode 100644 index 0000000..bf5f962 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<int i> class A { }; +template<short s> void f(A<s>); // expected-note{{candidate template ignored: substitution failure}} + +void k1() { + A<1> a; + f(a); // expected-error{{no matching function for call}} + f<1>(a); +} +template<const short cs> class B { }; +template<short s> void g(B<s>); +void k2() { + B<1> b; + g(b); // OK: cv-qualifiers are ignored on template parameter types +} + +template<short s> void h(int (&)[s]); // expected-note{{candidate function template not viable: requires 1 argument, but 2 were provided}} +void k3() { + int array[5]; + h(array); + h<5>(array); +} + +template<short s> void h(int (&)[s], A<s>); // expected-note{{candidate template ignored: substitution failure}} +void k4() { + A<5> a; + int array[5]; + h(array, a); // expected-error{{no matching function for call}} + h<5>(array, a); +} diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p2-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p2-0x.cpp new file mode 100644 index 0000000..5b031c2 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p2-0x.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p21.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p21.cpp new file mode 100644 index 0000000..4e98a6d --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p21.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p22.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p22.cpp new file mode 100644 index 0000000..fcc6cf7 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p22.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp new file mode 100644 index 0000000..c819d97 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p5-0x.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp new file mode 100644 index 0000000..a6b1172 --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp new file mode 100644 index 0000000..7774b5c --- /dev/null +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=c++11 -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/clang/test/CXX/temp/temp.names/p2.cpp b/clang/test/CXX/temp/temp.names/p2.cpp new file mode 100644 index 0000000..93e45dd --- /dev/null +++ b/clang/test/CXX/temp/temp.names/p2.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Ensure that when enforcing access control an unqualified template name with +// explicit template arguments, we don't lose the context of the name lookup +// because of the required early lookup to determine if it names a template. +namespace PR7163 { + template <typename R, typename P> void h(R (*func)(P)) {} + class C { + template <typename T> static void g(T*) {}; + public: + void f() { h(g<int>); } + }; +} diff --git a/clang/test/CXX/temp/temp.names/p4.cpp b/clang/test/CXX/temp/temp.names/p4.cpp new file mode 100644 index 0000000..103a1bd --- /dev/null +++ b/clang/test/CXX/temp/temp.names/p4.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct meta { + template<typename U> + struct apply { + typedef U* type; + }; +}; + +template<typename T, typename U> +void f(typename T::template apply<U>::type); + +void test_f(int *ip) { + f<meta, int>(ip); +} diff --git a/clang/test/CXX/temp/temp.param/p1.cpp b/clang/test/CXX/temp/temp.param/p1.cpp new file mode 100644 index 0000000..e9a9789 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p1.cpp @@ -0,0 +1,12 @@ +// Suppress 'no run line' failure. +// RUN: %clang_cc1 -fsyntax-only -verify %s + +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/clang/test/CXX/temp/temp.param/p10-0x.cpp b/clang/test/CXX/temp/temp.param/p10-0x.cpp new file mode 100644 index 0000000..37bb284 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p10-0x.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +template<typename> struct Y1; +template<typename, int> struct Y2; + +template<class T1, class T2 = int> using B2 = T1; +template<class T1 = int, class T2> using B2 = T1; + +template<template<class> class F, template<class> class G = Y1> using B2t = F<G<int>>; +template<template<class> class F = Y2, template<class> class G> using B2t = F<G<int>>; + +template<int N, int M = 5> using B2n = Y2<int, N + M>; +template<int N = 5, int M> using B2n = Y2<int, N + M>; diff --git a/clang/test/CXX/temp/temp.param/p10.cpp b/clang/test/CXX/temp/temp.param/p10.cpp new file mode 100644 index 0000000..b9dac75 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p10.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename> struct Y1; +template<typename, int> struct Y2; + +template<class T1, class T2 = int> class B2; +template<class T1 = int, class T2> class B2; + +template<template<class, int> class, template<class> class = Y1> class B2t; +template<template<class, int> class = Y2, template<class> class> class B2t; + +template<int N, int M = 5> class B2n; +template<int N = 5, int M> class B2n; diff --git a/clang/test/CXX/temp/temp.param/p11-0x.cpp b/clang/test/CXX/temp/temp.param/p11-0x.cpp new file mode 100644 index 0000000..d2276a3 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p11-0x.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +// If a template-parameter of a class template or alias 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> struct X3t; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}} +template<typename T = int, typename> using A3t = int; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}} +template<int V = 0, int> struct X3nt; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}} +template<int V = 0, int> using A3nt = int; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}} +template<template<class> class M = vector, template<class> class> struct X3tt; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}} +template<template<class> class M = vector, template<class> class> using A3tt = int; // expected-error{{template parameter missing a default argument}} expected-note{{previous default template argument defined here}} + +template<typename T = int, typename ...Types> struct X2t; +template<typename T = int, typename ...Types> using A2t = X2t<T, Types...>; +template<int V = 0, int ...Values> struct X2nt; +template<int V = 0, int ...Values> using A2nt = X2nt<V, Values...>; +template<template<class> class M = vector, template<class> class... Metas> + struct X2tt; +template<template<class> class M = vector, template<class> class... Metas> + using A2tt = X2tt<M, Metas...>; + +// If a template-parameter of a primary class template or alias 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, int After2> +struct X0t; +X0t<int> pr9789(); +template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}} + int After> +using A0t = int; + +template<int ...Values, // expected-error{{template parameter pack must be the last template parameter}} + int After> +struct X0nt; +template<int ...Values, // expected-error{{template parameter pack must be the last template parameter}} + int After> +using A0nt = int; + +template<template<typename> class ...Templates, // expected-error{{template parameter pack must be the last template parameter}} + int After> +struct X0tt; +template<template<typename> class ...Templates, // expected-error{{template parameter pack must be the last template parameter}} + int After> +using A0tt = int; + +// [ 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/clang/test/CXX/temp/temp.param/p11.cpp b/clang/test/CXX/temp/temp.param/p11.cpp new file mode 100644 index 0000000..5af0c4e --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p11.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename> struct Y1; +template<typename, int> struct Y2; + +template<class T1 = int, // expected-note{{previous default template argument defined here}} + class T2> // expected-error{{template parameter missing a default argument}} + class B1; + +template<template<class> class = Y1, // expected-note{{previous default template argument defined here}} + template<class> class> // expected-error{{template parameter missing a default argument}} + class B1t; + +template<int N = 5, // expected-note{{previous default template argument defined here}} + int M> // expected-error{{template parameter missing a default argument}} + class B1n; diff --git a/clang/test/CXX/temp/temp.param/p12.cpp b/clang/test/CXX/temp/temp.param/p12.cpp new file mode 100644 index 0000000..7be3879 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p12.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename> struct Y1; // expected-note{{too few template parameters in template template argument}} +template<typename, int> struct Y2; + +// C++ [temp.param]p12: +template<class T1, + class T2 = int> // expected-note{{previous default template argument defined here}} + class B3; +template<class T1, typename T2> class B3; +template<class T1, + typename T2 = float> // expected-error{{template parameter redefines default argument}} + class B3; + +template<template<class, int> class, + template<class> class = Y1> // expected-note{{previous default template argument defined here}} + class B3t; + +template<template<class, int> class, template<class> class> class B3t; + +template<template<class, int> class, + template<class> class = Y1> // expected-error{{template parameter redefines default argument}} + class B3t; + +template<int N, + int M = 5> // expected-note{{previous default template argument defined here}} + class B3n; + +template<int N, int M> class B3n; + +template<int N, + int M = 7> // expected-error{{template parameter redefines default argument}} + class B3n; + +// Check validity of default arguments +template<template<class, int> class // expected-note{{previous template template parameter is here}} + = Y1> // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} + class C1 {}; + +C1<> c1; // expected-note{{while checking a default template argument}} diff --git a/clang/test/CXX/temp/temp.param/p13.cpp b/clang/test/CXX/temp/temp.param/p13.cpp new file mode 100644 index 0000000..7e7dbe5 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p13.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// The scope of atemplate-parameterextends from its point of +// declaration until the end of its template. In particular, a +// template-parameter can be used in the declaration of subsequent +// template-parameters and their default arguments. + +template<class T, T* p, class U = T> class X { /* ... */ }; +// FIXME: template<class T> void f(T* p = new T); + +// Check for bogus template parameter shadow warning. +template<template<class T> class, + template<class T> class> + class B1noshadow; diff --git a/clang/test/CXX/temp/temp.param/p14.cpp b/clang/test/CXX/temp/temp.param/p14.cpp new file mode 100644 index 0000000..a6c53c1 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p14.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// XFAIL: * + +// A template-parameter shall not be used in its own default argument. +template<typename T = typename T::type> struct X; // expected-error{{default}} diff --git a/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp b/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp new file mode 100644 index 0000000..5fc57a4 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +template<typename T> struct X; +template<int I> struct Y; + +X<X<int>> *x1; + +Y<(1 >> 2)> *y1; +Y<1 >> 2> *y2; // FIXME: expected-error{{expected unqualified-id}} + +X<X<X<X<X<int>>>>> *x2; + +template<> struct X<int> { }; +typedef X<int> X_int; +struct Z : X_int { }; + +void f(const X<int> x) { + (void)reinterpret_cast<X<int>>(x); // expected-error{{reinterpret_cast from}} + (void)reinterpret_cast<X<X<X<int>>>>(x); // expected-error{{reinterpret_cast from}} + + X<X<int>> *x1; +} + +template<typename T = void> struct X1 { }; +X1<X1<>> x1a; diff --git a/clang/test/CXX/temp/temp.param/p15.cpp b/clang/test/CXX/temp/temp.param/p15.cpp new file mode 100644 index 0000000..ee572e9 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p15.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify %s +template<typename T> struct X; +template<int I> struct Y; + +X<X<int> > *x1; +X<X<int>> *x2; // expected-error{{a space is required between consecutive right angle brackets (use '> >')}} + +X<X<X<X<int>> // expected-error{{a space is required between consecutive right angle brackets (use '> >')}} + >> *x3; // expected-error{{a space is required between consecutive right angle brackets (use '> >')}} + +Y<(1 >> 2)> *y1; +Y<1 >> 2> *y2; // expected-warning{{use of right-shift operator ('>>') in template argument will require parentheses in C++11}} diff --git a/clang/test/CXX/temp/temp.param/p2.cpp b/clang/test/CXX/temp/temp.param/p2.cpp new file mode 100644 index 0000000..fed6e9c --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p2.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// There is no semantic difference between class and typename in a +// template-parameter. typename followed by an unqualified-id names a +// template type parameter. +template<class T> struct X; +template<typename T> struct X; + +// typename followed by aqualified-id denotes the type in a non-type +// parameter-declaration. +template<typename T, typename T::type Value> struct Y0; +template<typename T, typename X<T>::type Value> struct Y1; + +// A storage class shall not be specified in a template-parameter declaration. +template<static int Value> struct Z; // FIXME: expect an error + +// Make sure that we properly disambiguate non-type template parameters that +// start with 'class'. +class X1 { }; +template<class X1 *xptr> struct Y2 { }; + +// FIXME: add the example from p2 diff --git a/clang/test/CXX/temp/temp.param/p3.cpp b/clang/test/CXX/temp/temp.param/p3.cpp new file mode 100644 index 0000000..dc40c4b --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p3.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// A type-parameter defines its identifier to be a type-name (if +// declared with class or typename) or template-name (if declared with +// template) in the scope of the template declaration. +template<typename T> struct X0 { + T* value; +}; + +template<template<class T> class Y> struct X1 { + Y<int> value; +}; + +// [Note: because of the name lookup rules, a template-parameter that +// could be interpreted as either a non-type template-parameter or a +// type-parameter (because its identifier is the name of an already +// existing class) is taken as a type-parameter. For example, +class T { /* ... */ }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}} +int i; + +template<class T, T i> struct X2 { + void f(T t) + { + T t1 = i; //template-parameters T and i + ::T t2 = ::i; // global namespace members T and i \ + // expected-error{{no viable conversion}} + } +}; + +namespace PR6831 { + namespace NA { struct S; } + namespace NB { struct S; } + + using namespace NA; + using namespace NB; + + template <typename S> void foo(); + template <int S> void bar(); + template <template<typename> class S> void baz(); +} diff --git a/clang/test/CXX/temp/temp.param/p4.cpp b/clang/test/CXX/temp/temp.param/p4.cpp new file mode 100644 index 0000000..809fb20 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p4.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +class X; + +// C++ [temp.param]p4 +typedef int INT; +enum E { enum1, enum2 }; +template<int N> struct A1; +template<INT N, INT M> struct A2; +template<enum E x, E y> struct A3; +template<int &X> struct A4; +template<int *Ptr> struct A5; +template<int (&f)(int, int)> struct A6; +template<int (*fp)(float, double)> struct A7; +template<int X::*pm> struct A8; +template<float (X::*pmf)(float, int)> struct A9; +template<typename T, T x> struct A10; + +template<float f> struct A11; // expected-error{{a non-type template parameter cannot have type 'float'}} + +template<void *Ptr> struct A12; +template<int (*IncompleteArrayPtr)[]> struct A13; diff --git a/clang/test/CXX/temp/temp.param/p5.cpp b/clang/test/CXX/temp/temp.param/p5.cpp new file mode 100644 index 0000000..3cbb3b7 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p5.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -verify %s -std=c++11 + +template<const int I> struct S { + decltype(I) n; + int &&r = I; +}; +S<5> s; + +template<typename T, T v> struct U { + decltype(v) n; + int &&r = v; +}; +U<const int, 6> u; diff --git a/clang/test/CXX/temp/temp.param/p7.cpp b/clang/test/CXX/temp/temp.param/p7.cpp new file mode 100644 index 0000000..13f0367 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p7.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// A non-type template-parameter shall not be declared to have +// floating point, class, or void type. +struct A; + +template<double d> class X; // expected-error{{cannot have type}} +template<double* pd> class Y; //OK +template<double& rd> class Z; //OK + +template<A a> class X0; // expected-error{{cannot have type}} + +typedef void VOID; +template<VOID a> class X01; // expected-error{{cannot have type}} + diff --git a/clang/test/CXX/temp/temp.param/p8.cpp b/clang/test/CXX/temp/temp.param/p8.cpp new file mode 100644 index 0000000..fed048c --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p8.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<int X[10]> struct A; +template<int *X> struct A; +template<int f(float, double)> struct B; +typedef float FLOAT; +template<int (*f)(FLOAT, double)> struct B; diff --git a/clang/test/CXX/temp/temp.param/p9-0x.cpp b/clang/test/CXX/temp/temp.param/p9-0x.cpp new file mode 100644 index 0000000..29a7549 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p9-0x.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -std=c++11 -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() {} +} + +namespace PR10069 { + template<typename T, T a, T b=0, T c=1> + T f(T x); + + void g() { + f<unsigned int, 0>(0); + } +} diff --git a/clang/test/CXX/temp/temp.param/p9.cpp b/clang/test/CXX/temp/temp.param/p9.cpp new file mode 100644 index 0000000..b2318c2 --- /dev/null +++ b/clang/test/CXX/temp/temp.param/p9.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify %s + +// A default template-argument shall not be specified in a function +// template declaration or a function template definition +template<typename T = int> // expected-warning{{default template arguments for a function template are a C++11 extension}} + void foo0(T); +template<typename T = int> // expected-warning{{default template arguments for a function template are a C++11 extension}} + void foo1(T) { } + +// [...] nor in the template-parameter-list of the definition of a +// member of a class template. +template<int N> +struct X0 { + void f(); +}; + +template<int N = 0> // expected-error{{cannot add a default template argument}} +void X0<N>::f() { } + +class X1 { + template<template<int> class TT = X0> // expected-error{{not permitted on a friend template}} + friend void f2(); +}; diff --git a/clang/test/CXX/temp/temp.res/temp.dep.res/temp.point/p1.cpp b/clang/test/CXX/temp/temp.res/temp.dep.res/temp.point/p1.cpp new file mode 100644 index 0000000..75580d2 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.dep.res/temp.point/p1.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// XFAIL: * + +// Note: we fail this test because we perform template instantiation +// at the end of the translation unit, so argument-dependent lookup +// finds functions that occur after the point of instantiation. Note +// that GCC fails this test; EDG passes the test in strict mode, but +// not in relaxed mode. +namespace N { + struct A { }; + struct B : public A { }; + + int& f0(A&); +} + +template<typename T, typename Result> +struct X0 { + void test_f0(T t) { + Result r = f0(t); + }; +}; + +void test_f0() { + X0<N::A, int&> xA; + xA.test_f0(N::A()); + X0<N::B, int&> xB; + xB.test_f0(N::B()); +} + +namespace N { + char& f0(B&); +} diff --git a/clang/test/CXX/temp/temp.res/temp.dep/p3.cpp b/clang/test/CXX/temp/temp.res/temp.dep/p3.cpp new file mode 100644 index 0000000..c41a4c6 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.dep/p3.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A0 { + struct K { }; +}; + +template <typename T> struct B0: A0 { + static void f() { + K k; + } +}; + +namespace E1 { + typedef double A; + + template<class T> class B { + typedef int A; + }; + + template<class T> + struct X : B<T> { + A* blarg(double *dp) { + return dp; + } + }; +} + +namespace E2 { + struct A { + struct B; + int *a; + int Y; + }; + + int a; + template<class T> struct Y : T { + struct B { /* ... */ }; + B b; + void f(int i) { a = i; } + Y* p; + }; + + Y<A> ya; +} diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2-0x.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2-0x.cpp new file mode 100644 index 0000000..0aba402 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2-0x.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +template<int n> struct S; + +template<int n> struct T { + T() { + // An identifier is value-dependent if it is: + // - a name declared with a dependent type + S<n> s; + S<s> check1; // ok, s is value-dependent + // - the name of a non-type template parameter + typename S<n>::T check2; // ok, n is value-dependent + // - a constant with literal type and is initialized with an expression + // that is value-dependent. + const int k = n; + typename S<k>::T check3a; // ok, u is value-dependent + + constexpr const int *p = &k; + typename S<*p>::T check3b; // ok, p is value-dependent + + // (missing from the standard) + // - a reference and is initialized with an expression that is + // value-dependent. + const int &i = k; + typename S<i>::T check4; // ok, i is value-dependent + } +}; diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp new file mode 100644 index 0000000..68a41c7 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.constexpr/p2.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=c++98 -verify %s + +template<int n> struct S; + +template<int n> struct T { + T() { + // An identifier is value-dependent if it is: + // - a name declared with a dependent type + S<n> s; + S<s> check1; // ok, s is value-dependent + // - the name of a non-type template parameter + typename S<n>::T check2; // ok, n is value-dependent + // - a constant with literal type and is initialized with an expression + // that is value-dependent. + const int k = n; + typename S<k>::T check3; // ok, u is value-dependent + + const int &i = k; + typename S<i>::T check4; // expected-error {{not an integral constant expression}} expected-error {{qualified name}} + } +}; diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp new file mode 100644 index 0000000..81b070f --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// Examples from CWG1056. +namespace Example1 { + template<class T> struct A; + template<class T> using B = A<T>; + + template<class T> struct A { + struct C {}; + B<T>::C bc; // ok, B<T> is the current instantiation. + }; + + template<class T> struct A<A<T>> { + struct C {}; + B<B<T>>::C bc; // ok, B<B<T>> is the current instantiation. + }; + + template<class T> struct A<A<A<T>>> { + struct C {}; + B<B<T>>::C bc; // expected-error {{missing 'typename'}} + }; +} + +namespace Example2 { + template<class T> struct A { + void g(); + }; + template<class T> using B = A<T>; + template<class T> void B<T>::g() {} // ok. +} diff --git a/clang/test/CXX/temp/temp.res/temp.local/p1.cpp b/clang/test/CXX/temp/temp.res/temp.local/p1.cpp new file mode 100644 index 0000000..1ad4464 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.local/p1.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [temp.local]p1: +// Like normal (non-template) classes, class templates have an +// injected-class-name (Clause 9). The injected-class-name can be used with +// or without a template-argument-list. When it is used without +// a template-argument-list, it is equivalent to the injected-class-name +// followed by the template-parameters of the class template enclosed in <>. + +template <typename T> struct X0 { + X0(); + ~X0(); + X0 f(const X0&); +}; + +// Test non-type template parameters. +template <int N1, const int& N2, const int* N3> struct X1 { + X1(); + ~X1(); + X1 f(const X1& x1a) { X1 x1b(x1a); return x1b; } +}; + +// When it is used with a template-argument-list, it refers to the specified +// class template specialization, which could be the current specialization +// or another specialization. +// FIXME: Test this clause. + +int i = 42; +void test() { + X0<int> x0; (void)x0; + X1<42, i, &i> x1; (void)x1; +} diff --git a/clang/test/CXX/temp/temp.res/temp.local/p3.cpp b/clang/test/CXX/temp/temp.res/temp.local/p3.cpp new file mode 100644 index 0000000..54da885 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.local/p3.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -verify %s + +template <class T> struct Base { // expected-note 4 {{member found by ambiguous name lookup}} + static void f(); +}; + +struct X0 { }; + +template <class T> struct Derived: Base<int>, Base<char> { + typename Derived::Base b; // expected-error{{member 'Base' found in multiple base classes of different types}} + typename Derived::Base<double> d; // OK + + void g(X0 *t) { + t->Derived::Base<T>::f(); + t->Base<T>::f(); + t->Base::f(); // expected-error{{member 'Base' found in multiple base classes of different types}} \ + // expected-error{{no member named 'f' in 'X0'}} \ + // expected-error{{expected a class or namespace}} + } +}; + +namespace PR6717 { + template <typename T> + class WebVector { + } // expected-error {{expected ';' after class}} + + WebVector(const WebVector<T>& other) { } // expected-error{{undeclared identifier 'T'}} \ + expected-error{{requires a type specifier}} + + template <typename C> + WebVector<T>& operator=(const C& other) { } // expected-error{{undeclared identifier 'T'}} +} diff --git a/clang/test/CXX/temp/temp.res/temp.local/p7.cpp b/clang/test/CXX/temp/temp.res/temp.local/p7.cpp new file mode 100644 index 0000000..bd05e75 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.local/p7.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class T> struct A { + int B; + int f(); +}; + +template<class B> int A<B>::f() { + return B; +} diff --git a/clang/test/CXX/temp/temp.res/temp.local/p8.cpp b/clang/test/CXX/temp/temp.res/temp.local/p8.cpp new file mode 100644 index 0000000..5d9d509 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.local/p8.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace N { + enum { C }; + template<class T> class B { + void f(T); + }; +} + +template<class C> void N::B<C>::f(C) { + C b; +} + +namespace N { + enum { D }; + namespace M { + enum { C , D }; + template<typename C> class X { + template<typename U> void f(C, U); + + template<typename D> void g(C, D) { + C c; + D d; + } + }; + + struct Y { + template<typename U> void f(U); + }; + } + + struct Y { + template<typename D> void f(D); + }; +} + +template<typename C> +template<typename D> +void N::M::X<C>::f(C, D) { + C c; + D d; +} + +template<typename C> +void N::M::Y::f(C) { + C c; +} + +template<typename D> +void N::Y::f(D) { + D d; +} + diff --git a/clang/test/CXX/temp/temp.res/temp.local/p9.cpp b/clang/test/CXX/temp/temp.res/temp.local/p9.cpp new file mode 100644 index 0000000..9ca8d88 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.local/p9.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +struct A { + struct B { void f(); }; + int a; + int Y; +}; + +template<class B, class a> struct X : A { + B b; // A's B + a c; // expected-error{{unknown type name 'a'}} + + void g() { + b.g(); // expected-error{{no member named 'g' in 'A::B'}} + } +}; diff --git a/clang/test/CXX/temp/temp.spec/p5.cpp b/clang/test/CXX/temp/temp.spec/p5.cpp new file mode 100644 index 0000000..0e69a26 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/p5.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> inline void f(T) { } +template void f(int); // expected-note{{previous explicit instantiation}} +template void f(int); // expected-error{{duplicate explicit instantiation}} + +template<typename T> +struct X0 { + union Inner { }; + + void f(T) { } + + static T value; +}; + +template<typename T> +T X0<T>::value = 3.14; // expected-warning{{implicit conversion turns literal floating-point number into integer}} + +template struct X0<int>; // expected-note{{previous explicit instantiation}} \ + expected-note{{requested here}} +template struct X0<int>; // expected-error{{duplicate explicit instantiation}} + +template void X0<float>::f(float); // expected-note{{previous explicit instantiation}} +template void X0<float>::f(float); // expected-error{{duplicate explicit instantiation}} + +template union X0<float>::Inner; // expected-note{{previous explicit instantiation}} +template union X0<float>::Inner; // expected-error{{duplicate explicit instantiation}} + +template float X0<float>::value; // expected-note{{previous explicit instantiation}} +template float X0<float>::value; // expected-error{{duplicate explicit instantiation}} + +// Make sure that we don't get tricked by redeclarations of nested classes. +namespace NestedClassRedecls { + template<typename T> + struct X { + struct Nested; + friend struct Nested; + + struct Nested { + Nested() {} + } nested; + }; + + X<int> xi; + + template struct X<int>; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp new file mode 100644 index 0000000..aecbfb5 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp @@ -0,0 +1,334 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR5907 { + template<typename T> struct identity { typedef T type; }; + struct A { A(); }; + identity<A>::type::A() { } + + struct B { void f(); }; + template<typename T> struct C { typedef B type; }; + + void C<int>::type::f() { } +} + +namespace PR9421 { + namespace N { template<typename T> struct S { void f(); }; } + typedef N::S<int> T; + namespace N { template<> void T::f() {} } +} + +namespace PR8277 { + template< typename S > + struct C + { + template< int > + void F( void ) + { + } + }; + + template< typename S > + struct D + { + typedef C< int > A; + }; + + typedef D< int >::A A; + + template<> + template<> + void A::F< 0 >( void ) + { + } +} + +namespace PR8277b { + template<typename S> struct C { + void f(); + }; + template<typename S> struct D { + typedef C<int> A; + }; + template<> void D<int>::A::f() { + } +} + +namespace PR8708 { + template<typename T> struct A { + template<typename U> struct B { + // #2 + void f(); + }; + }; + + // #A specialize the member template for + // implicit instantiation of A<int>, + // leaving the member template "unspecialized" + // (14.7.3/16). Specialization uses the syntax + // for explicit specialization (14.7.3/14) + template<> template<typename U> + struct A<int>::B { + // #1 + void g(); + }; + + // #1 define its function g. There is an enclosing + // class template, so we write template<> for each + // specialized template (14.7.3/15). + template<> template<typename U> + void A<int>::B<U>::g() { } + + // #2 define the unspecialized member template's + // f + template<typename T> template<typename U> + void A<T>::B<U>::f() { } + + + // specialize the member template again, now + // specializing the member too. This specializes + // #A + template<> template<> + struct A<int>::B<int> { + // #3 + void h(); + }; + + // defines #3. There is no enclosing class template, so + // we write no "template<>". + void A<int>::B<int>::h() { } + + void test() { + // calls #1 + A<int>::B<float> a; a.g(); + + // calls #2 + A<float>::B<int> b; b.f(); + + // calls #3 + A<int>::B<int> c; c.h(); + } +} + +namespace PR9482 { + namespace N1 { + template <typename T> struct S { + void foo() {} + }; + } + + namespace N2 { + typedef N1::S<int> X; + } + + namespace N1 { + template<> void N2::X::foo() {} + } +} + +namespace PR9668 { + namespace First + { + template<class T> + class Bar + { + protected: + + static const bool static_bool; + }; + } + + namespace Second + { + class Foo; + } + + typedef First::Bar<Second::Foo> Special; + + namespace + First + { + template<> + const bool Special::static_bool(false); + } +} + +namespace PR9877 { + template<int> + struct X + { + struct Y; + }; + + template<> struct X<0>::Y { static const int Z = 1; }; + template<> struct X<1>::Y { static const int Z = 1; }; + + const int X<0>::Y::Z; + template<> const int X<1>::Y::Z; // expected-error{{extraneous 'template<>' in declaration of variable 'Z'}} +} + +namespace PR9913 { + template<class,class=int>struct S; + template<class X>struct S<X> { + template<class T> class F; + }; + + template<class A> + template<class B> + class S<A>::F{}; +} + +namespace template_class_spec_perClassDecl_nested +{ + template <typename T1> struct A { + template <typename T2> struct B { + template <typename T3> struct C { + static void foo(); + }; + }; + }; + + template <> struct A<int> { + template <typename T2> struct B { + template <typename T3> struct C { + static void foo(); + }; + }; + }; + + template <> template <typename T3> struct A<int>::B<int>::C { + static void foo(); + }; + + template <> template <> struct A<int>::B<int>::C<int> { + static void foo(); + }; + + template <> template<> template <typename T2> struct A<bool>::B<bool>::C { + static void foo(); + }; +} + + +namespace spec_vs_expl_inst { + + // Test all permutations of Specialization, + // explicit instantiation Declaration, and explicit instantiation defInition. + + namespace SDI { // PR11558 + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; + extern template class BasicStringPiece<int>; + template class BasicStringPiece<int>; + } + + namespace SID { + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; + template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + } + + namespace ISD { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + template class BasicStringPiece<int>; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::ISD::BasicStringPiece<int>'}} + template <> class BasicStringPiece<int> { }; + extern template class BasicStringPiece<int>; + } + + namespace IDS { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + template class BasicStringPiece<int>; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::IDS::BasicStringPiece<int>'}} // expected-note {{explicit instantiation definition is here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + template <> class BasicStringPiece<int> { }; + } + + namespace DIS { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::DIS::BasicStringPiece<int>'}} + template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; + } + + namespace DSI { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::DSI::BasicStringPiece<int>'}} + template <> class BasicStringPiece<int> { }; + template class BasicStringPiece<int>; + } + + // The same again, with a defined template class. + + namespace SDI_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template <> class BasicStringPiece<int> { }; + extern template class BasicStringPiece<int>; + template class BasicStringPiece<int>; + } + + namespace SID_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template <> class BasicStringPiece<int> { }; + template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + } + + namespace ISD_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template class BasicStringPiece<int>; // expected-note {{explicit instantiation first required here}} + template <> class BasicStringPiece<int> { }; // expected-error {{explicit specialization of 'spec_vs_expl_inst::ISD_WithDefinedTemplate::BasicStringPiece<int>' after instantiation}} + extern template class BasicStringPiece<int>; + } + + namespace IDS_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} expected-note {{previous definition is here}} + extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::IDS_WithDefinedTemplate::BasicStringPiece<int>'}} + } + + namespace DIS_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + extern template class BasicStringPiece<int>; // expected-note {{explicit instantiation first required here}} + template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; // expected-error {{explicit specialization of 'spec_vs_expl_inst::DIS_WithDefinedTemplate::BasicStringPiece<int>' after instantiation}} + } + + namespace DSI_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + extern template class BasicStringPiece<int>; // expected-note {{explicit instantiation first required here}} + template <> class BasicStringPiece<int> { }; // expected-error {{explicit specialization of 'spec_vs_expl_inst::DSI_WithDefinedTemplate::BasicStringPiece<int>' after instantiation}} + template class BasicStringPiece<int>; + } + + // And some more random tests. + + namespace SII_WithDefinedTemplate { + template <typename STRING_TYPE> class BasicStringPiece {}; + template <> class BasicStringPiece<int> { }; + template class BasicStringPiece<int>; // expected-note {{previous explicit instantiation is here}} + template class BasicStringPiece<int>; // expected-error {{duplicate explicit instantiation of 'BasicStringPiece<int>'}} + } + + namespace SIS { + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}} + template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SIS::BasicStringPiece<int>'}} + } + + namespace SDS { + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}} + extern template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SDS::BasicStringPiece<int>'}} + } + + namespace SDIS { + template <typename STRING_TYPE> class BasicStringPiece; + template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}} + extern template class BasicStringPiece<int>; + template class BasicStringPiece<int>; + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SDIS::BasicStringPiece<int>'}} + } + +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp new file mode 100644 index 0000000..3843c0d --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp @@ -0,0 +1,99 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %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 intent is to verify that +// implicit instantiations do not occur (because the explicit specialization +// is used instead). +struct NonDefaultConstructible { + NonDefaultConstructible(int); +}; + + +// C++ [temp.expl.spec]p1: +// An explicit specialization of any of the following: + +// -- function template +template<typename T> void f0(T) { + T t; +} + +template<> void f0(NonDefaultConstructible) { } + +void test_f0(NonDefaultConstructible NDC) { + f0(NDC); +} + +// -- class template +template<typename T> +struct X0 { + static T member; + + void f1(T t) { + t = 17; + } + + struct Inner : public T { }; + + template<typename U> + struct InnerTemplate : public T { }; + + template<typename U> + void ft1(T t, U u); +}; + +template<typename T> +template<typename U> +void X0<T>::ft1(T t, U u) { + t = u; +} + +template<typename T> T X0<T>::member; + +template<> struct X0<void> { }; +X0<void> test_X0; + + +// -- member function of a class template +template<> void X0<void*>::f1(void *) { } + +void test_spec(X0<void*> xvp, void *vp) { + xvp.f1(vp); +} + +// -- static data member of a class template +template<> +NonDefaultConstructible X0<NonDefaultConstructible>::member = 17; + +NonDefaultConstructible &get_static_member() { + return X0<NonDefaultConstructible>::member; +} + +// -- member class of a class template +template<> +struct X0<void*>::Inner { }; + +X0<void*>::Inner inner0; + +// -- member class template of a class template +template<> +template<> +struct X0<void*>::InnerTemplate<int> { }; + +X0<void*>::InnerTemplate<int> inner_template0; + +// -- member function template of a class template +template<> +template<> +void X0<void*>::ft1(void*, const void*) { } + +void test_func_template(X0<void *> xvp, void *vp, const void *cvp) { + xvp.ft1(vp, cvp); +} + +// example from the standard: +template<class T> class stream; +template<> class stream<char> { /* ... */ }; +template<class T> class Array { /* ... */ }; +template<class T> void sort(Array<T>& v) { /* ... */ } +template<> void sort<char*>(Array<char*>&) ; diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp new file mode 100644 index 0000000..b81c1e7 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class T> class X; +template<> class X<int>; // expected-note{{forward}} +X<int>* p; + +X<int> x; // expected-error{{incomplete type}} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp new file mode 100644 index 0000000..5fa2f62 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class T> class Array { /* ... */ }; +template<class T> void sort(Array<T>& v); + +// explicit specialization for sort(Array<int>&) +// with deduced template-argument of type int +template<> void sort(Array<int>&); diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp new file mode 100644 index 0000000..fb6d1be --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template<typename T> void f(T); + +template<> void f(int) { } +void f(int) { } diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp new file mode 100644 index 0000000..121cb8e --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +template<class T> void f(T) { /* ... */ } +template<class T> inline void g(T) { /* ... */ } + +// CHECK: define void @_Z1gIiEvT_ +template<> void g<>(int) { /* ... */ } + +template<class T> +struct X { + void f() { } + void g(); + void h(); +}; + +template<class T> +void X<T>::g() { +} + +template<class T> +inline void X<T>::h() { +} + +// CHECK: define void @_ZN1XIiE1fEv +template<> void X<int>::f() { } + +// CHECK: define void @_ZN1XIiE1hEv +template<> void X<int>::h() { } + +// CHECK: define linkonce_odr void @_Z1fIiEvT_ +template<> inline void f<>(int) { /* ... */ } + +// CHECK: define linkonce_odr void @_ZN1XIiE1gEv +template<> inline void X<int>::g() { } + +void test(X<int> xi) { + f(17); + g(17); + xi.f(); + xi.g(); + xi.h(); +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp new file mode 100644 index 0000000..72f33df --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct NonDefaultConstructible { + NonDefaultConstructible(const NonDefaultConstructible&); // expected-note{{candidate constructor}} +}; + +template<typename T, typename U> +struct X { + static T member; +}; + +template<typename T, typename U> +T X<T, U>::member; // expected-error{{no matching constructor}} + +// Okay; this is a declaration, not a definition. +template<> +NonDefaultConstructible X<NonDefaultConstructible, long>::member; + +NonDefaultConstructible &test(bool b) { + return b? X<NonDefaultConstructible, int>::member // expected-note{{instantiation}} + : X<NonDefaultConstructible, long>::member; +} + +namespace rdar9422013 { + template<int> + struct X { + struct Inner { + static unsigned array[17]; + }; + }; + + template<> unsigned X<1>::Inner::array[]; // okay +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp new file mode 100644 index 0000000..c7597e9 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T> struct A { + void f(T); + template<class X1> void g1(T, X1); + template<class X2> void g2(T, X2); + void h(T) { } +}; + +// specialization +template<> void A<int>::f(int); + +// out of class member template definition +template<class T> template<class X1> void A<T>::g1(T, X1) { } + +// member template specialization +template<> template<class X1> void A<int>::g1(int, X1); + +// member template specialization +template<> template<> + void A<int>::g1(int, char); // X1 deduced as char + +template<> template<> + void A<int>::g2<char>(int, char); // X2 specified as char + // member specialization even if defined in class definition + +template<> void A<int>::h(int) { } + +namespace PR10024 { + template <typename T> + struct Test{ + template <typename U> + void get(U i) {} + }; + + template <typename T> + template <> + void Test<T>::get<double>(double i) {} // expected-error{{cannot specialize (with 'template<>') a member of an unspecialized template}} +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp new file mode 100644 index 0000000..56231e2 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T1> +class A { + template<class T2> class B { + void mf(); + }; +}; + +template<> template<> class A<int>::B<double>; +template<> template<> void A<char>::B<char>::mf(); + +template<> void A<char>::B<int>::mf(); // expected-error{{requires 'template<>'}} + +namespace test1 { + template <class> class A { + static int foo; + static int bar; + }; + typedef A<int> AA; + + template <> int AA::foo = 0; + int AA::bar = 1; // expected-error {{template specialization requires 'template<>'}} + int A<float>::bar = 2; // expected-error {{template specialization requires 'template<>'}} + + template <> class A<double> { + public: + static int foo; + static int bar; + }; + + typedef A<double> AB; + template <> int AB::foo = 0; // expected-error{{extraneous 'template<>'}} + int AB::bar = 1; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp new file mode 100644 index 0000000..4d175a8 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T1> class A { + template<class T2> class B { + template<class T3> void mf1(T3); + void mf2(); + }; +}; + +template<> template<class X> +class A<long>::B { }; + +template<> template<> template<class T> + void A<int>::B<double>::mf1(T t) { } + +template<> template<> template<class T> +void A<long>::B<double>::mf1(T t) { } // expected-error{{does not match}} + +// FIXME: This diagnostic could probably be better. +template<class Y> template<> + void A<Y>::B<double>::mf2() { } // expected-error{{does not refer}} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp new file mode 100644 index 0000000..1c2ea7e --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X { + template<typename U> struct Inner { }; + + template<typename U> void f(T, U) { } +}; + +template<> template<typename U> +struct X<int>::Inner { + U member; +}; + +template<> template<typename U> +void X<int>::f(int x, U y) { + x = y; // expected-error{{incompatible type}} +} + +void test(X<int> xi, X<long> xl, float *fp) { + X<int>::Inner<float*> xii; + xii.member = fp; + xi.f(17, 25); + xi.f(17, 3.14159); + xi.f(17, fp); // expected-note{{instantiation}} + X<long>::Inner<float*> xli; + + xli.member = fp; // expected-error{{no member}} + xl.f(17, fp); // okay +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp new file mode 100644 index 0000000..b0a19fb --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp @@ -0,0 +1,302 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %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{{does not enclose namespace}} +} + +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{{does not enclose namespace}} +} + +// -- 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{{does not enclose namespace}} +} + + +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); +} + +namespace has_inline_namespaces { + inline namespace inner { + template<class T> void f(T&); + + template<class T> + struct X0 { + struct MemberClass; + + void mem_func(); + + template<typename U> + struct MemberClassTemplate; + + template<typename U> + void mem_func_template(U&); + + static int value; + }; + } + + struct X1; + struct X2; + + // An explicit specialization whose declarator-id is not qualified + // shall be declared in the nearest enclosing namespace of the + // template, or, if the namespace is inline (7.3.1), any namespace + // from its enclosing namespace set. + template<> void f(X1&); + template<> void f<X2>(X2&); + + template<> struct X0<X1> { }; + + template<> struct X0<X2>::MemberClass { }; + + template<> void X0<X2>::mem_func(); + + template<> template<typename T> struct X0<X2>::MemberClassTemplate { }; + + template<> template<typename T> void X0<X2>::mem_func_template(T&) { } + + template<> int X0<X2>::value = 12; +} + +struct X3; +struct X4; + +template<> void has_inline_namespaces::f(X3&); +template<> void has_inline_namespaces::f<X4>(X4&); + +template<> struct has_inline_namespaces::X0<X3> { }; + +template<> struct has_inline_namespaces::X0<X4>::MemberClass { }; + +template<> void has_inline_namespaces::X0<X4>::mem_func(); + +template<> template<typename T> +struct has_inline_namespaces::X0<X4>::MemberClassTemplate { }; + +template<> template<typename T> +void has_inline_namespaces::X0<X4>::mem_func_template(T&) { } + +template<> int has_inline_namespaces::X0<X4>::value = 13; diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp new file mode 100644 index 0000000..c972bf7 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp @@ -0,0 +1,252 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %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) { // expected-note{{here}} + 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{{does not enclose namespace}} +} + +template<> void N0::f0(double); // expected-warning{{C++11 extension}} +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 2{{here}} + static T member; // expected-note{{here}} + + void f1(T t) { // expected-note{{explicitly specialized declaration is here}} + t = 17; + } + + struct Inner : public T { }; // expected-note 3{{here}} + + template<typename U> + struct InnerTemplate : public T { }; // expected-note 2{{explicitly specialized}} \ + // expected-error{{base specifier}} + + template<typename U> + void ft1(T t, U u); // expected-note{{explicitly specialized}} +}; + +} + +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> { }; // expected-warning{{C++11 extension}} +N0::X0<void> test_X0; + +namespace N1 { + template<> struct N0::X0<const void> { }; // expected-error{{originally}} +} + +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 *) { } // expected-warning{{member function specialization}} + +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; // expected-warning{{C++11 extension}} + +template<> float N0::X0<float>::member = 3.14f; + +namespace N1 { + template<> double N0::X0<double>::member = 3.14; // expected-error{{does not enclose namespace}} +} + +// -- 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 { }; // expected-warning{{C++11 extension}} + +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> { }; // expected-warning{{class template specialization}} + +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) { } // expected-warning{{function template specialization}} + +namespace N1 { + template<> template<> + void N0::X0<void*>::ft1(void *, long) { } // expected-error{{does not enclose namespace}} +} + + +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); +} + +namespace PR8979 { + template<typename Z> + struct X0 { + template <class T, class U> class Inner; + struct OtherInner; + template<typename T, typename U> void f(Inner<T, U>&); + + typedef Inner<OtherInner, OtherInner> MyInner; + template<> void f(MyInner&); // expected-error{{cannot specialize a function 'f' within class scope}} + }; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp new file mode 100644 index 0000000..86cdcf8 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<typename T> +void f(T); + +template<typename T> +struct A { }; + +struct X { + template<> friend void f<int>(int); // expected-error{{in a friend}} + template<> friend class A<int>; // expected-error{{cannot be a friend}} + + friend void f<float>(float); // okay + friend class A<float>; // okay +}; diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp new file mode 100644 index 0000000..ab26f40 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X { + void mf1(T); + template<typename U> void mf2(T, U); // expected-note{{previous}} +}; + +template<> +void X<int>::mf1(int i = 17) // expected-error{{default}} +{ +} + +template<> template<> +void X<int>::mf2(int, int = 17) // expected-error{{default}} +{ } + +template<> template<typename U> +void X<int>::mf2(int, U = U()) // expected-error{{default}} +{ +} + +template<> +struct X<float> { + void mf1(float); +}; + +void X<float>::mf1(float = 3.14f) // okay +{ +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp new file mode 100644 index 0000000..84841cb --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace N { + template<class T> class X; +} + +template<> class X<int> { /* ... */ }; // expected-error {{non-template class 'X'}} + +namespace N { + +template<> class X<char*> { /* ... */ }; // OK: X is a template + +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp new file mode 100644 index 0000000..772aef6 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct IntHolder { // expected-note{{here}} // expected-note 2{{candidate constructor (the implicit copy constructor)}} + IntHolder(int); // expected-note 2{{candidate constructor}} +}; + +template<typename T, typename U> +struct X { // expected-note{{here}} + void f() { + T t; // expected-error{{no matching}} + } + + void g() { } + + struct Inner { // expected-error{{implicit default}} + T value; // expected-note {{member is declared here}} + }; + + static T value; +}; + +template<typename T, typename U> +T X<T, U>::value; // expected-error{{no matching constructor}} + +IntHolder &test_X_IntHolderInt(X<IntHolder, int> xih) { + xih.g(); // okay + xih.f(); // expected-note{{instantiation}} + + X<IntHolder, int>::Inner inner; // expected-note {{first required here}} + + return X<IntHolder, int>::value; // expected-note{{instantiation}} +} + +// Explicitly specialize the members of X<IntHolder, long> to not cause +// problems with instantiation. +template<> +void X<IntHolder, long>::f() { } + +template<> +struct X<IntHolder, long>::Inner { + Inner() : value(17) { } + IntHolder value; +}; + +template<> +IntHolder X<IntHolder, long>::value = 17; + +IntHolder &test_X_IntHolderInt(X<IntHolder, long> xih) { + xih.g(); // okay + xih.f(); // okay, uses specialization + + X<IntHolder, long>::Inner inner; // okay, uses specialization + + return X<IntHolder, long>::value; // okay, uses specialization +} + +template<> +X<IntHolder, long>::X() { } // expected-error{{instantiated member}} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp new file mode 100644 index 0000000..f49190e --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template<class T> struct A { + struct B { }; + template<class U> struct C { }; +}; + template<> struct A<int> { + void f(int); +}; +void h() { + A<int> a; + a.f(16); +} +// A<int>::f must be defined somewhere +// template<> not used for a member of an // explicitly specialized class template +void A<int>::f(int) { /* ... */ } + template<> struct A<char>::B { + void f(); +}; +// template<> also not used when defining a member of // an explicitly specialized member class +void A<char>::B::f() { /* ... */ } + template<> template<class U> struct A<char>::C { + void f(); +}; + +template<> +template<class U> void A<char>::C<U>::f() { /* ... */ } + template<> struct A<short>::B { + void f(); +}; +template<> void A<short>::B::f() { /* ... */ } // expected-error{{no function template matches function template specialization 'f'}} + template<> template<class U> struct A<short>::C { + void f(); +}; +template<class U> void A<short>::C<U>::f() { /* ... */ } // expected-error{{template parameter list matching the non-templated nested type 'A<short>' should be empty ('template<>')}} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp new file mode 100644 index 0000000..512ea47 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct IntHolder { + IntHolder(int); +}; + +template<typename T, typename U> +struct X { + void f() { + T t; + } + + void g() { } + + struct Inner { + T value; + }; + + static T value; +}; + +template<typename T, typename U> +T X<T, U>::value; + +// Explicitly specialize the members of X<IntHolder, long> to not cause +// problems with instantiation, but only provide declarations (not definitions). +template<> +void X<IntHolder, long>::f(); + +template<> +struct X<IntHolder, long>::Inner; // expected-note{{forward declaration}} + +template<> +IntHolder X<IntHolder, long>::value; + +IntHolder &test_X_IntHolderInt(X<IntHolder, long> xih) { + xih.g(); // okay + xih.f(); // okay, uses specialization + + X<IntHolder, long>::Inner inner; // expected-error {{incomplete}} + + return X<IntHolder, long>::value; // okay, uses specialization +} + + +template<class T> struct A { + void f(T) { /* ... */ } +}; + +template<> struct A<int> { + void f(int); +}; + +void h() { + A<int> a; + a.f(16); // A<int>::f must be defined somewhere +} + +// explicit specialization syntax not used for a member of +// explicitly specialized class template specialization +void A<int>::f(int) { /* ... */ } diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp new file mode 100644 index 0000000..f539471 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X0 { + void f(); + + template<typename U> + void g(U); + + struct Nested { + }; + + static T member; +}; + +int &use_X0_int(X0<int> x0i, // expected-note{{implicit instantiation first required here}} + int i) { + x0i.f(); // expected-note{{implicit instantiation first required here}} + x0i.g(i); // expected-note{{implicit instantiation first required here}} + X0<int>::Nested nested; // expected-note{{implicit instantiation first required here}} + return X0<int>::member; // expected-note{{implicit instantiation first required here}} +} + +template<> +void X0<int>::f() { // expected-error{{after instantiation}} +} + +template<> template<> +void X0<int>::g(int) { // expected-error{{after instantiation}} +} + +template<> +struct X0<int>::Nested { }; // expected-error{{after instantiation}} + +template<> +int X0<int>::member = 17; // expected-error{{after instantiation}} + +template<> +struct X0<int> { }; // expected-error{{after instantiation}} + +// Example from the standard +template<class T> class Array { /* ... */ }; + +template<class T> void sort(Array<T>& v) { /* ... */ } + +struct String {}; + +void f(Array<String>& v) { + + sort(v); // expected-note{{required}} + // use primary template + // sort(Array<T>&), T is String +} + +template<> void sort<String>(Array<String>& v); // // expected-error{{after instantiation}} +template<> void sort<>(Array<char*>& v); // OK: sort<char*> not yet used + +namespace PR6160 { + template<typename T> void f(T); + template<> void f(int); + extern template void f(int); + template<> void f(int) { } +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp new file mode 100644 index 0000000..d4ce01f --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace N { + template<class T> class X { /* ... */ }; + template<class T> class Y { /* ... */ }; + template<> class X<int> { /* ... */ }; + template<> class Y<double>; + + const unsigned NumElements = 17; +} + +template<> class N::Y<double> { + int array[NumElements]; +}; diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp new file mode 100644 index 0000000..80f0598 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +template<typename T> +struct X { + void f() {} +}; + +template inline void X<int>::f(); // expected-error{{explicit instantiation cannot be 'inline'}} + +template<typename T> +struct Y { + constexpr int f() { return 0; } +}; + +template constexpr int Y<int>::f(); // expected-error{{explicit instantiation cannot be 'constexpr'}} + +template<typename T> +struct Z { + enum E : T { e1, e2 }; + T t; // expected-note {{refers here}} +}; + +template enum Z<int>::E; // expected-error {{enumerations cannot be explicitly instantiated}} +template int Z<int>::t; // expected-error {{explicit instantiation of 't' does not refer to}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp new file mode 100644 index 0000000..d0df305 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 -o - %s | FileCheck %s +template<typename T> +struct X { + static T member1; + static T member2; + static T member3; +}; + +template<typename T> +T X<T>::member1; + +template<typename T> +T X<T>::member2 = 17; + +// CHECK: @_ZN1XIiE7member1E = weak_odr global i32 0 +template int X<int>::member1; + +// CHECK: @_ZN1XIiE7member2E = weak_odr global i32 17 +template int X<int>::member2; + +// For implicit instantiation of +long& get(bool Cond1, bool Cond2) { + // CHECK: @_ZN1XIlE7member1E = weak_odr global i64 0 + // CHECK: @_ZN1XIlE7member2E = weak_odr global i64 17 + // CHECK: @_ZN1XIlE7member3E = external global i64 + return Cond1? X<long>::member1 + : Cond2? X<long>::member2 + : X<long>::member3; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp new file mode 100644 index 0000000..b426339 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct C { }; + +template<typename T> +struct X0 { + T value; // expected-error{{incomplete}} +}; + +// Explicitly instantiate a class template specialization +template struct X0<int>; +template struct X0<void>; // expected-note{{instantiation}} + +// Explicitly instantiate a function template specialization +template<typename T> +void f0(T t) { + ++t; // expected-error{{cannot increment}} +} + +template void f0(int); +template void f0<long>(long); +template void f0<>(unsigned); +template void f0(int C::*); // expected-note{{instantiation}} + +// Explicitly instantiate a member template specialization +template<typename T> +struct X1 { + template<typename U> + struct Inner { + T member1; + U member2; // expected-error{{incomplete}} + }; + + template<typename U> + void f(T& t, U u) { + t = u; // expected-error{{incompatible}} + } +}; + +template struct X1<int>::Inner<float>; +template struct X1<int>::Inner<double>; +template struct X1<int>::Inner<void>; // expected-note{{instantiation}} + +template void X1<int>::f(int&, float); +template void X1<int>::f<long>(int&, long); +template void X1<int>::f<>(int&, double); +template void X1<int>::f<>(int&, int*); // expected-note{{instantiation}} + +// Explicitly instantiate members of a class template +struct Incomplete; // expected-note{{forward declaration}} +struct NonDefaultConstructible { // expected-note{{candidate constructor (the implicit copy constructor) not viable}} + NonDefaultConstructible(int); // expected-note{{candidate constructor}} +}; + +template<typename T, typename U> +struct X2 { + void f(T &t, U u) { + t = u; // expected-error{{incompatible}} + } + + struct Inner { + T member1; + U member2; // expected-error{{incomplete}} + }; + + static T static_member1; + static U static_member2; +}; + +template<typename T, typename U> +T X2<T, U>::static_member1 = 17; // expected-error{{cannot initialize}} + +template<typename T, typename U> +U X2<T, U>::static_member2; // expected-error{{no matching}} + +template void X2<int, float>::f(int &, float); +template void X2<int, float>::f(int &, double); // expected-error{{does not refer}} +template void X2<int, int*>::f(int&, int*); // expected-note{{instantiation}} + +template struct X2<int, float>::Inner; +template struct X2<int, Incomplete>::Inner; // expected-note{{instantiation}} + +template int X2<int, float>::static_member1; +template int* X2<int*, float>::static_member1; // expected-note{{instantiation}} +template + NonDefaultConstructible X2<NonDefaultConstructible, int>::static_member1; + +template + NonDefaultConstructible X2<int, NonDefaultConstructible>::static_member2; // expected-note{{instantiation}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp new file mode 100644 index 0000000..290a874 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X0 { + void f(T&); + + struct Inner; + + static T static_var; +}; + +template<typename T> +void X0<T>::f(T& t) { + t = 1; // expected-error{{incompatible type}} +} + +template<typename T> +struct X0<T>::Inner { + T member; +}; + +template<typename T> +T X0<T>::static_var = 1; // expected-error{{cannot initialize}} + +extern template struct X0<void*>; +template struct X0<void*>; // expected-note 2{{instantiation}} + +template struct X0<int>; // expected-note 4{{explicit instantiation definition is here}} + +extern template void X0<int>::f(int&); // expected-error{{follows explicit instantiation definition}} +extern template struct X0<int>::Inner; // expected-error{{follows explicit instantiation definition}} +extern template int X0<int>::static_var; // expected-error{{follows explicit instantiation definition}} +extern template struct X0<int>; // expected-error{{follows explicit instantiation definition}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp new file mode 100644 index 0000000..4ca5428 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class X { + template <typename T> class Y {}; +}; + +class A { + class B {}; + class C {}; +}; + +// C++0x [temp.explicit] 14.7.2/11: +// The usual access checking rules do not apply to names used to specify +// explicit instantiations. +template class X::Y<A::B>; + +// As an extension, this rule is applied to explicit specializations as well. +template <> class X::Y<A::C> {}; diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp new file mode 100644 index 0000000..c756486 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +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. + diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp new file mode 100644 index 0000000..1dfcf0c --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -Wc++11-compat %s + +// Example from the standard +template<class T> class Array { void mf() { } }; + +template class Array<char>; +template void Array<int>::mf(); +template<class T> void sort(Array<T>& v) { /* ... */ } +template void sort(Array<char>&); +namespace N { + template<class T> void f(T&) { } +} +template void N::f<int>(int&); + + +template<typename T> +struct X0 { + struct Inner {}; + void f() { } + static T value; +}; + +template<typename T> +T X0<T>::value = 17; + +typedef X0<int> XInt; + +template struct XInt::Inner; // expected-warning{{template-id}} +template void XInt::f(); // expected-warning{{template-id}} +template int XInt::value; // expected-warning{{template-id}} + +namespace N { + template<typename T> + struct X1 { // expected-note{{explicit instantiation refers here}} + }; + + template<typename T> + void f1(T) {} // expected-note{{explicit instantiation refers here}} +} +using namespace N; + +template struct X1<int>; // expected-warning{{must occur in}} +template void f1(int); // expected-warning{{must occur in}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp new file mode 100644 index 0000000..1028830 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// If the name declared in the explicit instantiation is an +// unqualified name, the explicit instantiation shall appear in the +// namespace where its template is declared or, if that namespace is +// inline (7.3.1), any namespace from its enclosing namespace set. + +namespace has_inline_namespaces { + inline namespace inner { + template<class T> void f(T&) {} + + template<class T> + struct X0 { + struct MemberClass {}; + + void mem_func() {} + + template<typename U> + struct MemberClassTemplate {}; + + template<typename U> + void mem_func_template(U&) {} + + static int value; + }; + } + + template<typename T> int X0<T>::value = 17; + + struct X1 {}; + struct X2 {}; + + template void f(X1&); + template void f<X2>(X2&); + + template struct X0<X1>; + + template struct X0<X2>::MemberClass; + + template void X0<X2>::mem_func(); + + template struct X0<X2>::MemberClassTemplate<X1>; + + template void X0<X2>::mem_func_template(X1&); + + template int X0<X2>::value; +} + +struct X3; +struct X4; + +template void has_inline_namespaces::f(X3&); +template void has_inline_namespaces::f<X4>(X4&); + +template struct has_inline_namespaces::X0<X3>; + +template struct has_inline_namespaces::X0<X4>::MemberClass; + +template void has_inline_namespaces::X0<X4>::mem_func(); + +template +struct has_inline_namespaces::X0<X4>::MemberClassTemplate<X3>; + +template +void has_inline_namespaces::X0<X4>::mem_func_template(X3&); diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp new file mode 100644 index 0000000..38ae768 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s + +// A declaration of a function template shall be in scope at the point of the +// explicit instantiation of the function template. +template<typename T> void f0(T); +template void f0(int); // okay +template<typename T> void f0(T) { } + +// A definition of the class or class template containing a member function +// template shall be in scope at the point of the explicit instantiation of +// the member function template. +struct X0; // expected-note {{forward declaration}} +template<typename> struct X1; // expected-note 5{{declared here}} + +template void X0::f0<int>(int); // expected-error {{incomplete type}} +template void X1<int>::f0<int>(int); // expected-error {{implicit instantiation of undefined template}} + +// A definition of a class template or class member template shall be in scope +// at the point of the explicit instantiation of the class template or class +// member template. +template struct X1<float>; // expected-error{{explicit instantiation of undefined template}} + +template<typename T> +struct X2 { // expected-note 4{{refers here}} + template<typename U> + struct Inner; // expected-note{{declared here}} + + struct InnerClass; // expected-note{{forward declaration}} +}; + +template struct X2<int>::Inner<float>; // expected-error{{explicit instantiation of undefined template}} + +// A definition of a class template shall be in scope at the point of an +// explicit instantiation of a member function or a static data member of the +// class template. +template void X1<int>::f1(int); // expected-error {{undefined template}} +template void X1<int>::f1<int>(int); // expected-error {{undefined template}} + +template int X1<int>::member; // expected-error {{undefined template}} + +// A definition of a member class of a class template shall be in scope at the +// point of an explicit instantiation of the member class. +template struct X2<float>::InnerClass; // expected-error{{undefined member}} + +// If the declaration of the explicit instantiation names an implicitly-declared +// special member function (Clause 12), the program is ill-formed. +template X2<int>::X2(); // expected-error{{not an instantiation}} +template X2<int>::X2(const X2&); // expected-error{{not an instantiation}} +template X2<int>::~X2(); // expected-error{{not an instantiation}} +template X2<int> &X2<int>::operator=(const X2<int>&); // expected-error{{not an instantiation}} + + +// A definition of a class template is sufficient to explicitly +// instantiate a member of the class template which itself is not yet defined. +namespace PR7979 { + template <typename T> struct S { + void f(); + static void g(); + static int i; + struct S2 { + void h(); + }; + }; + + template void S<int>::f(); + template void S<int>::g(); + template int S<int>::i; + template void S<int>::S2::h(); + + template <typename T> void S<T>::f() {} + template <typename T> void S<T>::g() {} + template <typename T> int S<T>::i; + template <typename T> void S<T>::S2::h() {} +} + +namespace PR11599 { + template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}} + + extern template class BasicStringPiece<int>; // expected-error{{explicit instantiation of undefined template 'PR11599::BasicStringPiece<int>}} + template class BasicStringPiece<int>; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp new file mode 100644 index 0000000..09c428e --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s + +template<typename T> void f0(T); // expected-note{{here}} +template void f0(int); // expected-error{{explicit instantiation of undefined function template}} + +template<typename T> +struct X0 { + struct Inner; + + void f1(); // expected-note{{here}} + + static T value; // expected-note{{here}} +}; + +template void X0<int>::f1(); // expected-error{{explicit instantiation of undefined member function}} + +template int X0<int>::value; // expected-error{{explicit instantiation of undefined static data member}} + +template<> void f0(long); // expected-note{{previous template specialization is here}} +template void f0(long); // expected-warning{{explicit instantiation of 'f0<long>' that occurs after an explicit specialization will be ignored}} + +template<> void X0<long>::f1(); // expected-note{{previous template specialization is here}} +template void X0<long>::f1(); // expected-warning{{explicit instantiation of 'f1' that occurs after an explicit specialization will be ignored}} + +template<> struct X0<long>::Inner; // expected-note{{previous template specialization is here}} +template struct X0<long>::Inner; // expected-warning{{explicit instantiation of 'Inner' that occurs after an explicit specialization will be ignored}} + +template<> long X0<long>::value; // expected-note{{previous template specialization is here}} +template long X0<long>::value; // expected-warning{{explicit instantiation of 'value' that occurs after an explicit specialization will be ignored}} + +template<> struct X0<double>; // expected-note{{previous template specialization is here}} +template struct X0<double>; // expected-warning{{explicit instantiation of 'X0<double>' that occurs after an explicit specialization will be ignored}} + +// PR 6458 +namespace test0 { + template <class T> class foo { + int compare(T x, T y); + }; + + template <> int foo<char>::compare(char x, char y); + template <class T> int foo<T>::compare(T x, T y) { + // invalid at T=char; if we get a diagnostic here, we're + // inappropriately instantiating this template. + void *ptr = x; + } + extern template class foo<char>; // expected-warning {{extern templates are a C++11 extension}} + template class foo<char>; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp new file mode 100644 index 0000000..8422c51 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s + +namespace N { + template<class T> class Y { // expected-note{{explicit instantiation refers here}} + void mf() { } + }; +} + +template class Z<int>; // expected-error{{explicit instantiation of non-template class 'Z'}} + +// FIXME: This example from the standard is wrong; note posted to CWG reflector +// on 10/27/2009 +using N::Y; +template class Y<int>; // expected-warning{{must occur in}} + +template class N::Y<char*>; +template void N::Y<double>::mf(); diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp new file mode 100644 index 0000000..1382272 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<class T> class Array { /* ... */ }; +template<class T> void sort(Array<T>& v) { } + +// instantiate sort(Array<int>&) - template-argument deduced +template void sort<>(Array<int>&); + +template void sort(Array<long>&); + +template<typename T, typename U> void f0(T, U*) { } + +template void f0<int>(int, float*); +template void f0<>(double, float*); + +template<typename T> struct hash { }; +struct S { + bool operator==(const S&) const { return false; } +}; + +template<typename T> struct Hash_map { + void Method(const T& x) { h(x); } + hash<T> h; +}; + +Hash_map<S> *x; +const Hash_map<S> *foo() { + return x; +} + +template<> struct hash<S> { + int operator()(const S& k) const { + return 0; + } +}; diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp new file mode 100644 index 0000000..7398dca --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template<typename T> +struct X0 { + struct MemberClass { + T member; // expected-error{{with function type}} + }; + + T* f0(T* ptr) { + return ptr + 1; // expected-error{{pointer to the function}} + } + + static T* static_member; +}; + +template<typename T> +T* X0<T>::static_member = ((T*)0) + 1; // expected-error{{pointer to the function}} + +template class X0<int>; // okay + +template class X0<int(int)>; // expected-note 3{{requested here}} + +// Specialize everything, so that the explicit instantiation does not trigger +// any diagnostics. +template<> +struct X0<int(long)>::MemberClass { }; + +typedef int int_long_func(long); +template<> +int_long_func *X0<int_long_func>::f0(int_long_func *) { return 0; } + +template<> +int_long_func *X0<int(long)>::static_member; + +template class X0<int(long)>; + diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp new file mode 100644 index 0000000..550078a --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +template<typename T> +struct X0 { + struct MemberClass; + + T* f0(T* ptr); + + static T* static_member; +}; + +template class X0<int(int)>; // ok; nothing gets instantiated. + +template<typename T> +struct X0<T>::MemberClass { + T member; +}; + +template<typename T> +T* X0<T>::f0(T* ptr) { + return ptr + 1; +} + +template<typename T> +T* X0<T>::static_member = 0; + +template class X0<int>; // ok + + +template<typename T> +struct X1 { + enum class E { + e = T::error // expected-error 2{{no members}} + }; +}; +template struct X1<int>; // expected-note {{here}} + +extern template struct X1<char>; // ok + +template struct X1<char>; // expected-note {{here}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp new file mode 100644 index 0000000..04e7df5 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -O1 -emit-llvm -std=c++11 -o - %s | FileCheck %s + +template<typename T> +struct X0 { + void f(T &t) { + t = 0; + } + + void g(T &t); + + void h(T &t); + + static T static_var; +}; + +template<typename T> +inline void X0<T>::g(T & t) { + t = 0; +} + +template<typename T> +void X0<T>::h(T & t) { + t = 0; +} + +template<typename T> +T X0<T>::static_var = 0; + +extern template struct X0<int*>; + +int *&test(X0<int*> xi, int *ip) { + // CHECK: define available_externally void @_ZN2X0IPiE1fERS0_ + xi.f(ip); + // CHECK: define available_externally void @_ZN2X0IPiE1gERS0_ + xi.g(ip); + // CHECK: declare void @_ZN2X0IPiE1hERS0_ + xi.h(ip); + return X0<int*>::static_var; +} + +template<typename T> +void f0(T& t) { + t = 0; +} + +template<typename T> +inline void f1(T& t) { + t = 0; +} + +extern template void f0<>(int *&); +extern template void f1<>(int *&); + +void test_f0(int *ip, float *fp) { + // CHECK: declare void @_Z2f0IPiEvRT_ + f0(ip); + // CHECK: define linkonce_odr void @_Z2f0IPfEvRT_ + f0(fp); +} + +void test_f1(int *ip, float *fp) { + // CHECK: define available_externally void @_Z2f1IPiEvRT_ + f1(ip); + // CHECK: define linkonce_odr void @_Z2f1IPfEvRT_ + f1(fp); +} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp new file mode 100644 index 0000000..8649017 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +template<typename T> +struct X0 { + void f(T &t) { + t = 1; // expected-error{{incompatible type}} + } + + void g(T &t); + + void h(T &t); + + static T static_var; +}; + +template<typename T> +inline void X0<T>::g(T & t) { + t = 1; // expected-error{{incompatible type}} +} + +template<typename T> +void X0<T>::h(T & t) { + t = 1; +} + +template<typename T> +T X0<T>::static_var = 1; + +extern template struct X0<int*>; + +int *&test(X0<int*> xi, int *ip) { + xi.f(ip); // expected-note{{instantiation}} + xi.g(ip); // expected-note{{instantiation}} + xi.h(ip); + return X0<int*>::static_var; +} + +template<typename T> +void f0(T& t) { + t = 1; // expected-error{{incompatible type}} +} + +template<typename T> +inline void f1(T& t) { + t = 1; // expected-error 2{{incompatible type}} +} + +extern template void f0<>(int *&); +extern template void f1<>(int *&); + +void test_f0(int *ip, float *fp) { + f0(ip); + f0(fp); // expected-note{{instantiation}} +} + +void test_f1(int *ip, float *fp) { + f1(ip); // expected-note{{instantiation}} + f1(fp); // expected-note{{instantiation}} +} diff --git a/clang/test/CXX/temp/temp.spec/temp.inst/p1.cpp b/clang/test/CXX/temp/temp.spec/temp.inst/p1.cpp new file mode 100644 index 0000000..8684fc4 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.inst/p1.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// The implicit specialization of a class template specialuzation causes the +// implicit instantiation of the declarations, but not the definitions or +// default arguments, of: + +// FIXME: Many omitted cases + +// - scoped member enumerations +namespace ScopedEnum { + template<typename T> struct ScopedEnum1 { + enum class E { + e = T::error // expected-error {{'double' cannot be used prior to '::'}} + }; + }; + ScopedEnum1<int> se1; // ok + + template<typename T> struct ScopedEnum2 { + enum class E : T { // expected-error {{non-integral type 'void *' is an invalid underlying type}} + e = 0 + }; + }; + ScopedEnum2<void*> se2; // expected-note {{here}} + + template<typename T> struct UnscopedEnum3 { + enum class E : T { + e = 4 + }; + int arr[(int)E::e]; + }; + UnscopedEnum3<int> ue3; // ok + + ScopedEnum1<double>::E e1; // ok + ScopedEnum1<double>::E e2 = decltype(e2)::e; // expected-note {{in instantiation of enumeration 'ScopedEnum::ScopedEnum1<double>::E' requested here}} + + // The behavior for enums defined within function templates is not clearly + // specified by the standard. We follow the rules for enums defined within + // class templates. + template<typename T> + int f() { + enum class E { + e = T::error + }; + return (int)E(); + } + int test1 = f<int>(); + + template<typename T> + int g() { + enum class E { + e = T::error // expected-error {{has no members}} + }; + return E::e; // expected-note {{here}} + } + int test2 = g<int>(); // expected-note {{here}} +} + +// And it cases the implicit instantiations of the definitions of: + +// - unscoped member enumerations +namespace UnscopedEnum { + template<typename T> struct UnscopedEnum1 { + enum E { + e = T::error // expected-error {{'int' cannot be used prior to '::'}} + }; + }; + UnscopedEnum1<int> ue1; // expected-note {{here}} + + template<typename T> struct UnscopedEnum2 { + enum E : T { // expected-error {{non-integral type 'void *' is an invalid underlying type}} + e = 0 + }; + }; + UnscopedEnum2<void*> ue2; // expected-note {{here}} + + template<typename T> struct UnscopedEnum3 { + enum E : T { + e = 4 + }; + int arr[E::e]; + }; + UnscopedEnum3<int> ue3; // ok + + template<typename T> + int f() { + enum E { + e = T::error // expected-error {{has no members}} + }; + return (int)E(); + } + int test1 = f<int>(); // expected-note {{here}} + + template<typename T> + int g() { + enum E { + e = T::error // expected-error {{has no members}} + }; + return E::e; + } + int test2 = g<int>(); // expected-note {{here}} +} + +// FIXME: +//- - member anonymous unions diff --git a/clang/test/CXX/temp/temp.spec/temp.inst/p11.cpp b/clang/test/CXX/temp/temp.spec/temp.inst/p11.cpp new file mode 100644 index 0000000..8184071 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.inst/p11.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify -emit-llvm-only %s + +// rdar://problem/7838962 +namespace test0 { + template<typename T> unsigned f0() { + return T::MaxSize; // expected-error {{'int' cannot be used prior to '::'}} + }; + template<typename T> struct A { + void Allocate(unsigned Alignment + = f0<T>()) // expected-note {{in instantiation}} + {} + }; + void f1(A<int> x) { x.Allocate(); } + +} diff --git a/clang/test/CXX/temp/temp.type/p1-0x.cpp b/clang/test/CXX/temp/temp.type/p1-0x.cpp new file mode 100644 index 0000000..35d00c2 --- /dev/null +++ b/clang/test/CXX/temp/temp.type/p1-0x.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +namespace Old { + template<template<class> class TT> struct X { }; + template<class> struct Y { }; + template<class T> using Z = Y<T>; + X<Y> y; + X<Z> z; + + using SameType = decltype(y); // expected-note {{here}} + using SameType = decltype(z); // expected-error {{different types}} +} + +namespace New { + template<class T> struct X { }; + template<class> struct Y { }; + template<class T> using Z = Y<T>; + X<Y<int>> y; + X<Z<int>> z; + + using SameType = decltype(y); + using SameType = decltype(z); // ok +} |