diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:02:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:02:28 +0000 |
commit | 7442d6faa2719e4e7d33a7021c406c5a4facd74d (patch) | |
tree | c72b9241553fc9966179aba84f90f17bfa9235c3 /test/CXX | |
parent | b52119637f743680a99710ce5fdb6646da2772af (diff) |
Notes
Diffstat (limited to 'test/CXX')
44 files changed, 1169 insertions, 97 deletions
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp index f32b23976547..18b18834bb48 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp @@ -1,17 +1,25 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s struct X0 { + X0(); + X0(int); X0 f1(); X0 f2(); + typedef int A; + typedef X0 B; }; template<typename T> -struct X1 { +struct X1 : X0 { + X1(); X1<T>(int); (X1<T>)(float); X1 f2(); X1 f2(int); X1 f2(float); + X1 f2(double); + X1 f2(short); + X1 f2(long); }; // Error recovery: out-of-line constructors whose names have template arguments. @@ -19,13 +27,88 @@ template<typename T> X1<T>::X1<T>(int) { } // expected-error{{out-of-line constr 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}} +X0::X0 X0::f1() { return X0(); } // expected-error{{qualified reference to 'X0' is a constructor name rather than a type in this context}} 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> X1<T>::X1<T> X1<T>::f2() { } // expected-error{{missing 'typename'}} +template<typename T> X1<T>::X1<T> (X1<T>::f2)(int) { } // expected-error{{missing 'typename'}} template<typename T> struct X1<T>::X1<T> (X1<T>::f2)(float) { } +template<typename T> struct X1<T>::X1 (X1<T>::f2)(double) { } +template<typename T> typename X1<T>::template X1<T> X1<T>::f2(short) { } // expected-warning {{qualified reference to 'X1' is a constructor name rather than a template name in this context}} +template<typename T> typename X1<T>::template X1<T> (X1<T>::f2)(long) { } // expected-warning {{qualified reference to 'X1' is a constructor name rather than a template name in this context}} + +void x1test(X1<int> x1i) { + x1i.f2(); + x1i.f2(0); + x1i.f2(0.f); + x1i.f2(0.); +} + +void other_contexts() { + X0::X0 x0; // expected-error{{qualified reference to 'X0' is a constructor name rather than a type in this context}} + X1<int>::X1 x1a; // expected-error{{qualified reference to 'X1' is a constructor name rather than a type in this context}} + X1<int>::X1<float> x1b; // expected-error{{qualified reference to 'X1' is a constructor name rather than a template name in this context}} + + X0::B ok1; + X0::X0::A ok2; + X0::X0::X0 x0b; // expected-error{{qualified reference to 'X0' is a constructor name rather than a type in this context}} + X1<int>::X0 ok3; + X1<int>::X0::X0 x0c; // expected-error{{qualified reference to 'X0' is a constructor name rather than a type in this context}} + X1<int>::X1<float>::X0 ok4; + + { + typename X0::X0 tn1; // expected-warning{{qualified reference to 'X0' is a constructor name rather than a type in this context}} expected-warning 0-1{{typename}} + typename X1<int>::X1<float> tn2; // expected-warning{{qualified reference to 'X1' is a constructor name rather than a template name in this context}} expected-warning 0-1{{typename}} + typename X0::B ok1; // expected-warning 0-1{{typename}} + typename X1<int>::X0 ok2; // expected-warning 0-1{{typename}} + } + + { + struct X0::X0 tag1; + struct X1<int>::X1 tag2; + struct X1<int>::X1<int> tag3; + } + + int a; + { + X0::X0(a); // expected-error{{qualified reference to 'X0' is a constructor name rather than a type in this context}} + } +} + +template<typename T> void in_instantiation_x0() { + typename T::X0 x0; // expected-warning{{qualified reference to 'X0' is a constructor name rather than a type in this context}} + typename T::A a; + typename T::B b; +} +template void in_instantiation_x0<X0>(); // expected-note {{instantiation of}} + +template<typename T> void in_instantiation_x1() { + typename T::X1 x1; // expected-warning{{qualified reference to 'X1' is a constructor name rather than a type in this context}} + typename T::template X1<int> x1i; // expected-warning{{qualified reference to 'X1' is a constructor name rather than a template name in this context}} + typename T::X0 x0; +} +template void in_instantiation_x1<X1<int> >(); // expected-note {{instantiation of}} + +namespace sfinae { + template<typename T> void f(typename T::X0 *) = delete; // expected-warning 0-1{{extension}} + template<typename T> void f(...); + void g() { f<X0>(0); } +} + +namespace versus_injected_class_name { + template <typename T> struct A : T::B { + struct T::B *p; + typename T::B::type a; + A() : T::B() {} + + typename T::B b; // expected-warning {{qualified reference to 'B' is a constructor name rather than a type in this context}} + }; + struct B { + typedef int type; + }; + template struct A<B>; // expected-note {{in instantiation of}} +} // We have a special case for lookup within using-declarations that are // member-declarations: foo::bar::baz::baz always names baz's constructor @@ -109,7 +192,7 @@ namespace InhCtor { // FIXME: Consider reusing the same diagnostic between dependent and non-dependent contexts typedef int I; struct UsingInt { - using I::I; // expected-error {{'I' (aka 'int') is not a class, namespace, or enumeration}} + using I::I; // expected-error {{'InhCtor::I' (aka 'int') is not a class, namespace, or enumeration}} }; template<typename T> struct UsingIntTemplate { using T::T; // expected-error {{type 'int' cannot be used prior to '::' because it has no members}} diff --git a/test/CXX/class.derived/class.abstract/p16.cpp b/test/CXX/class.derived/class.abstract/p16.cpp index 29adbccac479..80396a96d9ec 100644 --- a/test/CXX/class.derived/class.abstract/p16.cpp +++ b/test/CXX/class.derived/class.abstract/p16.cpp @@ -35,13 +35,15 @@ struct E : D {}; // expected-error@-1 {{deleted function '~E' cannot override a non-deleted function}} // expected-note@-2 {{destructor of 'E' is implicitly deleted because base class 'D' has an inaccessible destructor}} // expected-error@-3 {{deleted function 'operator=' cannot override a non-deleted function}} -// expected-note@-4 {{copy assignment operator of 'E' is implicitly deleted because base class 'D' has an inaccessible copy assignment operator}} +// expected-note@-4 {{while declaring the implicit copy assignment operator for 'E'}} +// expected-note@-5 {{copy assignment operator of 'E' is implicitly deleted because base class 'D' has an inaccessible copy assignment operator}} struct F : D {}; struct G : D {}; // expected-error@-1 {{deleted function '~G' cannot override a non-deleted function}} -// expected-note@-2 {{move assignment operator of 'G' is implicitly deleted because base class 'D' has an inaccessible move assignment operator}} +// expected-note@-2 {{destructor of 'G' is implicitly deleted because base class 'D' has an inaccessible destructor}} // expected-error@-3 {{deleted function 'operator=' cannot override a non-deleted function}} -// expected-note@-4 {{destructor of 'G' is implicitly deleted because base class 'D' has an inaccessible destructor}} +// expected-note@-4 {{while declaring the implicit move assignment operator for 'G'}} +// expected-note@-5 {{move assignment operator of 'G' is implicitly deleted because base class 'D' has an inaccessible move assignment operator}} struct H : D { H &operator=(H&&) = default; // expected-error@-1 {{deleted function 'operator=' cannot override a non-deleted function}} diff --git a/test/CXX/class.derived/class.member.lookup/p10.cpp b/test/CXX/class.derived/class.member.lookup/p10.cpp new file mode 100644 index 000000000000..afd87521885a --- /dev/null +++ b/test/CXX/class.derived/class.member.lookup/p10.cpp @@ -0,0 +1,114 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -Wshadow-all + +// Basic cases, ambiguous paths, and fields with different access +class A { +public: + int x; // expected-note 2{{declared here}} +protected: + int y; // expected-note 2{{declared here}} +private: + int z; +}; + +struct B : A { +}; + +struct C : A { +}; + +struct W { + int w; // expected-note {{declared here}} +}; + +struct U : W { +}; + +struct V : W { +}; + +class D { +public: + char w; // expected-note {{declared here}} +private: + char x; +}; + +// Check direct inheritance and multiple paths to the same base. +class E : B, C, D, U, V +{ + unsigned x; // expected-warning {{non-static data member 'x' of 'E' shadows member inherited from type 'A'}} + char y; // expected-warning {{non-static data member 'y' of 'E' shadows member inherited from type 'A'}} + double z; + char w; // expected-warning {{non-static data member 'w' of 'E' shadows member inherited from type 'D'}} expected-warning {{non-static data member 'w' of 'E' shadows member inherited from type 'W'}} +}; + +// Virtual inheritance +struct F : virtual A { +}; + +struct G : virtual A { +}; + +class H : F, G { + int x; // expected-warning {{non-static data member 'x' of 'H' shadows member inherited from type 'A'}} + int y; // expected-warning {{non-static data member 'y' of 'H' shadows member inherited from type 'A'}} + int z; +}; + +// Indirect inheritance +struct I { + union { + int x; // expected-note {{declared here}} + int y; + }; +}; + +struct J : I { + int x; // expected-warning {{non-static data member 'x' of 'J' shadows member inherited from type 'I'}} +}; + +// non-access paths +class N : W { +}; + +struct K { + int y; +}; + +struct L : private K { +}; + +struct M : L { + int y; + int w; +}; + +// Multiple ambiguous paths with different accesses +struct A1 { + int x; // expected-note {{declared here}} +}; + +class B1 : A1 { +}; + +struct B2 : A1 { +}; + +struct C1 : B1, B2 { +}; + +class D1 : C1 { +}; + +struct D2 : C1 { +}; + +class D3 : C1 { +}; + +struct E1 : D1, D2, D3{ + int x; // expected-warning {{non-static data member 'x' of 'E1' shadows member inherited from type 'A1'}} +}; + + + diff --git a/test/CXX/class.derived/class.member.lookup/p6.cpp b/test/CXX/class.derived/class.member.lookup/p6.cpp index 72398819263f..0a400a2405e9 100644 --- a/test/CXX/class.derived/class.member.lookup/p6.cpp +++ b/test/CXX/class.derived/class.member.lookup/p6.cpp @@ -1,24 +1,24 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify %s -Wshadow-field class V { public: int f(); - int x; + int x; // expected-note {{declared here}} }; class W { public: int g(); // expected-note{{member found by ambiguous name lookup}} - int y; // expected-note{{member found by ambiguous name lookup}} + int y; // expected-note{{member found by ambiguous name lookup}} expected-note {{declared here}} }; class B : public virtual V, public W { public: int f(); - int x; + int x; // expected-warning {{non-static data member 'x' of 'B' shadows member inherited from type 'V'}} int g(); // expected-note{{member found by ambiguous name lookup}} - int y; // expected-note{{member found by ambiguous name lookup}} + int y; // expected-note{{member found by ambiguous name lookup}} expected-warning {{non-static data member 'y' of 'B' shadows member inherited from type 'W'}} }; class C : public virtual V, public W { }; diff --git a/test/CXX/class.derived/class.member.lookup/p7.cpp b/test/CXX/class.derived/class.member.lookup/p7.cpp index a785e0f90e57..775057792c5c 100644 --- a/test/CXX/class.derived/class.member.lookup/p7.cpp +++ b/test/CXX/class.derived/class.member.lookup/p7.cpp @@ -1,11 +1,9 @@ -// RUN: %clang_cc1 -verify %s +// RUN: %clang_cc1 -verify %s -Wshadow-field -// expected-no-diagnostics - -struct A { int n; }; -struct B { float n; }; +struct A { int n; }; // expected-note {{declared here}} +struct B { float n; }; // expected-note {{declared here}} struct C : A, B {}; struct D : virtual C {}; -struct E : virtual C { char n; }; +struct E : virtual C { char n; }; // expected-warning {{non-static data member 'n' of 'E' shadows member inherited from type 'A'}} expected-warning {{non-static data member 'n' of 'E' shadows member inherited from type 'B'}} struct F : D, E {} f; char &k = f.n; diff --git a/test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/class-template-decl.cpp b/test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/class-template-decl.cpp new file mode 100644 index 000000000000..d1ad0404ef42 --- /dev/null +++ b/test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/class-template-decl.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s + +namespace nodiag { + +template <typename T> requires bool(T()) +struct A; +template <typename U> requires bool(U()) +struct A; + +} // end namespace nodiag + +namespace diag { + +template <typename T> requires true // expected-note{{previous template declaration is here}} +struct A; +template <typename T> struct A; // expected-error{{associated constraints differ in template redeclaration}} + +template <typename T> struct B; // expected-note{{previous template declaration is here}} +template <typename T> requires true // expected-error{{associated constraints differ in template redeclaration}} +struct B; + +template <typename T> requires true // expected-note{{previous template declaration is here}} +struct C; +template <typename T> requires !0 // expected-error{{associated constraints differ in template redeclaration}} +struct C; + +} // end namespace diag + +namespace nodiag { + +struct AA { + template <typename T> requires someFunc(T()) + struct A; +}; + +template <typename T> requires someFunc(T()) +struct AA::A { }; + +struct AAF { + template <typename T> requires someFunc(T()) + friend struct AA::A; +}; + +} // end namespace nodiag + +namespace diag { + +template <unsigned N> +struct TA { + template <template <unsigned> class TT> requires TT<N>::happy // expected-note 2{{previous template declaration is here}} + struct A; + + struct AF; +}; + +template <unsigned N> +template <template <unsigned> class TT> struct TA<N>::A { }; // expected-error{{associated constraints differ in template redeclaration}} + +template <unsigned N> +struct TA<N>::AF { + template <template <unsigned> class TT> requires TT<N + 0>::happy // expected-error{{associated constraints differ in template redeclaration}} + friend struct TA::A; +}; + +} // end namespace diag diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp index a27cea84db45..58c7c0cfac8b 100644 --- a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp @@ -23,7 +23,38 @@ template <> class [[deprecated]] X<int> {}; // expected-note {{'X<int>' has been X<char> x1; X<int> x2; // expected-warning {{'X<int>' is deprecated}} -template <typename T> class [[deprecated]] X2 {}; +template <typename T> class [[deprecated]] X2 {}; //expected-note {{'X2<char>' has been explicitly marked deprecated here}} template <> class X2<int> {}; -X2<char> x3; // FIXME: no warning! -X2<int> x4; +X2<char> x3; // expected-warning {{'X2<char>' is deprecated}} +X2<int> x4; // No warning, the specialization removes it. + +template <typename T> class [[deprecated]] X3; //expected-note {{'X3<char>' has been explicitly marked deprecated here}} +template <> class X3<int>; +X3<char> *x5; // expected-warning {{'X3<char>' is deprecated}} +X3<int> *x6; // No warning, the specialization removes it. + +template <typename T> struct A; +A<int> *p; +template <typename T> struct [[deprecated]] A;//expected-note {{'A<int>' has been explicitly marked deprecated here}} expected-note {{'A<float>' has been explicitly marked deprecated here}} +A<int> *q; // expected-warning {{'A<int>' is deprecated}} +A<float> *r; // expected-warning {{'A<float>' is deprecated}} + +template <typename T> struct B; +B<int> *p2; +template <typename T> struct [[deprecated]] B;//expected-note {{'B<int>' has been explicitly marked deprecated here}} expected-note {{'B<float>' has been explicitly marked deprecated here}} +B<int> *q2; // expected-warning {{'B<int>' is deprecated}} +B<float> *r2; // expected-warning {{'B<float>' is deprecated}} + +template <typename T> +T some_func(T t) { + struct [[deprecated]] FunS{}; // expected-note {{'FunS' has been explicitly marked deprecated here}} + FunS f;// expected-warning {{'FunS' is deprecated}} + +} + +template <typename T> +[[deprecated]]T some_func2(T t) { + struct FunS2{}; + FunS2 f;// No warning, entire function is deprecated, so usage here should be fine. + +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp index eb751517e2f2..e8f12156a424 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp @@ -3,15 +3,15 @@ // FIXME: This is in p11 (?) in C++1y. void f() { - decltype(auto) a = a; // expected-error{{variable 'a' declared with 'decltype(auto)' type cannot appear in its own initializer}} - if (decltype(auto) b = b) {} // expected-error {{variable 'b' declared with 'decltype(auto)' type cannot appear in its own initializer}} - decltype(auto) c = ({ decltype(auto) d = c; 0; }); // expected-error {{variable 'c' declared with 'decltype(auto)' type cannot appear in its own initializer}} + decltype(auto) a = a; // expected-error{{variable 'a' declared with deduced type 'decltype(auto)' cannot appear in its own initializer}} + if (decltype(auto) b = b) {} // expected-error {{variable 'b' declared with deduced type 'decltype(auto)' cannot appear in its own initializer}} + decltype(auto) c = ({ decltype(auto) d = c; 0; }); // expected-error {{variable 'c' declared with deduced type 'decltype(auto)' cannot appear in its own initializer}} } void g() { - decltype(auto) a; // expected-error{{declaration of variable 'a' with type 'decltype(auto)' requires an initializer}} + decltype(auto) a; // expected-error{{declaration of variable 'a' with deduced type 'decltype(auto)' requires an initializer}} - decltype(auto) *b; // expected-error{{cannot form pointer to 'decltype(auto)'}} expected-error{{declaration of variable 'b' with type 'decltype(auto) *' requires an initializer}} + decltype(auto) *b; // expected-error{{cannot form pointer to 'decltype(auto)'}} expected-error{{declaration of variable 'b' with deduced type 'decltype(auto) *' requires an initializer}} if (decltype(auto) b) {} // expected-error {{must have an initializer}} for (;decltype(auto) b;) {} // expected-error {{must have an initializer}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1z.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1z.cpp new file mode 100644 index 000000000000..73caa2de044e --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1z.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1z + +// FIXME: This is in p10 (?) in C++1z. +template<typename T> struct A { + A(T); +}; +template<typename T> A(T) -> A<T>; +A a = a; // expected-error{{variable 'a' declared with deduced type 'A' cannot appear in its own initializer}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp index e91cacf10466..440c78201293 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp @@ -1,17 +1,17 @@ // 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}} + auto a = a; // expected-error{{variable 'a' declared with deduced type 'auto' cannot appear in its own initializer}} + auto *b = b; // expected-error{{variable 'b' declared with deduced type 'auto *' cannot appear in its own initializer}} + const auto c = c; // expected-error{{variable 'c' declared with deduced type 'const auto' cannot appear in its own initializer}} + if (auto d = d) {} // expected-error {{variable 'd' declared with deduced type 'auto' cannot appear in its own initializer}} + auto e = ({ auto f = e; 0; }); // expected-error {{variable 'e' declared with deduced type 'auto' cannot appear in its own initializer}} } void g() { - auto a; // expected-error{{declaration of variable 'a' with type 'auto' requires an initializer}} + auto a; // expected-error{{declaration of variable 'a' with deduced type 'auto' requires an initializer}} - auto *b; // expected-error{{declaration of variable 'b' with type 'auto *' requires an initializer}} + auto *b; // expected-error{{declaration of variable 'b' with deduced type 'auto *' requires an initializer}} if (auto b) {} // expected-error {{must have an initializer}} for (;auto b;) {} // expected-error {{must have an initializer}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp index 46c874f605cb..bf1b3092e08e 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p4.cpp @@ -36,7 +36,7 @@ class X { }; struct S { - static const auto a; // expected-error {{declaration of variable 'a' with type 'const auto' requires an initializer}} + static const auto a; // expected-error {{declaration of variable 'a' with deduced type 'const auto' requires an initializer}} static const auto b = 0; static const int c; }; diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp index 0cdf3c6e053f..a260f99f5cf1 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp @@ -9,7 +9,7 @@ struct S { void f() throw (auto); // expected-error{{'auto' not allowed here}} - friend auto; // expected-error{{'auto' not allowed in non-static struct member}} + friend auto; // expected-error{{'auto' not allowed in friend declaration}} operator auto(); // expected-error{{'auto' not allowed in conversion function type}} }; diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-1y.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-1y.cpp index 06bd72e125d1..60ddabeb4a90 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-1y.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-1y.cpp @@ -51,7 +51,7 @@ decltype(auto) *f3(); // expected-error {{cannot form pointer to 'decltype(auto) const decltype(auto) f4(); // expected-error {{'decltype(auto)' cannot be combined with other type specifiers}} typedef decltype(auto) f5(); // expected-error {{'decltype(auto)' not allowed in typedef}} decltype(auto) ((((((f6))))())); // ok -decltype(auto) f7()(); // expected-error {{'decltype(auto)' can only be used as a return type in a function declaration}} expected-error {{function cannot return function type}} +decltype(auto) f7()(); // expected-error {{'decltype(auto)' can only be used as a return type in a function declaration}} decltype(auto) (S::*f8)(); // expected-error {{'decltype(auto)' can only be used as a return type in a function declaration}} expected-error {{requires an initializer}} decltype(auto) &f9(); // expected-error {{cannot form reference to 'decltype(auto)'}} decltype(auto) (&f10())[10]; // expected-error {{cannot form array of 'decltype(auto)'}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp index 8d789bdd5ad3..e9294d7f4362 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7.cpp @@ -1,3 +1,4 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++14 // 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() { @@ -19,22 +20,42 @@ void f() { } void g() { - auto a = 0, #if __has_feature(cxx_trailing_return) - (*b)() -> void, -#endif + auto a = 0, + (*b)() -> void, // expected-error {{declaration with trailing return type must be the only declaration in its group}} 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 + auto d = 0, + e() -> void, // expected-error {{declaration with trailing return type must be the only declaration in its group}} f = 0.0; + auto x() -> void, // expected-error {{declaration with trailing return type must be the only declaration in its group}} + y() -> void; +#endif #if __has_feature(cxx_decltype) auto g = 0ull, h = decltype(g)(0); #endif } +#if __has_feature(cxx_trailing_return) +int F(); +auto p = 0, (*q)() -> auto = F; // expected-error {{declaration with trailing return type must be the only declaration in its group}} + #if __cplusplus < 201402L + // expected-error@-2 {{'auto' not allowed in function return type}} + #endif +#endif + +#if __cplusplus >= 201402L +namespace DeducedReturnType { + auto a = 0, + b(), // expected-error {{function with deduced return type must be the only declaration in its group}} + c = 0.0; + auto d(), // expected-error {{function with deduced return type must be the only declaration in its group}} + e = 1; + auto f(), // expected-error {{function with deduced return type must be the only declaration in its group}} + g(); +} +#endif + template<typename T> void h() { auto a = T(), *b = &a; #if __has_feature(cxx_decltype) diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp new file mode 100644 index 000000000000..cfb9a61f1ac4 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +template<typename T> struct A { constexpr A(int = 0) {} }; +A() -> A<int>; +A(int) -> A<char>; + +static constexpr inline const volatile A a = {}; // ok, specifiers are permitted +// FIXME: There isn't really a good reason to reject this. +A b; // expected-error {{requires an initializer}} +A c [[]] {}; + +A d = {}, e = {}; +A f(0), g{}; // expected-error {{template arguments deduced as 'A<char>' in declaration of 'f' and deduced as 'A<int>' in declaration of 'g'}} + +struct B { + static A a; // expected-error {{requires an initializer}} +}; +extern A x; // expected-error {{requires an initializer}} diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3.cpp index f381ed708f70..ade327485773 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3.cpp @@ -150,35 +150,44 @@ namespace cxx1z_direct_enum_init { void f(T); f(T{0}); + + char c; + auto t3 = T{c}; } #if __cplusplus <= 201402L - // expected-error@-15 5{{cannot initialize}} - // expected-error@-15 5{{cannot initialize}} - // expected-error@-15 5{{cannot initialize}} + // expected-error@-18 5{{cannot initialize}} + // expected-error@-18 5{{cannot initialize}} + // expected-error@-18 5{{cannot initialize}} + // // + // expected-error@-18 5{{cannot initialize}} // - // expected-error@-15 5{{cannot initialize}} + // expected-error@-18 5{{cannot initialize}} // - // expected-error@-15 5{{cannot initialize}} + // expected-error@-18 5{{cannot initialize}} // - // expected-error@-15 5{{cannot initialize}} // + // expected-error@-18 5{{cannot initialize}} // - // expected-error@-15 5{{cannot initialize}} + // + // expected-error@-18 5{{cannot initialize}} #else - // expected-error@-29 {{cannot initialize}} - // expected-error@-29 {{cannot initialize}} - // expected-error@-29 {{cannot initialize}} + // expected-error@-35 {{cannot initialize}} + // expected-error@-35 {{cannot initialize}} + // expected-error@-35 {{cannot initialize}} + // // + // expected-error@-35 {{cannot initialize}} // - // expected-error@-29 {{cannot initialize}} + // expected-error@-35 {{cannot initialize}} // - // expected-error@-29 {{cannot initialize}} + // expected-error@-35 {{cannot initialize}} // - // expected-error@-29 {{cannot initialize}} // + // expected-error@-35 {{cannot initialize}} // - // expected-error@-29 {{cannot initialize}} + // + // expected-error@-35 {{cannot initialize}} #endif template<typename T> void bad() { @@ -252,4 +261,12 @@ namespace cxx1z_direct_enum_init { (void)B{0.0}; // expected-error {{type 'double' cannot be narrowed}} #endif } + +#if __cplusplus > 201402L + enum class F : unsigned {}; + F f1(unsigned x) { return F{x}; } + F f2(const unsigned x) { return F{x}; } + F f3(bool x) { return F{x}; } + F f4(const bool x) { return F{x}; } +#endif } diff --git a/test/CXX/drs/dr10xx.cpp b/test/CXX/drs/dr10xx.cpp index e11e796165e2..e1db9ef54adf 100644 --- a/test/CXX/drs/dr10xx.cpp +++ b/test/CXX/drs/dr10xx.cpp @@ -12,6 +12,30 @@ namespace std { }; } +namespace dr1004 { // dr1004: 5 + template<typename> struct A {}; + template<typename> struct B1 {}; + template<template<typename> class> struct B2 {}; + template<typename X> void f(); // expected-note {{[with X = dr1004::A<int>]}} + template<template<typename> class X> void f(); // expected-note {{[with X = A]}} + template<template<typename> class X> void g(); // expected-note {{[with X = A]}} + template<typename X> void g(); // expected-note {{[with X = dr1004::A<int>]}} + struct C : A<int> { + B1<A> b1a; + B2<A> b2a; + void h() { + f<A>(); // expected-error {{ambiguous}} + g<A>(); // expected-error {{ambiguous}} + } + }; + + // This example (from the standard) is actually ill-formed, because + // name lookup of "T::template A" names the constructor. + // FIXME: Only issue one diagnostic for this case. + template<class T, template<class> class U = T::template A> struct Third { }; // expected-error 2{{is a constructor name}} + Third<A<int> > t; // expected-note {{in instantiation of}} expected-note {{while substituting}} expected-note {{while checking}} +} + namespace dr1048 { // dr1048: 3.6 struct A {}; const A f(); diff --git a/test/CXX/drs/dr12xx.cpp b/test/CXX/drs/dr12xx.cpp index 45b33f9d7daf..24039a1cd240 100644 --- a/test/CXX/drs/dr12xx.cpp +++ b/test/CXX/drs/dr12xx.cpp @@ -14,7 +14,7 @@ namespace dr1213 { // dr1213: 4 #endif } -namespace dr1250 { // dr1250: 3.9 +namespace dr1250 { // dr1250: 3.9 struct Incomplete; struct Base { @@ -24,9 +24,23 @@ struct Base { struct Derived : Base { virtual Incomplete *meow(); }; -} // dr1250 +} + +namespace dr1265 { // dr1265: 5 +#if __cplusplus >= 201103L + auto a = 0, b() -> int; // expected-error {{declaration with trailing return type must be the only declaration in its group}} + auto b() -> int, d = 0; // expected-error {{declaration with trailing return type must be the only declaration in its group}} + auto e() -> int, f() -> int; // expected-error {{declaration with trailing return type must be the only declaration in its group}} +#endif + +#if __cplusplus >= 201402L + auto g(), h = 0; // expected-error {{function with deduced return type must be the only declaration in its group}} + auto i = 0, j(); // expected-error {{function with deduced return type must be the only declaration in its group}} + auto k(), l(); // expected-error {{function with deduced return type must be the only declaration in its group}} +#endif +} -namespace dr1295 { // dr1295: 4 +namespace dr1295 { // dr1295: 4 struct X { unsigned bitfield : 4; }; diff --git a/test/CXX/drs/dr13xx.cpp b/test/CXX/drs/dr13xx.cpp index f35ead7b5e94..56ff1237480f 100644 --- a/test/CXX/drs/dr13xx.cpp +++ b/test/CXX/drs/dr13xx.cpp @@ -3,6 +3,96 @@ // RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++1z %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +__extension__ typedef __SIZE_TYPE__ size_t; + +namespace std { + template<typename T> struct initializer_list { + const T *ptr; + size_t n; + initializer_list(const T*, size_t); + }; +} + +namespace dr1310 { // dr1310: 5 + struct S {} * sp = new S::S; // expected-error {{qualified reference to 'S' is a constructor name}} + void f() { + S::S(a); // expected-error {{qualified reference to 'S' is a constructor name}} + } + struct T { int n; typedef int U; typedef T V; }; + int k = T().T::T::n; + T::V v; + + struct U { int U; }; + int u = U().U::U; + struct U::U w; + + struct V : T::T { + // FIXME: This is technically ill-formed, but we consider that to be a defect. + V() : T::T() {} + }; + template<typename T> struct VT : T::T { + VT() : T::T() {} + }; + template struct VT<T>; + + template<template<typename> class> class TT {}; + template<typename> class TTy {}; + + template<typename T> struct WBase {}; + template<typename T> struct W : WBase<T> { typedef int X; int n; }; + + void w_test() { + W<int>::W w1a; // expected-error {{qualified reference to 'W' is a constructor name}} + W<int>::W::X w1ax; + W<int>::W<int> w1b; // expected-error {{qualified reference to 'W' is a constructor name}} + W<int>::W<int>::X w1bx; + typename W<int>::W w2a; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{outside of a template}} + typename W<int>::W::X w2ax; // expected-error 0-1{{outside of a template}} + typename W<int>::W<int> w2b; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{outside of a template}} + typename W<int>::W<int>::X w2bx; // expected-error 0-1{{outside of a template}} + W<int>::template W<int> w3; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{outside of a template}} + W<int>::template W<int>::X w3x; // expected-error 0-1{{outside of a template}} + typename W<int>::template W<int> w4; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-2{{outside of a template}} + typename W<int>::template W<int>::X w4x; // expected-error 0-2{{outside of a template}} + + TT<W<int>::W> tt1; // expected-error {{qualified reference to 'W' is a constructor name}} + TTy<W<int>::W> tt1a; // expected-error {{qualified reference to 'W' is a constructor name}} + TT<W<int>::template W> tt2; // expected-error {{qualified reference to 'W' is a constructor name}} expected-error 0-1{{outside of a template}} + TT<W<int>::WBase> tt3; + TTy<W<int>::WBase> tt3a; + TT<W<int>::template WBase> tt4; // expected-error 0-1{{outside of a template}} + + W<int> w; + (void)w.W::W::n; + (void)w.W<int>::W::n; + (void)w.W<int>::W<int>::n; + (void)w.W<int>::template W<int>::n; // expected-error 0-1{{outside of a template}} + } + + template<typename W> + void wt_test() { + typename W::W w2a; // expected-error {{qualified reference to 'W' is a constructor name}} + typename W::template W<int> w4; // expected-error {{qualified reference to 'W' is a constructor name}} + TTy<typename W::W> tt2; // expected-error {{qualified reference to 'W' is a constructor name}} + TT<W::template W> tt3; // expected-error {{qualified reference to 'W' is a constructor name}} + } + template<typename W> + void wt_test_good() { + typename W::W::X w2ax; + typename W::template W<int>::X w4x; + TTy<typename W::WBase> tt4; + TT<W::template WBase> tt5; + + W w; + (void)w.W::W::n; + (void)w.W::template W<int>::n; + (void)w.template W<int>::W::n; + (void)w.template W<int>::template W<int>::n; + } + template void wt_test<W<int> >(); // expected-note {{instantiation of}} + template void wt_test_good<W<int> >(); +} + namespace dr1315 { // dr1315: partial template <int I, int J> struct A {}; template <int I> // expected-note {{non-deducible template parameter 'I'}} @@ -159,6 +249,15 @@ namespace dr1346 { // dr1346: 3.5 #endif } +namespace dr1347 { // dr1347: yes + auto x = 5, *y = &x; // expected-error 0-1{{extension}} + auto z = y, *q = y; // expected-error {{'auto' deduced as 'int *' in declaration of 'z' and deduced as 'int' in declaration of 'q'}} expected-error 0-1{{extension}} +#if __cplusplus >= 201103L + auto a = 5, b = {1, 2}; // expected-error {{'auto' deduced as 'int' in declaration of 'a' and deduced as 'std::initializer_list<int>' in declaration of 'b'}} + auto (*fp)(int) -> int, i = 0; // expected-error {{declaration with trailing return type must be the only declaration in its group}} +#endif +} + namespace dr1359 { // dr1359: 3.5 #if __cplusplus >= 201103L union A { constexpr A() = default; }; diff --git a/test/CXX/drs/dr16xx.cpp b/test/CXX/drs/dr16xx.cpp index c9f084db73a1..08ae92570cec 100644 --- a/test/CXX/drs/dr16xx.cpp +++ b/test/CXX/drs/dr16xx.cpp @@ -3,6 +3,13 @@ // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +namespace dr1611 { // dr1611: dup 1658 + struct A { A(int); }; + struct B : virtual A { virtual void f() = 0; }; + struct C : B { C() : A(0) {} void f(); }; + C c; +} + namespace dr1684 { // dr1684: 3.6 #if __cplusplus >= 201103L struct NonLiteral { // expected-note {{because}} @@ -101,3 +108,114 @@ namespace dr1653 { // dr1653: 4 c++17 b -= 1; // ok } } + +namespace dr1658 { // dr1658: 5 + namespace DefCtor { + class A { A(); }; // expected-note 0-2{{here}} + class B { ~B(); }; // expected-note 0-2{{here}} + + // The stars align! An abstract class does not construct its virtual bases. + struct C : virtual A { C(); virtual void foo() = 0; }; + C::C() = default; // ok, not deleted, expected-error 0-1{{extension}} + struct D : virtual B { D(); virtual void foo() = 0; }; + D::D() = default; // ok, not deleted, expected-error 0-1{{extension}} + + // In all other cases, we are not so lucky. + struct E : A { E(); virtual void foo() = 0; }; +#if __cplusplus < 201103L + E::E() = default; // expected-error {{private default constructor}} expected-error {{extension}} expected-note {{here}} +#else + E::E() = default; // expected-error {{would delete}} expected-note@-4{{inaccessible default constructor}} +#endif + struct F : virtual A { F(); }; +#if __cplusplus < 201103L + F::F() = default; // expected-error {{private default constructor}} expected-error {{extension}} expected-note {{here}} +#else + F::F() = default; // expected-error {{would delete}} expected-note@-4{{inaccessible default constructor}} +#endif + + struct G : B { G(); virtual void foo() = 0; }; +#if __cplusplus < 201103L + G::G() = default; // expected-error@-2 {{private destructor}} expected-error {{extension}} expected-note {{here}} +#else + G::G() = default; // expected-error {{would delete}} expected-note@-4{{inaccessible destructor}} +#endif + struct H : virtual B { H(); }; +#if __cplusplus < 201103L + H::H() = default; // expected-error@-2 {{private destructor}} expected-error {{extension}} expected-note {{here}} +#else + H::H() = default; // expected-error {{would delete}} expected-note@-4{{inaccessible destructor}} +#endif + } + + namespace Dtor { + class B { ~B(); }; // expected-note 0-2{{here}} + + struct D : virtual B { ~D(); virtual void foo() = 0; }; + D::~D() = default; // ok, not deleted, expected-error 0-1{{extension}} + + struct G : B { ~G(); virtual void foo() = 0; }; +#if __cplusplus < 201103L + G::~G() = default; // expected-error@-2 {{private destructor}} expected-error {{extension}} expected-note {{here}} +#else + G::~G() = default; // expected-error {{would delete}} expected-note@-4{{inaccessible destructor}} +#endif + struct H : virtual B { ~H(); }; +#if __cplusplus < 201103L + H::~H() = default; // expected-error@-2 {{private destructor}} expected-error {{extension}} expected-note {{here}} +#else + H::~H() = default; // expected-error {{would delete}} expected-note@-4{{inaccessible destructor}} +#endif + } + + namespace MemInit { + struct A { A(int); }; // expected-note {{here}} + struct B : virtual A { + B() {} + virtual void f() = 0; + }; + struct C : virtual A { + C() {} // expected-error {{must explicitly initialize}} + }; + } + + namespace CopyCtorParamType { + struct A { A(A&); }; + struct B : virtual A { virtual void f() = 0; }; + struct C : virtual A { virtual void f(); }; + struct D : A { virtual void f() = 0; }; + + struct X { + friend B::B(const B&) throw(); + friend C::C(C&); + friend D::D(D&); + }; + } + + namespace CopyCtor { + class A { A(const A&); A(A&&); }; // expected-note 0-4{{here}} expected-error 0-1{{extension}} + + struct C : virtual A { C(const C&); C(C&&); virtual void foo() = 0; }; // expected-error 0-1{{extension}} + C::C(const C&) = default; // expected-error 0-1{{extension}} + C::C(C&&) = default; // expected-error 0-2{{extension}} + + struct E : A { E(const E&); E(E&&); virtual void foo() = 0; }; // expected-error 0-1{{extension}} +#if __cplusplus < 201103L + E::E(const E&) = default; // expected-error {{private copy constructor}} expected-error {{extension}} expected-note {{here}} + E::E(E&&) = default; // expected-error {{private move constructor}} expected-error 2{{extension}} expected-note {{here}} +#else + E::E(const E&) = default; // expected-error {{would delete}} expected-note@-5{{inaccessible copy constructor}} + E::E(E&&) = default; // expected-error {{would delete}} expected-note@-6{{inaccessible move constructor}} +#endif + struct F : virtual A { F(const F&); F(F&&); }; // expected-error 0-1{{extension}} +#if __cplusplus < 201103L + F::F(const F&) = default; // expected-error {{private copy constructor}} expected-error {{extension}} expected-note {{here}} + F::F(F&&) = default; // expected-error {{private move constructor}} expected-error 2{{extension}} expected-note {{here}} +#else + F::F(const F&) = default; // expected-error {{would delete}} expected-note@-5{{inaccessible copy constructor}} + F::F(F&&) = default; // expected-error {{would delete}} expected-note@-6{{inaccessible move constructor}} +#endif + } + + // assignment case is superseded by dr2180 +} diff --git a/test/CXX/drs/dr1xx.cpp b/test/CXX/drs/dr1xx.cpp index 9521f0a8b784..f5395cfe183d 100644 --- a/test/CXX/drs/dr1xx.cpp +++ b/test/CXX/drs/dr1xx.cpp @@ -535,13 +535,15 @@ namespace dr145 { // dr145: yes } } -namespace dr147 { // dr147: no +namespace dr147 { // dr147: yes namespace example1 { template<typename> struct A { template<typename T> A(T); }; - // FIXME: This appears to be valid, and EDG and G++ accept. + // Per core issue 1435, this is ill-formed because A<int>::A<int> does not + // name the injected-class-name. (A<int>::A does, though.) template<> template<> A<int>::A<int>(int) {} // expected-error {{out-of-line constructor for 'A' cannot have template arguments}} + template<> template<> A<float>::A(float) {} } namespace example2 { struct A { A(); }; diff --git a/test/CXX/drs/dr21xx.cpp b/test/CXX/drs/dr21xx.cpp new file mode 100644 index 000000000000..78fc0bec40bf --- /dev/null +++ b/test/CXX/drs/dr21xx.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors + +namespace dr2180 { // dr2180: yes + class A { + A &operator=(const A &); // expected-note 0-2{{here}} + A &operator=(A &&); // expected-note 0-2{{here}} expected-error 0-1{{extension}} + }; + + struct B : virtual A { + B &operator=(const B &); + B &operator=(B &&); // expected-error 0-1{{extension}} + virtual void foo() = 0; + }; +#if __cplusplus < 201103L + B &B::operator=(const B&) = default; // expected-error {{private member}} expected-error {{extension}} expected-note {{here}} + B &B::operator=(B&&) = default; // expected-error {{private member}} expected-error 2{{extension}} expected-note {{here}} +#else + B &B::operator=(const B&) = default; // expected-error {{would delete}} expected-note@-9{{inaccessible copy assignment}} + B &B::operator=(B&&) = default; // expected-error {{would delete}} expected-note@-10{{inaccessible move assignment}} +#endif +} diff --git a/test/CXX/drs/dr2xx.cpp b/test/CXX/drs/dr2xx.cpp index 68261f6c00f1..a5677a125a00 100644 --- a/test/CXX/drs/dr2xx.cpp +++ b/test/CXX/drs/dr2xx.cpp @@ -1014,7 +1014,7 @@ namespace dr294 { // dr294: no namespace dr295 { // dr295: 3.7 typedef int f(); - const f g; // expected-warning {{'const' qualifier on function type 'f' (aka 'int ()') has no effect}} + const f g; // expected-warning {{'const' qualifier on function type 'dr295::f' (aka 'int ()') has no effect}} f &r = g; template<typename T> struct X { const T &f; @@ -1022,10 +1022,10 @@ namespace dr295 { // dr295: 3.7 X<f> x = {g}; typedef int U(); - typedef const U U; // expected-warning {{'const' qualifier on function type 'U' (aka 'int ()') has no effect}} + typedef const U U; // expected-warning {{'const' qualifier on function type 'dr295::U' (aka 'int ()') has no effect}} typedef int (*V)(); - typedef volatile U *V; // expected-warning {{'volatile' qualifier on function type 'U' (aka 'int ()') has no effect}} + typedef volatile U *V; // expected-warning {{'volatile' qualifier on function type 'dr295::U' (aka 'int ()') has no effect}} } namespace dr296 { // dr296: yes @@ -1053,7 +1053,7 @@ namespace dr298 { // dr298: yes B::B() {} // expected-error {{requires a type specifier}} B::A() {} // ok - C::~C() {} // expected-error {{destructor cannot be declared using a typedef 'C' (aka 'const dr298::A') of the class name}} + C::~C() {} // expected-error {{destructor cannot be declared using a typedef 'dr298::C' (aka 'const dr298::A') of the class name}} typedef struct D E; // expected-note {{here}} struct E {}; // expected-error {{conflicts with typedef}} diff --git a/test/CXX/drs/dr3xx.cpp b/test/CXX/drs/dr3xx.cpp index a1c1c4ce6132..3342148461ad 100644 --- a/test/CXX/drs/dr3xx.cpp +++ b/test/CXX/drs/dr3xx.cpp @@ -908,18 +908,21 @@ namespace dr372 { // dr372: no } } -namespace dr373 { // dr373: no - // FIXME: This is valid. - namespace X { int dr373; } // expected-note 2{{here}} +namespace dr373 { // dr373: 5 + namespace X { int dr373; } struct dr373 { // expected-note {{here}} void f() { - using namespace dr373::X; // expected-error {{no namespace named 'X' in 'dr373::dr373'}} + using namespace dr373::X; int k = dr373; // expected-error {{does not refer to a value}} - namespace Y = dr373::X; // expected-error {{no namespace named 'X' in 'dr373::dr373'}} + namespace Y = dr373::X; k = Y::dr373; } }; + + struct A { struct B {}; }; // expected-note 2{{here}} + namespace X = A::B; // expected-error {{expected namespace name}} + using namespace A::B; // expected-error {{expected namespace name}} } namespace dr374 { // dr374: yes c++11 diff --git a/test/CXX/drs/dr4xx.cpp b/test/CXX/drs/dr4xx.cpp index 6046c4afefd5..3ea226a745f6 100644 --- a/test/CXX/drs/dr4xx.cpp +++ b/test/CXX/drs/dr4xx.cpp @@ -35,9 +35,7 @@ namespace dr401 { // dr401: yes }; A<B> *b; // expected-note {{default argument}} - // FIXME: We're missing the "in instantiation of" note for the default - // argument here. - A<D> *d; + A<D> *d; // expected-note {{in instantiation of default argument}} struct E { template<class T, class U = typename T::type> class A : public T {}; diff --git a/test/CXX/drs/dr5xx.cpp b/test/CXX/drs/dr5xx.cpp index 89e404f5fd6d..97b40b8b7c26 100644 --- a/test/CXX/drs/dr5xx.cpp +++ b/test/CXX/drs/dr5xx.cpp @@ -877,13 +877,25 @@ namespace dr583 { // dr583: 4 namespace dr585 { // dr585: yes template<typename> struct T; struct A { - friend T; // expected-error {{requires a type specifier}} expected-error {{can only be classes or functions}} + friend T; +#if __cplusplus <= 201402L + // expected-error@-2 {{requires a type specifier}} expected-error@-2 {{can only be classes or functions}} +#else + // expected-error@-4 {{use of class template 'T' requires template arguments; argument deduction not allowed in friend declaration}} + // expected-note@-7 {{here}} +#endif // FIXME: It's not clear whether the standard allows this or what it means, // but the DR585 writeup suggests it as an alternative. template<typename U> friend T<U>; // expected-error {{must use an elaborated type}} }; template<template<typename> class T> struct B { - friend T; // expected-error {{requires a type specifier}} expected-error {{can only be classes or functions}} + friend T; +#if __cplusplus <= 201402L + // expected-error@-2 {{requires a type specifier}} expected-error@-2 {{can only be classes or functions}} +#else + // expected-error@-4 {{use of template template parameter 'T' requires template arguments; argument deduction not allowed in friend declaration}} + // expected-note@-6 {{here}} +#endif template<typename U> friend T<U>; // expected-error {{must use an elaborated type}} }; } @@ -942,7 +954,7 @@ namespace dr591 { // dr591: no template<typename T> struct A<T>::B::C : A<T> { // FIXME: Should find member of non-dependent base class A<T>. - M m; // expected-error {{incomplete type 'M' (aka 'void'}} + M m; // expected-error {{incomplete type 'dr591::A::B::M' (aka 'void'}} }; } diff --git a/test/CXX/expr/expr.post/expr.type.conv/p1.cpp b/test/CXX/expr/expr.post/expr.type.conv/p1.cpp new file mode 100644 index 000000000000..f3608bc378bc --- /dev/null +++ b/test/CXX/expr/expr.post/expr.type.conv/p1.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +template<typename T> struct A { // expected-note 2{{candidate}} + T t, u; +}; +template<typename T> A(T, T) -> A<T>; // expected-note {{deduced conflicting types for parameter 'T'}} +template<typename T> A(A<T>) -> A<T>; // expected-note {{requires 1 argument, but 2 were provided}} + +A a = A{1, 2}; +A b = A{3, 4.0}; // expected-error {{no viable constructor or deduction guide}} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp index 4a2a4f3d7353..e7fce11abc5e 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify +// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture -verify void odr_used() { int i = 17; diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp index 8bb707e0dbc7..b55beb7d4ed7 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify +// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture -verify void f2() { int i = 1; diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp index 94f8111015aa..905192ff830b 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify +// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture -verify struct X { diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp index 93c2805497f3..72cf93be5190 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify +// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture -verify // expected-no-diagnostics template<typename T, typename U> diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp index 1dbcbf498031..a8b40249f0f0 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify +// RUN: %clang_cc1 -std=c++11 %s -Wunused -Wno-unused-lambda-capture -verify struct MoveOnly { MoveOnly(MoveOnly&&); diff --git a/test/CXX/over/over.match/over.match.best/p1.cpp b/test/CXX/over/over.match/over.match.best/p1.cpp index 59e3dac74283..fad5bf9a72ee 100644 --- a/test/CXX/over/over.match/over.match.best/p1.cpp +++ b/test/CXX/over/over.match/over.match.best/p1.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s // expected-no-diagnostics template<typename T> int &f0(T*, int); @@ -12,6 +12,28 @@ void test_f0(int* ip, void *vp) { float &fr = f0(vp, 0); } +namespace deduction_guide_example { + template<typename T> struct A { + A(T, int*); + A(A<T>&, int*); + enum { value }; + }; + + template<typename T> struct remove_ref_impl; + template<typename T> struct remove_ref_impl<T&> { using type = T; }; + template<typename T> using remove_ref = typename remove_ref_impl<T>::type; + + // FIXME: The standard's example is wrong; we add a remove_ref<...> here to + // fix it. + template<typename T, int N = remove_ref<T>::value> A(T&&, int*) -> A<T>; + A a{1, 0}; + extern A<int> a; + A b{a, 0}; + + A<int> *pa = &a; + A<A<int>&> *pb = &b; +} + // Partial ordering of function template specializations will be tested // elsewhere // FIXME: Initialization by user-defined conversion is tested elsewhere diff --git a/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp b/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp new file mode 100644 index 000000000000..fe1b6a63d75b --- /dev/null +++ b/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -verify -std=c++1z %s + +namespace Explicit { + // Each notional constructor is explicit if the function or function template + // was generated from a constructor or deduction-guide that was declared explicit. + template<typename T> struct A { + A(T); + A(T*); + }; + template<typename T> A(T) -> A<T>; + template<typename T> explicit A(T*) -> A<T>; // expected-note {{explicit}} + + int *p; + A a(p); + A b = p; + A c{p}; + A d = {p}; // expected-error {{selected an explicit deduction guide}} + + using X = A<int>; + using Y = A<int*>; + + using X = decltype(a); + using Y = decltype(b); + using X = decltype(c); +} diff --git a/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p3.cpp b/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p3.cpp new file mode 100644 index 000000000000..4ed1d30b83d5 --- /dev/null +++ b/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p3.cpp @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +namespace std_example { + template <class T> struct A { + explicit A(const T &, ...) noexcept; // expected-note {{explicit}} expected-note 2{{candidate}} + A(T &&, ...); // expected-note 2{{candidate}} + }; + + int i; + A a1 = {i, i}; // expected-error {{class template argument deduction for 'A' selected an explicit constructor for copy-list-initialization}} + A a2{i, i}; + A a3{0, i}; + A a4 = {0, i}; + + template <class T> A(const T &, const T &) -> A<T &>; // expected-note 2{{candidate}} + template <class T> explicit A(T &&, T &&) -> A<T>; // expected-note {{explicit deduction guide declared here}} + + // FIXME: The standard gives an incorrect explanation for why a5, a7, and a8 are ill-formed. + A a5 = {0, 1}; // expected-error {{class template argument deduction for 'A' selected an explicit deduction guide}} + A a6{0, 1}; + A a7 = {0, i}; // expected-error {{ambiguous deduction}} + A a8{0, i}; // expected-error {{ambiguous deduction}} + + template <class T> struct B { + template <class U> using TA = T; + template <class U> B(U, TA<U>); + }; + B b{(int *)0, (char *)0}; +} + +namespace check { + using namespace std_example; + template<typename T, typename U> constexpr bool same = false; + template<typename T> constexpr bool same<T, T> = true; + + static_assert(same<decltype(a2), A<int>>); + static_assert(same<decltype(a3), A<int>>); + static_assert(same<decltype(a4), A<int>>); + static_assert(same<decltype(a6), A<int>>); + static_assert(same<decltype(b), B<char*>>); +} diff --git a/test/CXX/special/class.dtor/p10-0x.cpp b/test/CXX/special/class.dtor/p10-0x.cpp index 3b8a0ad4d6a7..3be0a98d47d7 100644 --- a/test/CXX/special/class.dtor/p10-0x.cpp +++ b/test/CXX/special/class.dtor/p10-0x.cpp @@ -33,7 +33,7 @@ void a(const A *x, int i, int *pi) { 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(int())(); // expected-error{{member reference type 'int *' is a pointer; did you mean to use '->'?}} 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/test/CXX/temp/temp.decls/temp.variadic/sizeofpack.cpp b/test/CXX/temp/temp.decls/temp.variadic/sizeofpack.cpp index 4960a2bac20a..87c22a0d7e94 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/sizeofpack.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/sizeofpack.cpp @@ -61,7 +61,7 @@ struct X { template<class... Members> template<int i> -X<Members...>::get_t<i> X<Members...>::get() +typename X<Members...>::template get_t<i> X<Members...>::get() { return 0; } diff --git a/test/CXX/temp/temp.deduct.guide/p1.cpp b/test/CXX/temp/temp.deduct.guide/p1.cpp new file mode 100644 index 000000000000..c0a2ba1129e2 --- /dev/null +++ b/test/CXX/temp/temp.deduct.guide/p1.cpp @@ -0,0 +1,108 @@ +// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -verify %s +// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -verify %s -DCLASS + +#ifdef CLASS +struct Outer { +#endif + +template<typename> struct A {}; + +// Valid forms. +A(int(&)[1]) -> A<int>; +explicit A(int(&)[2]) -> A<int>; + +// Declarator pieces are not OK. +*A(int(&)[3]) -> A<int>; // expected-error {{cannot specify any part of a return type in the declaration of a deduction guide}} +&A(int(&)[4]) -> A<int>; // expected-error {{cannot specify any part of a return type in the declaration of a deduction guide}} +A(int(&)[5])[3] -> A<int>; +#ifdef CLASS // FIXME: These diagnostics are both pretty bad. +// expected-error@-2 {{function cannot return array type}} expected-error@-2 {{';'}} +#else +// expected-error@-4 {{expected function body after function declarator}} +#endif + +(A[3])(int(&)[5][1]) -> A<int>; // expected-error {{'<deduction guide for A>' cannot be the name of a variable}} +#ifndef CLASS +// expected-error@-2 {{declared as array of functions}} +#endif +(*A)(int(&)[5][2]) -> A<int>; // expected-error {{'<deduction guide for A>' cannot be the name of a variable}} +(&A)(int(&)[5][3]) -> A<int>; // expected-error {{'<deduction guide for A>' cannot be the name of a variable}} +(*A(int))(int(&)[5][4]) -> A<int>; // expected-error {{cannot specify any part of a return type in the declaration of a deduction guide}} + +// (Pending DR) attributes and parens around the declarator-id are OK. +[[deprecated]] A(int(&)[6]) [[]] -> A<int> [[]]; +A [[]] (int(&)[7]) -> A<int>; +(A)(int(&)[8]) -> A<int>; + +// ... but the trailing-return-type is part of the function-declarator as normal +(A(int(&)[9])) -> A<int>; +#ifdef CLASS // FIXME: These diagnostics are both pretty bad. +// expected-error@-2 {{deduction guide declaration without trailing return type}} expected-error@-2 {{';'}} +#else +// expected-error@-4 {{expected function body after function declarator}} +#endif +(A(int(&)[10]) -> A<int>); // expected-error {{trailing return type may not be nested within parentheses}} + +// A trailing-return-type is mandatory. +A(int(&)[11]); // expected-error {{deduction guide declaration without trailing return type}} + +// No type specifier is permitted; we don't even parse such cases as a deduction-guide. +int A(int) -> A<int>; // expected-error {{function with trailing return type must specify return type 'auto', not 'int'}} +template<typename T> struct B {}; // expected-note {{here}} +auto B(int) -> B<int>; // expected-error {{redefinition of 'B' as different kind of symbol}} + +// No storage class specifier, function specifier, ... +friend A(int(&)[20]) -> A<int>; +#ifdef CLASS +// expected-error@-2 {{cannot declare a deduction guide as a friend}} +#else +// expected-error@-4 {{'friend' used outside of class}} +#endif +typedef A(int(&)[21]) -> A<int>; // expected-error {{deduction guide cannot be declared 'typedef'}} +constexpr A(int(&)[22]) -> A<int>; // expected-error {{deduction guide cannot be declared 'constexpr'}} +inline A(int(&)[23]) -> A<int>; // expected-error {{deduction guide cannot be declared 'inline'}} +static A(int(&)[24]) -> A<int>; // expected-error {{deduction guide cannot be declared 'static'}} +thread_local A(int(&)[25]) -> A<int>; // expected-error {{'thread_local' is only allowed on variable declarations}} +extern A(int(&)[26]) -> A<int>; +#ifdef CLASS +// expected-error@-2 {{storage class specified for a member}} +#else +// expected-error@-4 {{deduction guide cannot be declared 'extern'}} +#endif +mutable A(int(&)[27]) -> A<int>; // expected-error-re {{{{'mutable' cannot be applied to|illegal storage class on}} function}} +virtual A(int(&)[28]) -> A<int>; // expected-error {{'virtual' can only appear on non-static member functions}} +const A(int(&)[28]) -> A<int>; // expected-error {{deduction guide cannot be declared 'const'}} + +const volatile static constexpr inline A(int(&)[29]) -> A<int>; // expected-error {{deduction guide cannot be declared 'static inline constexpr const volatile'}} + +A(int(&)[30]) const -> A<int>; // expected-error {{deduction guide cannot have 'const' qualifier}} + +// No definition is allowed. +A(int(&)[40]) -> A<int> {} // expected-error {{deduction guide cannot have a function definition}} +A(int(&)[41]) -> A<int> = default; // expected-error {{deduction guide cannot have a function definition}} expected-error {{only special member functions may be defaulted}} +A(int(&)[42]) -> A<int> = delete; // expected-error {{deduction guide cannot have a function definition}} +A(int(&)[43]) -> A<int> try {} catch (...) {} // expected-error {{deduction guide cannot have a function definition}} + +#ifdef CLASS +}; +#endif + +namespace ExplicitInst { + // Explicit instantiation / specialization is not permitted. + template<typename T> struct B {}; + template<typename T> B(T) -> B<T>; + template<> B(int) -> B<int>; // expected-error {{deduction guide cannot be explicitly specialized}} + extern template B(float) -> B<float>; // expected-error {{deduction guide cannot be explicitly instantiated}} + template B(char) -> B<char>; // expected-error {{deduction guide cannot be explicitly instantiated}} + + // An attempt at partial specialization doesn't even parse as a deduction-guide. + template<typename T> B<T*>(T*) -> B<T*>; // expected-error 1+{{}} expected-note 0+{{}} + + struct X { + template<typename T> struct C {}; + template<typename T> C(T) -> C<T>; + template<> C(int) -> C<int>; // expected-error {{explicit specialization of '<deduction guide for C>' in class scope}} + extern template C(float) -> C<float>; // expected-error {{expected member name or ';'}} + template C(char) -> C<char>; // expected-error {{expected '<' after 'template'}} + }; +} diff --git a/test/CXX/temp/temp.deduct.guide/p2.cpp b/test/CXX/temp/temp.deduct.guide/p2.cpp new file mode 100644 index 000000000000..3549755ff0f2 --- /dev/null +++ b/test/CXX/temp/temp.deduct.guide/p2.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s +// expected-no-diagnostics + +namespace std_example { + template<typename T, typename U = int> struct S { + T data; + }; + template<typename U> S(U) -> S<typename U::type>; + + struct A { + using type = short; + operator type(); + }; + S x{A()}; +} diff --git a/test/CXX/temp/temp.deduct.guide/p3.cpp b/test/CXX/temp/temp.deduct.guide/p3.cpp new file mode 100644 index 000000000000..e12f7b6ef255 --- /dev/null +++ b/test/CXX/temp/temp.deduct.guide/p3.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -std=c++1z %s -verify + +// The same restrictions apply to the parameter-declaration-clause of a +// deduction guide as in a function declaration. +template<typename T> struct A {}; +A(void) -> A<int>; // ok +A(void, int) -> A<int>; // expected-error {{'void' must be the first and only parameter if specified}} + +// We interpret this as also extending to the validity of redeclarations. It's +// a bit of a stretch (OK, a lot of a stretch) but it gives desirable answers. +A() -> A<int>; // ok, redeclaration + +A() -> A<int>; // expected-note {{previous}} +A() -> A<float>; // FIXME: "functions" is a poor term. expected-error {{functions that differ only in their return type cannot be overloaded}} + +template<typename T> A(T) -> A<typename T::foo>; +template<typename T> A(T) -> A<typename T::bar>; // ok, can overload on return type (SFINAE applies) + +A(long) -> A<int>; +template<typename T = int> A(long) -> A<char>; // ok, non-template beats template as usual + +// (Pending DR) The template-name shall name a class template. +template<typename T> using B = A<T>; // expected-note {{template}} +B() -> B<int>; // expected-error {{cannot specify deduction guide for alias template 'B'}} +// FIXME: expected-error@-1 {{declarator requires an identifier}} +template<typename T> int C; +C() -> int; // expected-error {{requires a type specifier}} +template<typename T> void D(); +D() -> int; // expected-error {{requires a type specifier}} +template<template<typename> typename TT> struct E { // expected-note 2{{template}} + // FIXME: Should only diagnose this once! + TT(int) -> TT<int>; // expected-error 2{{cannot specify deduction guide for template template parameter 'TT'}} expected-error {{requires an identifier}} +}; + +A(int) -> int; // expected-error {{deduced type 'int' of deduction guide is not a specialization of template 'A'}} +template<typename T> A(T) -> B<T>; // expected-error {{deduced type 'B<T>' (aka 'A<type-parameter-0-0>') of deduction guide is not written as a specialization of template 'A'}} +template<typename T> A(T*) -> const A<T>; // expected-error {{deduced type 'const A<T>' of deduction guide is not a specialization of template 'A'}} + +// A deduction-guide shall be declared in the same scope as the corresponding +// class template. +namespace WrongScope { + namespace { + template<typename T> struct AnonNS1 {}; // expected-note {{here}} + AnonNS1(float) -> AnonNS1<float>; // ok + } + AnonNS1(int) -> AnonNS1<int>; // expected-error {{deduction guide must be declared in the same scope as template 'WrongScope::}} + template<typename T> struct AnonNS2 {}; // expected-note {{here}} + namespace { + AnonNS1(char) -> AnonNS1<char>; // ok + AnonNS2(int) -> AnonNS2<int>; // expected-error {{deduction guide must be declared in the same scope as template 'WrongScope::AnonNS2'}} + } + namespace N { + template<typename T> struct NamedNS1 {}; // expected-note {{here}} + template<typename T> struct NamedNS2 {}; // expected-note {{here}} + } + using N::NamedNS1; + NamedNS1(int) -> NamedNS1<int>; // expected-error {{deduction guide must be declared in the same scope as template}} + using namespace N; + NamedNS2(int) -> NamedNS2<int>; // expected-error {{deduction guide must be declared in the same scope as template}} + struct ClassMemberA { + template<typename T> struct X {}; // expected-note {{here}} + }; + struct ClassMemberB : ClassMemberA { + X(int) -> X<int>; // expected-error {{deduction guide must be declared in the same scope as template 'WrongScope::ClassMemberA::X'}} + }; + template<typename T> struct Local {}; + void f() { + Local(int) -> Local<int>; // expected-error 2{{expected}} expected-note {{to match}} + using WrongScope::Local; + Local(int) -> Local<int>; // expected-error 2{{expected}} expected-note {{to match}} + } +} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp index e470dd016644..ebff0a1df4e7 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp @@ -1,9 +1,39 @@ // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++1z -fsyntax-only -verify %s +// A forwarding reference is an rvalue reference to a cv-unqualified template +// parameter that does not represent a template parameter of a class template. +#if __cplusplus > 201402L +namespace ClassTemplateParamNotForwardingRef { + // This is not a forwarding reference. + template<typename T> struct A { // expected-note {{candidate}} + A(T&&); // expected-note {{no known conversion from 'int' to 'int &&'}} + }; + int n; + A a = n; // expected-error {{no viable constructor or deduction guide}} -// 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. + A b = 0; + A<int> *pb = &b; + + // This is a forwarding reference. + template<typename T> A(T&&) -> A<T>; + A c = n; + A<int&> *pc = &c; + + A d = 0; + A<int> *pd = &d; + + template<typename T = void> struct B { + // This is a forwarding reference. + template<typename U> B(U &&); + }; + B e = n; + B<void> *pe = &e; +} +#endif + +// If P is a forwarding reference 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&&); @@ -43,4 +73,21 @@ namespace std_example { int n1 = f(i); int n2 = f(0); int n3 = g(i); // expected-error{{no matching function for call to 'g'}} + +#if __cplusplus > 201402L + template<class T> struct A { // expected-note {{candidate}} + template<class U> + A(T &&, U &&, int *); // expected-note {{[with T = int, U = int] not viable: no known conversion from 'int' to 'int &&'}} + A(T &&, int *); // expected-note {{requires 2}} + }; + template<class T> A(T &&, int *) -> A<T>; // expected-note {{requires 2}} + + int *ip; + A a{i, 0, ip}; // expected-error {{no viable constructor or deduction guide}} + A a0{0, 0, ip}; + A a2{i, ip}; + + A<int> &a0r = a0; + A<int&> &a2r = a2; +#endif } diff --git a/test/CXX/temp/temp.res/p3.cpp b/test/CXX/temp/temp.res/p3.cpp new file mode 100644 index 000000000000..ea87b8d10546 --- /dev/null +++ b/test/CXX/temp/temp.res/p3.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -verify %s -std=c++11 + +template<typename T> struct A { + template<typename U> struct B; + template<typename U> using C = U; // expected-note {{here}} +}; + +struct X { + template<typename T> X(T); + struct Y { + template<typename T> Y(T); + }; +}; + +template<typename T> A // expected-error {{missing 'typename' prior to dependent type template name 'A<T>::B'}} + <T>::B<T> f1(); +template<typename T> A<T>::C<T> f2(); // expected-error {{missing 'typename' prior to dependent type template name 'A<T>::C'}} + +// FIXME: Should these cases really be valid? There doesn't appear to be a rule prohibiting them... +template<typename T> A<T>::C<X>::X(T) {} +template<typename T> A<T>::C<X>::X::Y::Y(T) {} + +// FIXME: This is ill-formed +template<typename T> int A<T>::B<T>::*f3() {} +template<typename T> int A<T>::C<X>::*f4() {} + +// FIXME: This is valid +template<typename T> int A<T>::template C<int>::*f5() {} // expected-error {{has no members}} + +template<typename T> template<typename U> struct A<T>::B { + friend A<T>::C<T> f6(); // ok, same as 'friend T f6();' + + // FIXME: Error recovery here is awful; we decide that the template-id names + // a type, and then complain about the rest of the tokens, and then complain + // that we didn't get a function declaration. + friend A<U>::C<T> f7(); // expected-error {{use 'template' keyword to treat 'C' as a dependent template name}} expected-error 3{{}} + friend A<U>::template C<T> f8(); // expected-error 3{{}} +}; diff --git a/test/CXX/temp/temp.res/temp.local/p1.cpp b/test/CXX/temp/temp.res/temp.local/p1.cpp index f6ef636daa56..faa85cb5fce3 100644 --- a/test/CXX/temp/temp.res/temp.local/p1.cpp +++ b/test/CXX/temp/temp.res/temp.local/p1.cpp @@ -1,12 +1,55 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s -// C++0x [temp.local]p1: +// C++1z [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 <>. +// injected-class-name (Clause 9). The injected-class-name can +// be used as a template-name or a type-name. + +template<typename> char id; + +template<typename> struct TempType {}; +template<template<typename> class> struct TempTemp {}; + +template<typename> void use(int&); // expected-note {{invalid explicitly-specified argument}} expected-note {{no known conversion}} +template<template<typename> class> void use(float&); // expected-note 2{{no known conversion}} +template<int> void use(char&); // expected-note 2{{invalid explicitly-specified argument}} + +template<typename T> struct A { + template<typename> struct C {}; + struct B : C<T> { + // When it is used with a template-argument-list, + A<int> *aint; + typename B::template C<int> *cint; + + // as a template-argument for a template template-parameter, + TempTemp<A> a_as_temp; + TempTemp<B::template C> c_as_temp; + + // or as the final identifier in the elaborated-type-specifier of a friend + // class template declaration, + template<typename U> friend struct A; + // it refers to the class template itself. + + // Otherwise, it is equivalent to the template-name followed by the + // template-parameters of the class template enclosed in <>. + A *aT; + typename B::C *cT; + TempType<A> a_as_type; + TempType<typename B::C> c_as_type; + friend struct A; + friend struct B::C; + + void f(T &t) { + use<A>(t); // expected-error {{no matching function}} + if constexpr (&id<T> != &id<int>) + use<B::template C>(t); // expected-error {{no matching function}} + } + }; +}; + +template struct A<int>; +template struct A<float>; +template struct A<char>; // expected-note {{instantiation of}} template <typename T> struct X0 { X0(); diff --git a/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp b/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp index 7eb5e3744d18..425d527e5212 100644 --- a/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp +++ b/test/CXX/temp/temp.spec/cxx1y-variable-template-no-body.cpp @@ -9,7 +9,7 @@ T pi = T(3.1415926535897932385); // expected-note {{template is declared here}} template int pi<int>; #ifndef FIXING -template float pi<>; // expected-error {{too few template arguments for template 'pi'}} +template float pi<>; // expected-error {{too few template arguments for variable template 'pi'}} template double pi_var0; // expected-error {{explicit instantiation of 'pi_var0' does not refer to a function template, variable template, member function, member class, or static data member}} #endif |