diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
| commit | bab175ec4b075c8076ba14c762900392533f6ee4 (patch) | |
| tree | 01f4f29419a2cb10abe13c1e63cd2a66068b0137 /test/CXX | |
| parent | 8b7a8012d223fac5d17d16a66bb39168a9a1dfc0 (diff) | |
Notes
Diffstat (limited to 'test/CXX')
84 files changed, 2703 insertions, 278 deletions
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp index 004d1e491f176..ca17ba50ac299 100644 --- a/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp @@ -9,7 +9,7 @@ namespace test0 { typedef int A; // expected-note {{declared here}} int test() { - struct A a; // expected-error {{elaborated type refers to a typedef}} + struct A a; // expected-error {{typedef 'A' cannot be referenced with a struct specifier}} return a.foo; } } @@ -18,7 +18,7 @@ namespace test0 { template <class> class A; // expected-note {{declared here}} int test() { - struct A a; // expected-error {{elaborated type refers to a template}} + struct A a; // expected-error {{template 'A' cannot be referenced with a struct specifier}} return a.foo; } } diff --git a/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p2.cpp b/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p2.cpp new file mode 100644 index 0000000000000..9e3210c6650f7 --- /dev/null +++ b/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p2.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -std=c++1z -fsized-deallocation -fexceptions -verify %s + +using size_t = decltype(sizeof(0)); + +namespace std { enum class align_val_t : size_t {}; } + +// p2 says "A template instance is never a usual deallocation function, +// regardless of its signature." We (and every other implementation) assume +// this means "A function template specialization [...]" +template<typename...Ts> struct A { + void *operator new(size_t); + void operator delete(void*, Ts...) = delete; // expected-note 4{{deleted}} +}; + +auto *a1 = new A<>; // expected-error {{deleted}} +auto *a2 = new A<size_t>; // expected-error {{deleted}} +auto *a3 = new A<std::align_val_t>; // expected-error {{deleted}} +auto *a4 = new A<size_t, std::align_val_t>; // expected-error {{deleted}} +auto *a5 = new A<std::align_val_t, size_t>; // ok, not usual diff --git a/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-noexceptions.cpp b/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-noexceptions.cpp index 9819ea0293f64..41aeeee73edaf 100644 --- a/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-noexceptions.cpp +++ b/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-noexceptions.cpp @@ -1,3 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s // RUN: %clang_cc1 -fsyntax-only -verify %s // expected-no-diagnostics namespace std { diff --git a/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp b/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp index 47b51585556f8..257aca1c3f7bf 100644 --- a/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp +++ b/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp @@ -1,3 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -fexceptions -fcxx-exceptions -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -fexceptions -fcxx-exceptions -verify -std=c++11 %s // RUN: %clang_cc1 -fsyntax-only -fexceptions -fcxx-exceptions -verify %s int *use_new(int N) { if (N == 1) @@ -19,10 +21,21 @@ namespace std { 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); +#if __cplusplus < 201103L +// expected-note@-2 {{previous declaration}} +#endif 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()'}} +void* operator new(std::size_t); +#if __cplusplus < 201103L +// expected-warning@-2 {{'operator new' is missing exception specification 'throw(std::bad_alloc)'}} +#endif +void operator delete(void*); +#if __cplusplus < 201103L +// expected-warning@-2 {{'operator delete' is missing exception specification 'throw()'}} +#else +// expected-warning@-4 {{previously declared with an explicit exception specification redeclared with an implicit}} +#endif diff --git a/test/CXX/class.access/class.friend/p1.cpp b/test/CXX/class.access/class.friend/p1.cpp index 54069b6b87bee..b6a1bcdab926f 100644 --- a/test/CXX/class.access/class.friend/p1.cpp +++ b/test/CXX/class.access/class.friend/p1.cpp @@ -1,3 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s // RUN: %clang_cc1 -fsyntax-only -verify %s // C++'0x [class.friend] p1: @@ -216,9 +219,17 @@ namespace test6 { struct A {}; struct B { - friend A::A(); + friend +#if __cplusplus >= 201103L + constexpr +#endif + A::A(); friend A::~A(); - friend A &A::operator=(const A&); + friend +#if __cplusplus >= 201402L + constexpr +#endif + A &A::operator=(const A&); }; } @@ -233,7 +244,11 @@ namespace test7 { class A { friend void X<int>::foo(); friend X<int>::X(); - friend X<int>::X(const X&); + friend +#if __cplusplus >= 201103L + constexpr +#endif + X<int>::X(const X&); private: A(); // expected-note 2 {{declared private here}} diff --git a/test/CXX/class.access/p4.cpp b/test/CXX/class.access/p4.cpp index 435b09920df63..f010ad5a2cb3b 100644 --- a/test/CXX/class.access/p4.cpp +++ b/test/CXX/class.access/p4.cpp @@ -1,3 +1,5 @@ +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++98 %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s // C++0x [class.access]p4: @@ -88,7 +90,7 @@ namespace test1 { namespace test2 { class A { private: - A(); // expected-note 3 {{declared private here}} + A(); // expected-note 1+{{declared private here}} static A foo; }; @@ -96,6 +98,7 @@ namespace test2 { A a; // expected-error {{calling a private constructor}} A A::foo; // okay +#if __cplusplus < 201103L class B : A { }; // expected-error {{base class 'test2::A' has private default constructor}} B b; // expected-note{{implicit default constructor}} @@ -106,6 +109,19 @@ namespace test2 { class D : C { }; // expected-error {{inherited virtual base class 'test2::A' has private default constructor}} D d; // expected-note{{implicit default constructor}} +#else + class B : A { }; // expected-note {{base class 'test2::A' has an inaccessible default constructor}} + B b; // expected-error {{call to implicitly-deleted default constructor}} + + // FIXME: Do a better job of explaining how we get here from class D. + class C : virtual A { // expected-note {{default constructor of 'D' is implicitly deleted because base class 'test2::A' has an inaccessible default constructor}} + public: + C(); + }; + + class D : C { }; + D d; // expected-error {{call to implicitly-deleted default constructor}} +#endif } // Implicit destructor calls. @@ -123,6 +139,7 @@ namespace test3 { A local; // expected-error {{variable of type 'test3::A' has private destructor}} } +#if __cplusplus < 201103L 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}} @@ -152,6 +169,33 @@ namespace test3 { {}; Derived3 d3; // expected-note {{implicit default constructor}}\ // expected-note{{implicit destructor}}} +#else + template <unsigned N> class Base { ~Base(); }; // expected-note 4{{declared private here}} + class Base2 : virtual Base<2> { ~Base2(); }; // expected-note 1{{declared private here}} + class Base3 : virtual Base<3> { public: ~Base3(); }; + + // 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 : + Base<0>, // expected-note {{deleted because base class 'Base<0>' has an inaccessible destructor}} + virtual Base<1>, + Base2, + virtual Base3 + {}; + Derived3 d3; // expected-error {{implicitly-deleted default constructor}} +#endif } // Conversion functions. @@ -201,9 +245,13 @@ namespace test4 { // Implicit copy assignment operator uses. namespace test5 { class A { - void operator=(const A &); // expected-note 2 {{implicitly declared private here}} + void operator=(const A &); +#if __cplusplus < 201103L + // expected-note@-2 2{{implicitly declared private here}} +#endif }; +#if __cplusplus < 201103L class Test1 { A a; }; // expected-error {{private member}} void test1() { Test1 a; @@ -215,15 +263,32 @@ namespace test5 { Test2 a; a = Test2(); // expected-note{{implicit copy}} } +#else + class Test1 { A a; }; // expected-note {{because field 'a' has an inaccessible copy assignment operator}} + void test1() { + Test1 a; + a = Test1(); // expected-error {{copy assignment operator is implicitly deleted}} + } + + class Test2 : A {}; // expected-note {{because base class 'test5::A' has an inaccessible copy assignment operator}} + void test2() { + Test2 a; + a = Test2(); // expected-error {{copy assignment operator is implicitly deleted}} + } +#endif } // Implicit copy constructor uses. namespace test6 { class A { public: A(); - private: A(const A &); // expected-note 2 {{declared private here}} + private: A(const A &); +#if __cplusplus < 201103L + // expected-note@-2 2{{declared private here}} +#endif }; +#if __cplusplus < 201103L 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 copy}} @@ -233,6 +298,17 @@ namespace test6 { void test2(const Test2 &t) { Test2 a = t; // expected-note{{implicit copy}} } +#else + class Test1 { A a; }; // expected-note {{field 'a' has an inaccessible copy constructor}} + void test1(const Test1 &t) { + Test1 a = t; // expected-error{{implicitly-deleted}} + } + + class Test2 : A {}; // expected-note {{base class 'test6::A' has an inaccessible copy constructor}} + void test2(const Test2 &t) { + Test2 a = t; // expected-error{{implicitly-deleted}} + } +#endif } // Redeclaration lookups are not accesses. diff --git a/test/CXX/class.derived/class.abstract/p16.cpp b/test/CXX/class.derived/class.abstract/p16.cpp index 2053218ca5b5f..29adbccac4795 100644 --- a/test/CXX/class.derived/class.abstract/p16.cpp +++ b/test/CXX/class.derived/class.abstract/p16.cpp @@ -31,12 +31,20 @@ private: D &operator=(D&&) = default; virtual ~D(); // expected-note 2{{here}} }; -struct E : D {}; // expected-error {{deleted function '~E' cannot override a non-deleted function}} \ - // expected-error {{deleted function 'operator=' cannot override a non-deleted function}} +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}} struct F : D {}; -struct G : D {}; // expected-error {{deleted function '~G' cannot override a non-deleted function}} - // expected-error@-1 {{deleted function 'operator=' cannot override a non-deleted function}} +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-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}} struct H : D { - H &operator=(H&&) = default; // expected-error {{deleted function 'operator=' cannot override a non-deleted function}} + H &operator=(H&&) = default; + // expected-error@-1 {{deleted function 'operator=' cannot override a non-deleted function}} + // expected-note@-3 {{move assignment operator of 'H' is implicitly deleted because base class 'D' has an inaccessible move assignment operator}} ~H(); }; diff --git a/test/CXX/class.derived/class.abstract/p2.cpp b/test/CXX/class.derived/class.abstract/p2.cpp new file mode 100644 index 0000000000000..713a5269f1431 --- /dev/null +++ b/test/CXX/class.derived/class.abstract/p2.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +// no objects of an abstract class can be created except as subobjects of a +// class derived from it + +struct A { + A() {} + A(int) : A() {} // ok + + virtual void f() = 0; // expected-note 1+{{unimplemented}} +}; + +void f(A &&a); + +void g() { + f({}); // expected-error {{abstract class}} + f({0}); // expected-error {{abstract class}} + f(0); // expected-error {{abstract class}} +} + +struct B : A { + B() : A() {} // ok +}; diff --git a/test/CXX/class.derived/class.abstract/p3.cpp b/test/CXX/class.derived/class.abstract/p3.cpp new file mode 100644 index 0000000000000..ad5b874788359 --- /dev/null +++ b/test/CXX/class.derived/class.abstract/p3.cpp @@ -0,0 +1,97 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +struct A { + A() {} + A(int) : A() {} // ok + + virtual void f() = 0; // expected-note 1+{{unimplemented}} +}; + +template<typename> struct SecretlyAbstract { + SecretlyAbstract(); + SecretlyAbstract(int); + virtual void f() = 0; // expected-note 1+{{unimplemented}} +}; +using B = SecretlyAbstract<int>; +using C = SecretlyAbstract<float>; +using D = SecretlyAbstract<char>[1]; + +B b; // expected-error {{abstract class}} +D d; // expected-error {{abstract class}} + +template<int> struct N; + +// Note: C is not instantiated anywhere in this file, so we never discover that +// it is in fact abstract. The C++ standard suggests that we need to +// instantiate in all cases where abstractness could affect the validity of a +// program, but that breaks a *lot* of code, so we don't do that. +// +// FIXME: Once DR1640 is resolved, remove the check on forming an abstract +// array type entirely. The only restriction we need is that you can't create +// an object of abstract (most-derived) type. + + +// An abstract class shall not be used + +// - as a parameter type +void f(A&); +void f(A); // expected-error {{abstract class}} +void f(A[1]); // expected-error {{abstract class}} +void f(B); // expected-error {{abstract class}} +void f(B[1]); // expected-error {{abstract class}} +void f(C); +void f(C[1]); +void f(D); // expected-error {{abstract class}} +void f(D[1]); // expected-error {{abstract class}} + +// - as a function return type +A &f(N<0>); +A *f(N<1>); +A f(N<2>); // expected-error {{abstract class}} +A (&f(N<3>))[2]; // expected-error {{abstract class}} +B f(N<4>); // expected-error {{abstract class}} +B (&f(N<5>))[2]; // expected-error {{abstract class}} +C f(N<6>); +C (&f(N<7>))[2]; + +// - as the type of an explicit conversion +void g(A&&); +void h() { + A(); // expected-error {{abstract class}} + A(0); // expected-error {{abstract class}} + A{}; // expected-error {{abstract class}} + A{0}; // expected-error {{abstract class}} + (A)(0); // expected-error {{abstract class}} + (A){}; // expected-error {{abstract class}} + (A){0}; // expected-error {{abstract class}} + + D(); // expected-error {{array type}} + D{}; // expected-error {{abstract class}} + D{0}; // expected-error {{abstract class}} + (D){}; // expected-error {{abstract class}} + (D){0}; // expected-error {{abstract class}} +} + +template<typename T> void t(T); // expected-note 2{{abstract class}} +void i(A &a, B &b, C &c, D &d) { + // FIXME: These should be handled consistently. We currently reject the first + // two early because we (probably incorrectly, depending on dr1640) take + // abstractness into account in forming implicit conversion sequences. + t(a); // expected-error {{no matching function}} + t(b); // expected-error {{no matching function}} + t(c); // expected-error {{allocating an object of abstract class type}} + t(d); // ok, decays to pointer +} + +struct E : A { + E() : A() {} // ok + E(int n) : A( A(n) ) {} // expected-error {{abstract class}} +}; + +namespace std { + template<typename T> struct initializer_list { + const T *begin, *end; + initializer_list(); + }; +} +std::initializer_list<A> ila = {1, 2, 3, 4}; // expected-error {{abstract class}} diff --git a/test/CXX/class/class.union/p1.cpp b/test/CXX/class/class.union/p1.cpp index 439cc9cec8dad..84ce1c991533d 100644 --- a/test/CXX/class/class.union/p1.cpp +++ b/test/CXX/class/class.union/p1.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s void abort() __attribute__((noreturn)); diff --git a/test/CXX/conv/conv.fctptr/p1.cpp b/test/CXX/conv/conv.fctptr/p1.cpp new file mode 100644 index 0000000000000..be9c050af51ef --- /dev/null +++ b/test/CXX/conv/conv.fctptr/p1.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s -triple x86_64-unknown-unknown + +struct S; + +typedef void Nothrow() noexcept; +typedef void Throw(); + +Nothrow *a; +Throw *b; +Nothrow S::*c; +Throw S::*d; + +void test() { + a = b; // expected-error {{assigning to 'Nothrow *' (aka 'void (*)() noexcept') from incompatible type 'Throw *' (aka 'void (*)()'): different exception specifications}} + b = a; + c = d; // expected-error {{assigning to 'Nothrow S::*' from incompatible type 'Throw S::*': different exception specifications}} + d = c; + + // Function pointer conversions do not combine properly with qualification conversions. + // FIXME: This seems like a defect. + Nothrow *const *pa = b; // expected-error {{cannot initialize}} + Throw *const *pb = a; // expected-error {{cannot initialize}} + Nothrow *const S::*pc = d; // expected-error {{cannot initialize}} + Throw *const S::*pd = c; // expected-error {{cannot initialize}} +} + +// ... The result is a pointer to the function. +void f() noexcept; +constexpr void (*p)() = &f; +static_assert(f == p); + +struct S { void f() noexcept; }; +constexpr void (S::*q)() = &S::f; +static_assert(q == &S::f); + + +namespace std_example { + void (*p)(); + void (**pp)() noexcept = &p; // expected-error {{cannot initialize a variable of type 'void (**)() noexcept' with an rvalue of type 'void (**)()'}} + + struct S { typedef void (*p)(); operator p(); }; // expected-note {{candidate}} + void (*q)() noexcept = S(); // expected-error {{no viable conversion from 'std_example::S' to 'void (*)() noexcept'}} +} diff --git a/test/CXX/cpp/cpp.predefined/p1.cpp b/test/CXX/cpp/cpp.predefined/p1.cpp new file mode 100644 index 0000000000000..c0dcbd54f3873 --- /dev/null +++ b/test/CXX/cpp/cpp.predefined/p1.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -std=c++1z %s -verify -triple x86_64-linux-gnu -DALIGN=16 +// RUN: %clang_cc1 -std=c++1z %s -verify -fnew-alignment=2 -DALIGN=2 +// RUN: %clang_cc1 -std=c++1z %s -verify -fnew-alignment=256 -DALIGN=256 + +// expected-no-diagnostics + +#if ALIGN != __STDCPP_DEFAULT_NEW_ALIGNMENT__ +#error wrong value for __STDCPP_DEFAULT_NEW_ALIGNMENT__ +#endif diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp index f92362380a1c2..39bed7db7ab38 100644 --- a/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp @@ -1,13 +1,18 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// FIXME: We should probably suppress the warning on reopening an inline +// namespace without the inline keyword if it's not the first opening of the +// namespace in the file, because there's no risk of the inlineness differing +// across TUs in that case. + 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 reopened as a non-inline namespace}} +namespace IL {} // expected-warning{{inline namespace reopened 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-warning {{cannot be reopened as a non-inline namespace}} + namespace {} // expected-warning {{inline namespace reopened as a non-inline namespace}} } diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp index 6c63f061ab0f1..0ea4eeb1e9b08 100644 --- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify %s // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s // RUN: not %clang_cc1 -fsyntax-only -std=c++98 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck --check-prefix=CXX98 %s // RUN: not %clang_cc1 -fsyntax-only -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck --check-prefix=CXX11 %s // C++0x N2914. @@ -44,10 +45,158 @@ void f() { #endif } -template <typename T> -struct PR21933 : T { - static void StaticFun() { using T::member; } // expected-error{{using declaration cannot refer to class member}} -}; +namespace PR21933 { + struct A { int member; }; + struct B { static int member; }; + enum C { member }; + + template <typename T> + struct X { + static void StaticFun() { + using T::member; // expected-error 2{{class member}} expected-note {{use a reference instead}} +#if __cplusplus < 201103L + // expected-error@-2 {{cannot be used prior to '::'}} +#endif + (void)member; + } + }; + template<typename T> + struct Y : T { + static void StaticFun() { + using T::member; // expected-error 2{{class member}} expected-note {{use a reference instead}} + (void)member; + } + }; + + void f() { + X<A>::StaticFun(); // expected-note {{instantiation of}} + X<B>::StaticFun(); // expected-note {{instantiation of}} + X<C>::StaticFun(); +#if __cplusplus < 201103L + // expected-note@-2 {{instantiation of}} +#endif + Y<A>::StaticFun(); // expected-note {{instantiation of}} + Y<B>::StaticFun(); // expected-note {{instantiation of}} + } + + template<typename T, typename U> void value_vs_value() { + using T::a; // expected-note {{previous}} +#if __cplusplus < 201103L + // expected-error@-2 {{cannot be used prior to '::'}} +#endif + extern int a(); // expected-error {{different kind of symbol}} + a(); + + extern int b(); // expected-note {{previous}} + using T::b; // expected-error {{different kind of symbol}} + b(); + + using T::c; // expected-note {{previous}} + using U::c; // expected-error-re {{redefinition of 'c'{{$}}}} + c(); + } + + template<typename T, typename U> void value_vs_type() { + using T::Xt; // expected-note {{previous}} + typedef struct {} Xt; // expected-error {{different kind of symbol}} + (void)Xt; + + using T::Xs; // expected-note {{hidden by}} + struct Xs {}; + (void)Xs; + Xs xs; // expected-error {{must use 'struct'}} + + using T::Xe; // expected-note {{hidden by}} + enum Xe {}; + (void)Xe; + Xe xe; // expected-error {{must use 'enum'}} + + typedef struct {} Yt; // expected-note {{candidate}} + using T::Yt; // eypected-error {{different kind of symbol}} expected-note {{candidate}} + Yt yt; // expected-error {{ambiguous}} + + struct Ys {}; + using T::Ys; // expected-note {{hidden by}} + (void)Ys; + Ys ys; // expected-error {{must use 'struct'}} + + enum Ye {}; + using T::Ye; // expected-note {{hidden by}} + Ye ye; // expected-error {{must use 'enum'}} + } + + template<typename T> void type() { + // Must be a class member because T:: can only name a class or enum, + // and an enum cannot have a type member. + using typename T::X; // expected-error {{cannot refer to class member}} + } + + namespace N1 { enum E { a, b, c }; } + namespace N2 { enum E { a, b, c }; } + void g() { value_vs_value<N1::E, N2::E>(); } +#if __cplusplus < 201103L + // expected-note@-2 {{in instantiation of}} +#endif + +#if __cplusplus >= 201402L + namespace partial_substitute { + template<typename T> auto f() { + return [](auto x) { + using A = typename T::template U<decltype(x)>; + using A::E::e; + struct S : A { + using A::f; + using typename A::type; + type f(int) { return e; } + }; + return S(); + }; + } + enum Enum { e }; + struct X { + template<typename T> struct U { + int f(int, int); + using type = int; + using E = Enum; + }; + }; + int test() { + auto s = f<X>()(0); + return s.f(0) + s.f(0, 0); + } + + template<typename T, typename U> auto g() { + return [](auto x) { + using X = decltype(x); + struct S : T::template Q<X>, U::template Q<X> { + using T::template Q<X>::f; + using U::template Q<X>::f; + void h() { f(); } + void h(int n) { f(n); } + }; + return S(); + }; + } + struct A { template<typename> struct Q { int f(); }; }; + struct B { template<typename> struct Q { int f(int); }; }; + int test2() { + auto s = g<A, B>()(0); + s.f(); + s.f(0); + s.h(); + s.h(0); + } + } +#endif + + template<typename T, typename U> struct RepeatedMember : T, U { + // FIXME: This is the wrong error: we should complain that a member type + // cannot be redeclared at class scope. + using typename T::type; // expected-note {{candidate}} + using typename U::type; // expected-note {{candidate}} + type x; // expected-error {{ambiguous}} + }; +} struct S { static int n; diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp index 027104151ac68..f3e79c0aae44a 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp @@ -2,18 +2,18 @@ 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}} +struct X<int>* p2; // expected-error {{type alias template 'X' cannot be referenced with a struct specifier}} 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}} + struct F<int> i; // expected-error {{type alias template 'Id' cannot be referenced with a struct specifier}} 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}} + struct Y<F>::template U<char> k; // expected-error 2{{type alias template 'U' cannot be referenced with a struct specifier}} typename Y<F>::template U<char> l; // ok }; template struct Y<Id>; // expected-note {{requested here}} diff --git a/test/CXX/dcl.decl/dcl.decomp/p2.cpp b/test/CXX/dcl.decl/dcl.decomp/p2.cpp new file mode 100644 index 0000000000000..211719a7e9c64 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.decomp/p2.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s -Wpedantic + +struct X { + X(int); + X(const X&) = delete; +}; + +int array() { + static int arr[3] = {}; + auto [a, b, c] = arr; + static_assert(&a != &arr[0]); + + using I3 = int[3]; + auto [a2, b2, c2] = I3{1, 2, 3}; + + using X3 = X[3]; + auto [a3, b3, c3] = X3{1, 2, 3}; + + auto &[d, e] = arr; // expected-error {{type 'int [3]' decomposes into 3 elements, but only 2 names were provided}} + auto &[f, g, h, i] = arr; // expected-error {{type 'int [3]' decomposes into 3 elements, but 4 names were provided}} + + auto &[r0, r1, r2] = arr; + const auto &[cr0, cr1, cr2] = arr; + + static_assert(&arr[0] == &r0); + static_assert(&arr[0] == &cr0); + + using T = int; + using T = decltype(r0); + using U = const int; + using U = decltype(cr0); + + return r1 + cr2; +} diff --git a/test/CXX/dcl.decl/dcl.decomp/p3.cpp b/test/CXX/dcl.decl/dcl.decomp/p3.cpp new file mode 100644 index 0000000000000..b7092e3af0238 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.decomp/p3.cpp @@ -0,0 +1,232 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +using size_t = decltype(sizeof(0)); + +struct A { int x, y; }; +struct B { int x, y; }; + +void no_tuple_size_1() { auto [x, y] = A(); } // ok, decompose elementwise + +namespace std { template<typename T> struct tuple_size; } +void no_tuple_size_2() { auto [x, y] = A(); } // ok, decompose elementwise + +struct Bad1 { int a, b; }; +template<> struct std::tuple_size<Bad1> {}; +void no_tuple_size_3() { auto [x, y] = Bad1(); } // expected-error {{cannot decompose this type; 'std::tuple_size<Bad1>::value' is not a valid integral constant expression}} + +struct Bad2 {}; +template<> struct std::tuple_size<Bad2> { const int value = 5; }; +void no_tuple_size_4() { auto [x, y] = Bad2(); } // expected-error {{cannot decompose this type; 'std::tuple_size<Bad2>::value' is not a valid integral constant expression}} + +template<> struct std::tuple_size<A> { static const int value = 3; }; +template<> struct std::tuple_size<B> { enum { value = 3 }; }; + +void no_get_1() { + { + auto [a0, a1] = A(); // expected-error {{decomposes into 3 elements}} + auto [b0, b1] = B(); // expected-error {{decomposes into 3 elements}} + } + auto [a0, a1, a2] = A(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit initialization of binding declaration 'a0'}} +} + +int get(A); + +void no_get_2() { + // FIXME: This diagnostic is not great. + auto [a0, a1, a2] = A(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit initialization of binding declaration 'a0'}} +} + +template<int> float &get(A); + +void no_tuple_element_1() { + auto [a0, a1, a2] = A(); // expected-error-re {{'std::tuple_element<0U{{L*}}, A>::type' does not name a type}} expected-note {{in implicit}} +} + +namespace std { template<size_t, typename> struct tuple_element; } // expected-note 2{{here}} + +void no_tuple_element_2() { + auto [a0, a1, a2] = A(); // expected-error {{implicit instantiation of undefined template 'std::tuple_element<0, A>'}} expected-note {{in implicit}} +} + +template<> struct std::tuple_element<0, A> { typedef float type; }; + +void no_tuple_element_3() { + auto [a0, a1, a2] = A(); // expected-error {{implicit instantiation of undefined template 'std::tuple_element<1, A>'}} expected-note {{in implicit}} +} + +template<> struct std::tuple_element<1, A> { typedef float &type; }; +template<> struct std::tuple_element<2, A> { typedef const float &type; }; + +template<int N> auto get(B) -> int (&)[N + 1]; +template<int N> struct std::tuple_element<N, B> { typedef int type[N +1 ]; }; + +template<typename T> struct std::tuple_size<const T> : std::tuple_size<T> {}; +template<size_t N, typename T> struct std::tuple_element<N, const T> { + typedef const typename std::tuple_element<N, T>::type type; +}; + +void referenced_type() { + auto [a0, a1, a2] = A(); + auto [b0, b1, b2] = B(); + + A a; + B b; + auto &[ar0, ar1, ar2] = a; + auto &[br0, br1, br2] = b; + + auto &&[arr0, arr1, arr2] = A(); + auto &&[brr0, brr1, brr2] = B(); + + const auto &[acr0, acr1, acr2] = A(); + const auto &[bcr0, bcr1, bcr2] = B(); + + + using Float = float; + using Float = decltype(a0); + using Float = decltype(ar0); + using Float = decltype(arr0); + + using ConstFloat = const float; + using ConstFloat = decltype(acr0); + + using FloatRef = float&; + using FloatRef = decltype(a1); + using FloatRef = decltype(ar1); + using FloatRef = decltype(arr1); + using FloatRef = decltype(acr1); + + using ConstFloatRef = const float&; + using ConstFloatRef = decltype(a2); + using ConstFloatRef = decltype(ar2); + using ConstFloatRef = decltype(arr2); + using ConstFloatRef = decltype(acr2); + + + using Int1 = int[1]; + using Int1 = decltype(b0); + using Int1 = decltype(br0); + using Int1 = decltype(brr0); + + using ConstInt1 = const int[1]; + using ConstInt1 = decltype(bcr0); + + using Int2 = int[2]; + using Int2 = decltype(b1); + using Int2 = decltype(br1); + using Int2 = decltype(brr1); + + using ConstInt2 = const int[2]; + using ConstInt2 = decltype(bcr1); + + using Int3 = int[3]; + using Int3 = decltype(b2); + using Int3 = decltype(br2); + using Int3 = decltype(brr2); + + using ConstInt3 = const int[3]; + using ConstInt3 = decltype(bcr2); +} + +struct C { template<int> int get(); }; +template<> struct std::tuple_size<C> { static const int value = 1; }; +template<> struct std::tuple_element<0, C> { typedef int type; }; + +int member_get() { + auto [c] = C(); + using T = int; + using T = decltype(c); + return c; +} + +struct D { template<int> struct get {}; }; // expected-note {{declared here}} +template<> struct std::tuple_size<D> { static const int value = 1; }; +template<> struct std::tuple_element<0, D> { typedef D::get<0> type; }; +void member_get_class_template() { + auto [d] = D(); // expected-error {{cannot refer to member 'get' in 'D' with '.'}} expected-note {{in implicit init}} +} + +struct E { int get(); }; +template<> struct std::tuple_size<E> { static const int value = 1; }; +template<> struct std::tuple_element<0, E> { typedef int type; }; +void member_get_non_template() { + // FIXME: This diagnostic is not very good. + auto [e] = E(); // expected-error {{no member named 'get'}} expected-note {{in implicit init}} +} + +namespace ADL { + struct X {}; +}; +template<int> int get(ADL::X); +template<> struct std::tuple_size<ADL::X> { static const int value = 1; }; +template<> struct std::tuple_element<0, ADL::X> { typedef int type; }; +void adl_only_bad() { + auto [x] = ADL::X(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit init}} +} + +template<typename ElemType, typename GetTypeLV, typename GetTypeRV> +struct wrap { + template<size_t> GetTypeLV get() &; + template<size_t> GetTypeRV get() &&; +}; +template<typename ET, typename GTL, typename GTR> +struct std::tuple_size<wrap<ET, GTL, GTR>> { + static const int value = 1; +}; +template<typename ET, typename GTL, typename GTR> +struct std::tuple_element<0, wrap<ET, GTL, GTR>> { + using type = ET; +}; + +template<typename T> T &lvalue(); + +void test_value_category() { + // If the declared variable is an lvalue reference, the operand to get is an + // lvalue. Otherwise it's an xvalue. + { auto [a] = wrap<int, void, int>(); } + { auto &[a] = lvalue<wrap<int, int, void>>(); } + { auto &&[a] = wrap<int, void, int>(); } + // If the initializer (call to get) is an lvalue, the binding is an lvalue + // reference to the element type. Otherwise it's an rvalue reference to the + // element type. + { auto [a] = wrap<int, void, int&>(); } + { auto [a] = wrap<int&, void, int&>(); } + { auto [a] = wrap<int&&, void, int&>(); } // ok, reference collapse to int& + + { auto [a] = wrap<int, void, int&&>(); } + { auto [a] = wrap<int&, void, int&&>(); } // expected-error {{non-const lvalue reference to type 'int' cannot bind}} expected-note {{in implicit}} + { auto [a] = wrap<const int&, void, int&&>(); } + { auto [a] = wrap<int&&, void, int&&>(); } + + { auto [a] = wrap<int, void, float&>(); } // expected-error {{cannot bind}} expected-note {{implicit}} + { auto [a] = wrap<const int, void, float&>(); } // ok, const int &a can bind to float + { auto [a] = wrap<int, void, float>(); } // ok, int &&a can bind to float +} + +namespace constant { + struct Q {}; + template<int N> constexpr int get(Q &&) { return N * N; } +} +template<> struct std::tuple_size<constant::Q> { static const int value = 3; }; +template<int N> struct std::tuple_element<N, constant::Q> { typedef int type; }; +namespace constant { + Q q; + // This creates and lifetime-extends a temporary to hold the result of each get() call. + auto [a, b, c] = q; // expected-note {{temporary}} + static_assert(a == 0); // expected-error {{constant expression}} expected-note {{temporary}} + + constexpr bool f() { + auto [a, b, c] = q; + return a == 0 && b == 1 && c == 4; + } + static_assert(f()); + + constexpr int g() { + int *p = nullptr; + { + auto [a, b, c] = q; + p = &c; + } + return *p; // expected-note {{read of object outside its lifetime}} + } + static_assert(g() == 4); // expected-error {{constant}} expected-note {{in call to 'g()'}} +} diff --git a/test/CXX/dcl.decl/dcl.decomp/p4.cpp b/test/CXX/dcl.decl/dcl.decomp/p4.cpp new file mode 100644 index 0000000000000..c461eb6f54b72 --- /dev/null +++ b/test/CXX/dcl.decl/dcl.decomp/p4.cpp @@ -0,0 +1,200 @@ +// RUN: %clang_cc1 -std=c++1z -verify -triple i686-linux-gnu %s + +template<typename T, typename U> struct same; +template<typename T> struct same<T, T> { ~same(); }; + +struct Empty {}; + +struct A { + int a; +}; + +namespace NonPublicMembers { + struct NonPublic1 { + protected: + int a; // expected-note {{declared protected here}} + }; + + struct NonPublic2 { + private: + int a; // expected-note 2{{declared private here}} + }; + + struct NonPublic3 : private A {}; // expected-note {{constrained by private inheritance}} + + struct NonPublic4 : NonPublic2 {}; + + void test() { + auto [a1] = NonPublic1(); // expected-error {{cannot decompose non-public member 'a' of 'NonPublicMembers::NonPublic1'}} + auto [a2] = NonPublic2(); // expected-error {{cannot decompose non-public member 'a' of 'NonPublicMembers::NonPublic2'}} + auto [a3] = NonPublic3(); // expected-error {{cannot decompose members of non-public base class 'A' of 'NonPublic3'}} + auto [a4] = NonPublic4(); // expected-error {{cannot decompose non-public member 'a' of 'NonPublicMembers::NonPublic4'}} + } +} + +namespace AnonymousMember { + struct Struct { + struct { // expected-note {{declared here}} + int i; + }; + }; + + struct Union { + union { // expected-note {{declared here}} + int i; + }; + }; + + void test() { + auto [a1] = Struct(); // expected-error {{cannot decompose class type 'AnonymousMember::Struct' because it has an anonymous struct member}} + auto [a2] = Union(); // expected-error {{cannot decompose class type 'AnonymousMember::Union' because it has an anonymous union member}} + } +} + +namespace MultipleClasses { + struct B : A { + int a; + }; + + struct C { int a; }; + struct D : A, C {}; + + struct E : virtual A {}; + struct F : A, E {}; // expected-warning {{direct base 'A' is inaccessible due to ambiguity}} + + struct G : virtual A {}; + struct H : E, G {}; + + struct I { int i; }; + struct J : I {}; + struct K : I, virtual J {}; // expected-warning {{direct base 'MultipleClasses::I' is inaccessible due to ambiguity}} + + struct L : virtual J {}; + struct M : virtual J, L {}; + + void test() { + auto [b] = B(); // expected-error {{cannot decompose class type 'B': both it and its base class 'A' have non-static data members}} + auto [d] = D(); // expected-error {{cannot decompose class type 'D': its base classes 'A' and 'MultipleClasses::C' have non-static data members}} + auto [e] = E(); + auto [f] = F(); // expected-error-re {{cannot decompose members of ambiguous base class 'A' of 'F':{{.*}}struct MultipleClasses::F -> struct A{{.*}}struct MultipleClasses::F -> struct MultipleClasses::E -> struct A}} + auto [h] = H(); // ok, only one (virtual) base subobject even though there are two paths to it + auto [k] = K(); // expected-error {{cannot decompose members of ambiguous base class 'MultipleClasses::I'}} + auto [m] = M(); // ok, all paths to I are through the same virtual base subobject J + + same<decltype(m), int>(); + } +} + +namespace BindingTypes { + struct A { + int i = 0; + int &r = i; + const float f = i; + mutable volatile int mvi; + }; + void e() { + auto [i,r,f,mvi] = A(); + + same<decltype(i), int>(); + same<decltype(r), int&>(); + same<decltype(f), const float>(); + same<decltype(mvi), volatile int>(); + + same<decltype((i)), int&>(); + same<decltype((r)), int&>(); + same<decltype((f)), const float&>(); + same<decltype((mvi)), volatile int&>(); + } + void f() { + auto &&[i,r,f,mvi] = A(); + + same<decltype(i), int>(); + same<decltype(r), int&>(); + same<decltype(f), const float>(); + same<decltype(mvi), volatile int>(); + + same<decltype((i)), int&>(); + same<decltype((r)), int&>(); + same<decltype((f)), const float&>(); + same<decltype((mvi)), volatile int&>(); + } + void g() { + const auto [i,r,f,mvi] = A(); + + same<decltype(i), const int>(); + same<decltype(r), int&>(); + same<decltype(f), const float>(); + same<decltype(mvi), volatile int>(); // not 'const volatile int', per expected resolution of DRxxx + + same<decltype((i)), const int&>(); + same<decltype((r)), int&>(); + same<decltype((f)), const float&>(); + same<decltype((mvi)), volatile int&>(); // not 'const volatile int&', per expected resolution of DRxxx + } + void h() { + typedef const A CA; + auto &[i,r,f,mvi] = CA(); // type of var is 'const A &' + + same<decltype(i), const int>(); // not 'int', per expected resolution of DRxxx + same<decltype(r), int&>(); + same<decltype(f), const float>(); + same<decltype(mvi), volatile int>(); // not 'const volatile int', per expected resolution of DRxxx + + same<decltype((i)), const int&>(); // not 'int&', per expected resolution of DRxxx + same<decltype((r)), int&>(); + same<decltype((f)), const float&>(); + same<decltype((mvi)), volatile int&>(); // not 'const volatile int&', per expected resolution of DRxxx + } + struct B { + mutable int i; + }; + void mut() { + auto [i] = B(); + const auto [ci] = B(); + volatile auto [vi] = B(); + same<decltype(i), int>(); + same<decltype(ci), int>(); + same<decltype(vi), volatile int>(); + } +} + +namespace Bitfield { + struct S { unsigned long long x : 4, y : 32; int z; }; // expected-note 2{{here}} + int f(S s) { + auto [a, b, c] = s; + unsigned long long &ra = a; // expected-error {{bit-field 'x'}} + unsigned long long &rb = b; // expected-error {{bit-field 'y'}} + int &rc = c; + + // the type of the binding is the type of the field + same<decltype(a), unsigned long long>(); + same<decltype(b), unsigned long long>(); + + // the type of the expression is an lvalue of the field type + // (even though a reference can't bind to the field) + same<decltype((a)), unsigned long long&>(); + same<decltype((b)), unsigned long long&>(); + + // the expression promotes to a type large enough to hold the result + same<decltype(+a), int>(); + same<decltype(+b), unsigned int>(); + return rc; + } +} + +namespace Constexpr { + struct Q { int a, b; constexpr Q() : a(1), b(2) {} }; + constexpr Q q; + auto &[qa, qb] = q; + static_assert(&qa == &q.a && &qb == &q.b); + static_assert(qa == 1 && qb == 2); +} + +namespace std_example { + struct S { int x1 : 2; volatile double y1; }; + S f(); + const auto [x, y] = f(); + + same<decltype((x)), const int&> same1; + same<decltype((y)), const volatile double&> same2; +} diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp index 40f6431e3ddb8..7a92e7a13d959 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp @@ -122,3 +122,39 @@ struct DefaultedAggr { ~DefaultedAggr() = default; }; DefaultedAggr da = { 42 } ; + +struct ExplicitDefaultedAggr { + int n; + explicit ExplicitDefaultedAggr() = default; // expected-note {{candidate}} + ExplicitDefaultedAggr(const ExplicitDefaultedAggr &) = default; // expected-note {{candidate}} + ExplicitDefaultedAggr(ExplicitDefaultedAggr &&) = default; // expected-note {{candidate}} +}; +ExplicitDefaultedAggr eda = { 42 }; // expected-error {{no matching constructor}} +ExplicitDefaultedAggr eda2{}; + +struct DefaultedBase { + int n; + DefaultedBase() = default; // expected-note 0+ {{candidate}} + DefaultedBase(DefaultedBase const&) = default; // expected-note 0+ {{candidate}} + DefaultedBase(DefaultedBase &&) = default; // expected-note 0+ {{candidate}} +}; + +struct InheritingConstructors : DefaultedBase { // expected-note 3 {{candidate}} + using DefaultedBase::DefaultedBase; // expected-note 2 {{inherited here}} +}; +InheritingConstructors ic = { 42 }; // expected-error {{no matching constructor}} + +struct NonInheritingConstructors : DefaultedBase {}; // expected-note 0+ {{candidate}} +NonInheritingConstructors nic = { 42 }; +#if __cplusplus <= 201402L +// expected-error@-2 {{no matching constructor}} +#endif + +struct NonAggrBase { + NonAggrBase(int) {} +}; +struct HasNonAggrBase : NonAggrBase {}; // expected-note 0+ {{candidate}} +HasNonAggrBase hnab = {42}; +#if __cplusplus <= 201402L +// expected-error@-2 {{no matching constructor}} +#endif diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp index 299611ba73593..d66494fa2c2c4 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.list/p7-0x-fixits.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wc++11-compat -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -fsyntax-only -std=c++98 -Wc++11-compat -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s // Verify that the appropriate fixits are emitted for narrowing conversions in // initializer lists. diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4.cpp new file mode 100644 index 0000000000000..1a3732d99ea6f --- /dev/null +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +void f() noexcept; +void (&r)() = f; +void (&s)() noexcept = r; // expected-error {{cannot bind}} + +void (&cond1)() noexcept = true ? r : f; // expected-error {{cannot bind}} +void (&cond2)() noexcept = true ? f : r; // expected-error {{cannot bind}} +// FIXME: Strictly, the rules in p4 don't allow this, because the operand types +// are not of the same type other than cv-qualifiers, but we consider that to +// be a defect, and instead allow reference-compatible types here. +void (&cond3)() = true ? r : f; +void (&cond4)() = true ? f : r; diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp index f86b24e992590..7a5caef36e737 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-show-option -Wbind-to-temporary-copy -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++03 -fdiagnostics-show-option -Wbind-to-temporary-copy -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 @@ -19,7 +19,7 @@ private: }; struct X3 { - X3(); + X3(); // expected-note{{requires 0 arguments, but 1 was provided}} private: X3(X3&); // expected-note{{candidate constructor not viable: expects an l-value for 1st argument}} @@ -42,8 +42,8 @@ struct X4 { // 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'}} + X5(); // expected-note {{requires 0 arguments}} + X5(const X5&, const X5& = X5()); // expected-warning{{no viable constructor copying parameter of type 'X5'}} expected-note {{requires 2 arguments}} }; void g1(const X1&); diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp index be1113d47e3a6..052349c8e2e00 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -ast-dump %s 2>&1 | FileCheck %s -// CHECK: example0 +// CHECK-LABEL: example0 void example0() { double d = 2.0; // CHECK: VarDecl{{.*}}rd 'double &' @@ -14,14 +14,15 @@ void example0() { struct A { }; struct B : A { } b; -// CHECK: example1 +// CHECK-LABEL: example1 void example1() { // CHECK: VarDecl{{.*}}ra 'struct A &' // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue <DerivedToBase (A)> A &ra = b; // CHECK: VarDecl{{.*}}rca 'const struct A &' - // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <NoOp> - // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue <DerivedToBase (A)> + // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <DerivedToBase (A)> + // CHECK-NOT: MaterializeTemporaryExpr + // CHECK: ImplicitCastExpr{{.*}}'const struct B' lvalue <NoOp> const A& rca = b; } @@ -31,21 +32,23 @@ struct X { operator B(); } x; -// CHECK: example2 +// CHECK-LABEL: example2 void example2() { // CHECK: VarDecl{{.*}}rca 'const struct A &' - // CHECK: ImplicitCastExpr{{.*}}'const struct A' <NoOp> - // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)> + // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <DerivedToBase (A)> + // CHECK: MaterializeTemporaryExpr{{.*}}'const struct B' + // CHECK: ImplicitCastExpr{{.*}}'const struct B' <NoOp> // CHECK: CallExpr{{.*}}B const A &rca = f(); // CHECK: VarDecl{{.*}}r 'const struct A &' - // CHECK: ImplicitCastExpr{{.*}}'const struct A' <NoOp> - // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)> + // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <DerivedToBase (A)> + // CHECK: MaterializeTemporaryExpr{{.*}}'const struct B' + // CHECK: ImplicitCastExpr{{.*}}'const struct B' <NoOp> // CHECK: CXXMemberCallExpr{{.*}}'struct B' const A& r = x; } -// CHECK: example3 +// CHECK-LABEL: example3 void example3() { // CHECK: VarDecl{{.*}}rcd2 'const double &' // CHECK: ImplicitCastExpr{{.*}} <IntegralToFloating> diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp index 263f661208c5a..e775e8f0e3cc5 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp @@ -41,7 +41,7 @@ namespace PR6066 { namespace test3 { struct A { - unsigned bitX : 4; // expected-note 4 {{bit-field is declared here}} + unsigned bitX : 4; // expected-note 3 {{bit-field is declared here}} unsigned bitY : 4; // expected-note {{bit-field is declared here}} unsigned var; @@ -50,7 +50,7 @@ namespace test3 { void test(A *a) { unsigned &t0 = a->bitX; // expected-error {{non-const reference cannot bind to bit-field 'bitX'}} - unsigned &t1 = (unsigned&) a->bitX; // expected-error {{non-const reference cannot bind to bit-field 'bitX'}} + unsigned &t1 = (unsigned&) a->bitX; // expected-error {{C-style cast from bit-field lvalue to reference type 'unsigned int &'}} unsigned &t2 = const_cast<unsigned&>(a->bitX); // expected-error {{const_cast from bit-field lvalue to reference type 'unsigned int &'}} unsigned &t3 = (a->foo(), a->bitX); // expected-error {{non-const reference cannot bind to bit-field 'bitX'}} unsigned &t4 = (a->var ? a->bitX : a->bitY); // expected-error {{non-const reference cannot bind to bit-field}} diff --git a/test/CXX/dcl.decl/dcl.init/p5.cpp b/test/CXX/dcl.decl/dcl.init/p5.cpp index e7ccb2ec41e68..76e53edf33574 100644 --- a/test/CXX/dcl.decl/dcl.init/p5.cpp +++ b/test/CXX/dcl.decl/dcl.init/p5.cpp @@ -1,3 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s // RUN: %clang_cc1 -fsyntax-only -verify %s // A program that calls for default-initialization or value-initialization of @@ -5,6 +7,11 @@ // cv-unqualified version of T is used for these definitions of // zero-initialization, default-initialization, and value-initialization. +typedef int &IR; +IR r; // expected-error {{declaration of reference variable 'r' requires an initializer}} +int n = IR(); // expected-error {{reference to type 'int' requires an initializer}} + +#if __cplusplus < 201103L struct S { // expected-error {{implicit default constructor for 'S' must explicitly initialize the reference member}} int &x; // expected-note {{declared here}} expected-error 3{{reference to type 'int' requires an initializer}} }; @@ -22,6 +29,25 @@ struct U { T t[3]; // expected-note {{in value-initialization of type 'T' here}} }; U u = U(); // expected-note {{in value-initialization of type 'U' here}} +#else +struct S { + int &x; // expected-note 4{{because field 'x' of reference type 'int &' would not be initialized}} +}; +S s; // expected-error {{deleted default constructor}} +S f() { + return S(); // expected-error {{deleted default constructor}} +} + +struct T + : S { // expected-note 2{{because base class 'S' has a deleted default constructor}} +}; +T t = T(); // expected-error {{deleted default constructor}} + +struct U { + T t[3]; // expected-note {{because field 't' has a deleted default constructor}} +}; +U u = U(); // expected-error {{deleted default constructor}} +#endif // Ensure that we handle C++11 in-class initializers properly as an extension. // In this case, there is no user-declared default constructor, so we @@ -29,20 +55,19 @@ U u = U(); // expected-note {{in value-initialization of type 'U' here}} // constructor call anyway, because the default constructor is not trivial. struct V { int n; - int &r = n; // expected-warning {{C++11}} + int &r = n; // expected-warning 0-1{{C++11}} }; V v = V(); // ok struct W { int n; - S s = { n }; // expected-warning {{C++11}} + S s = { n }; // expected-warning 0-1{{C++11}} }; W w = W(); // ok // Ensure we're not faking this up by making the default constructor // non-trivial. -#define static_assert(B, S) typedef int assert_failed[(B) ? 1 : -1]; -static_assert(__has_trivial_constructor(S), ""); -static_assert(__has_trivial_constructor(T), ""); -static_assert(__has_trivial_constructor(U), ""); -static_assert(!__has_trivial_constructor(V), ""); -static_assert(!__has_trivial_constructor(W), ""); +_Static_assert(__has_trivial_constructor(S), ""); +_Static_assert(__has_trivial_constructor(T), ""); +_Static_assert(__has_trivial_constructor(U), ""); +_Static_assert(!__has_trivial_constructor(V), ""); +_Static_assert(!__has_trivial_constructor(W), ""); diff --git a/test/CXX/dcl.decl/dcl.init/p7.cpp b/test/CXX/dcl.decl/dcl.init/p7.cpp index 03216f4c28ac5..1c1d793e8a5e6 100644 --- a/test/CXX/dcl.decl/dcl.init/p7.cpp +++ b/test/CXX/dcl.decl/dcl.init/p7.cpp @@ -12,3 +12,5 @@ struct B : NotAggregateBase { explicit B() = default; // expected-note {{here}} }; B b = {}; // expected-error {{chosen constructor is explicit}} +B b2{}; +B b3; diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp index cec747e1d6054..d93cc8b90874d 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6-0x.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++1z -fsyntax-only -verify %s void f0() &; // expected-error {{non-member function cannot have '&' qualifier}} void f1() &&; // expected-error {{non-member function cannot have '&&' qualifier}} @@ -58,3 +59,16 @@ template<typename T> struct pass { }; pass<func_type_lvalue> pass0; pass<func_type_lvalue> pass1; + +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; }; +constexpr bool cxx1z = __cplusplus > 201402L; + +void noexcept_true() noexcept(true); +void noexcept_false() noexcept(false); +using func_type_noexcept_true = wrap<decltype(noexcept_true)>; +using func_type_noexcept_false = wrap<decltype(noexcept_false)>; +static_assert(is_same<func_type_noexcept_false, func_type_noexcept_true>::value == !cxx1z, ""); +static_assert(is_same<func_type_noexcept_false::val, func_type_noexcept_true::val>::value == !cxx1z, ""); +static_assert(is_same<func_type_noexcept_false::ptr, func_type_noexcept_true::ptr>::value == !cxx1z, ""); +static_assert(is_same<func_type_noexcept_false::ref, func_type_noexcept_true::ref>::value == !cxx1z, ""); diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp index 3bb6701b32e1a..c988b6aba57e5 100644 --- a/test/CXX/drs/dr0xx.cpp +++ b/test/CXX/drs/dr0xx.cpp @@ -248,7 +248,7 @@ namespace dr20 { // dr20: yes private: X(const X&); // expected-note {{here}} }; - X f(); + X &f(); X x = f(); // expected-error {{private}} } @@ -276,20 +276,39 @@ namespace dr23 { // dr23: yes namespace dr25 { // dr25: yes struct A { - void f() throw(int); + void f() throw(int); // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}} }; - void (A::*f)() throw (int); - void (A::*g)() throw () = f; // expected-error {{is not superset of source}} + void (A::*f)() throw (int); // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}} + void (A::*g)() throw () = f; +#if __cplusplus <= 201402L + // expected-error@-2 {{is not superset of source}} +#else + // expected-error@-4 {{different exception specifications}} +#endif void (A::*g2)() throw () = 0; - void (A::*h)() throw (int, char) = f; - void (A::*i)() throw () = &A::f; // expected-error {{is not superset of source}} + void (A::*h)() throw (int, char) = f; // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}} + void (A::*i)() throw () = &A::f; +#if __cplusplus <= 201402L + // expected-error@-2 {{is not superset of source}} +#else + // expected-error@-4 {{different exception specifications}} +#endif void (A::*i2)() throw () = 0; - void (A::*j)() throw (int, char) = &A::f; + void (A::*j)() throw (int, char) = &A::f; // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}} void x() { - // FIXME: Don't produce the second error here. - g2 = f; // expected-error {{is not superset}} expected-error {{incompatible}} + g2 = f; +#if __cplusplus <= 201402L + // expected-error@-2 {{is not superset of source}} +#else + // expected-error@-4 {{different exception specifications}} +#endif h = f; - i2 = &A::f; // expected-error {{is not superset}} expected-error {{incompatible}} + i2 = &A::f; +#if __cplusplus <= 201402L + // expected-error@-2 {{is not superset of source}} +#else + // expected-error@-4 {{different exception specifications}} +#endif j = &A::f; } } @@ -297,8 +316,15 @@ namespace dr25 { // dr25: yes namespace dr26 { // dr26: yes struct A { A(A, const A & = A()); }; // expected-error {{must pass its first argument by reference}} struct B { - B(); // expected-note {{candidate}} - B(const B &, B = B()); // expected-error {{no matching constructor}} expected-note {{candidate}} expected-note {{here}} + B(); // expected-note 0-1{{candidate}} + B(const B &, B = B()); +#if __cplusplus <= 201402L + // expected-error@-2 {{no matching constructor}} expected-note@-2 {{candidate}} expected-note@-2 {{here}} +#endif + }; + struct C { + static C &f(); + C(const C &, C = f()); // expected-error {{no matching constructor}} expected-note {{candidate}} expected-note {{here}} }; } @@ -307,7 +333,7 @@ namespace dr27 { // dr27: yes E &m = true ? n : n; } -// dr28: na +// dr28: na lib namespace dr29 { // dr29: 3.4 void dr29_f0(); // expected-note {{here}} @@ -643,25 +669,33 @@ namespace dr58 { // dr58: yes namespace dr59 { // dr59: yes template<typename T> struct convert_to { operator T() const; }; - struct A {}; // expected-note 2{{volatile qualifier}} - struct B : A {}; // expected-note 2{{volatile qualifier}} -#if __cplusplus >= 201103L // move constructors - // expected-note@-3 2{{volatile qualifier}} - // expected-note@-3 2{{volatile qualifier}} -#endif + struct A {}; // expected-note 5+{{candidate}} + struct B : A {}; // expected-note 0+{{candidate}} A a1 = convert_to<A>(); A a2 = convert_to<A&>(); A a3 = convert_to<const A>(); - A a4 = convert_to<const volatile A>(); // expected-error {{no viable}} + A a4 = convert_to<const volatile A>(); +#if __cplusplus <= 201402L + // expected-error@-2 {{no viable}} +#endif A a5 = convert_to<const volatile A&>(); // expected-error {{no viable}} B b1 = convert_to<B>(); B b2 = convert_to<B&>(); B b3 = convert_to<const B>(); - B b4 = convert_to<const volatile B>(); // expected-error {{no viable}} + B b4 = convert_to<const volatile B>(); +#if __cplusplus <= 201402L + // expected-error@-2 {{no viable}} +#endif B b5 = convert_to<const volatile B&>(); // expected-error {{no viable}} + A c1 = convert_to<B>(); + A c2 = convert_to<B&>(); + A c3 = convert_to<const B>(); + A c4 = convert_to<const volatile B>(); // expected-error {{no viable}} + A c5 = convert_to<const volatile B&>(); // expected-error {{no viable}} + int n1 = convert_to<int>(); int n2 = convert_to<int&>(); int n3 = convert_to<const int>(); @@ -901,14 +935,17 @@ namespace dr84 { // dr84: yes struct A { operator B() const; }; struct C {}; struct B { - B(B&); // expected-note {{candidate}} - B(C); + B(B&); // expected-note 0-1{{candidate}} + B(C); // expected-note 0-1{{no known conversion from 'dr84::B' to 'dr84::C'}} operator C() const; }; A a; // Cannot use B(C) / operator C() pair to construct the B from the B temporary - // here. - B b = a; // expected-error {{no viable}} + // here. In C++1z, we initialize the B object directly using 'A::operator B()'. + B b = a; +#if __cplusplus <= 201402L + // expected-error@-2 {{no viable}} +#endif } namespace dr85 { // dr85: yes @@ -942,10 +979,11 @@ namespace dr85 { // dr85: yes // dr86: dup 446 namespace dr87 { // dr87: no + // FIXME: Superseded by dr1975 template<typename T> struct X {}; // FIXME: This is invalid. X<void() throw()> x; - // ... but this is valid. + // This is valid under dr87 but not under dr1975. X<void(void() throw())> y; } @@ -994,24 +1032,40 @@ namespace dr91 { // dr91: yes int k = f(U()); } -namespace dr92 { // FIXME: Issue is still open. - void f() throw(int, float); - void (*p)() throw(int) = &f; // expected-error {{target exception specification is not superset of source}} - void (*q)() throw(int); - void (**pp)() throw() = &q; // expected-error {{exception specifications are not allowed}} +namespace dr92 { // dr92: 4.0 c++17 + void f() throw(int, float); // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}} + void (*p)() throw(int) = &f; // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}} +#if __cplusplus <= 201402L + // expected-error@-2 {{target exception specification is not superset of source}} +#else + // expected-warning@-4 {{target exception specification is not superset of source}} +#endif + void (*q)() throw(int); // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}} + void (**pp)() throw() = &q; +#if __cplusplus <= 201402L + // expected-error@-2 {{exception specifications are not allowed}} +#else + // expected-error@-4 {{cannot initialize}} +#endif - void g(void() throw()); - void h() { - g(f); // expected-error {{is not superset}} - g(q); // expected-error {{is not superset}} + void g(void() throw()); // expected-note 0-2 {{no known conversion}} expected-warning 0-1{{mangled name of 'g' will change in C++17}} + void h() throw() { + g(f); // expected-error-re {{{{is not superset|no matching function}}}} + g(q); // expected-error-re {{{{is not superset|no matching function}}}} } // Prior to C++17, this is OK because the exception specification is not // considered in this context. In C++17, we *do* perform an implicit - // conversion (which performs initialization), but we convert to the type of - // the template parameter, which does not include the exception specification. + // conversion (which performs initialization), and the exception specification + // is part of the type of the parameter, so this is invalid. template<void() throw()> struct X {}; - X<&f> xp; // ok + X<&f> xp; +#if __cplusplus > 201402L + // expected-error@-2 {{not implicitly convertible}} +#endif + + template<void() throw(int)> struct Y {}; // expected-error 0-1{{ISO C++1z does not allow}} expected-note 0-1{{use 'noexcept}} + Y<&h> yp; // ok } // dr93: na diff --git a/test/CXX/drs/dr10xx.cpp b/test/CXX/drs/dr10xx.cpp index a1d7ef67c66d9..e11e796165e22 100644 --- a/test/CXX/drs/dr10xx.cpp +++ b/test/CXX/drs/dr10xx.cpp @@ -3,8 +3,6 @@ // 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 -// expected-no-diagnostics - namespace std { __extension__ typedef __SIZE_TYPE__ size_t; @@ -32,6 +30,18 @@ namespace dr1048 { // dr1048: 3.6 #endif } +namespace dr1054 { // dr1054: no + // FIXME: Test is incomplete. + struct A {} volatile a; + void f() { + // FIXME: This is wrong: an lvalue-to-rvalue conversion is applied here, + // which copy-initializes a temporary from 'a'. Therefore this is + // ill-formed because A does not have a volatile copy constructor. + // (We might want to track this aspect under dr1383 instead?) + a; // expected-warning {{assign into a variable to force a volatile load}} + } +} + namespace dr1070 { // dr1070: 3.5 #if __cplusplus >= 201103L struct A { diff --git a/test/CXX/drs/dr118.cpp b/test/CXX/drs/dr118.cpp new file mode 100644 index 0000000000000..58aa3912c8010 --- /dev/null +++ b/test/CXX/drs/dr118.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple x86_64-linux -std=c++98 %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call " +// RUN: %clang_cc1 -triple x86_64-linux -std=c++11 %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call " +// RUN: %clang_cc1 -triple x86_64-linux -std=c++14 %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call " +// RUN: %clang_cc1 -triple x86_64-linux -std=c++1z %s -pedantic-errors -emit-llvm -o - | FileCheck %s --implicit-check-not " call " + +// dr118: yes + +struct S { + virtual void f(); +}; +void (S::*pmf)(); + +// CHECK-LABEL: define {{.*}} @_Z1g +void g(S *sp) { + // CHECK: call void % + sp->f(); // 1: polymorphic + // CHECK: call void @ + sp->S::f(); // 2: non-polymorphic + // CHECK: call void @ + (sp->S::f)(); // 3: non-polymorphic + // CHECK: call void % + (sp->*pmf)(); // 4: polymorphic + // CHECK: call void % + (sp->*&S::f)(); // 5: polymorphic +} + diff --git a/test/CXX/drs/dr12xx.cpp b/test/CXX/drs/dr12xx.cpp index 048c21acde568..72d8d683ab7a7 100644 --- a/test/CXX/drs/dr12xx.cpp +++ b/test/CXX/drs/dr12xx.cpp @@ -3,7 +3,16 @@ // 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 -// expected-no-diagnostics +namespace dr1213 { // dr1213: 4.0 +#if __cplusplus >= 201103L + using T = int[3]; + int &&r = T{}[1]; + + using T = decltype((T{})); + using U = decltype((T{}[2])); + using U = int &&; +#endif +} namespace dr1250 { // dr1250: 3.9 struct Incomplete; @@ -16,3 +25,29 @@ struct Derived : Base { virtual Incomplete *meow(); }; } // dr1250 + +namespace dr1295 { // dr1295: 4.0 + struct X { + unsigned bitfield : 4; + }; + + X x = {1}; + + unsigned const &r1 = static_cast<X &&>(x).bitfield; // expected-error 0-1{{C++11}} + unsigned const &r2 = static_cast<unsigned &&>(x.bitfield); // expected-error 0-1{{C++11}} + + template<unsigned &r> struct Y {}; + Y<x.bitfield> y; +#if __cplusplus <= 201402L + // expected-error@-2 {{does not refer to any declaration}} expected-note@-3 {{here}} +#else + // expected-error@-4 {{refers to subobject}} +#endif + +#if __cplusplus >= 201103L + const unsigned other = 0; + using T = decltype(true ? other : x.bitfield); + using T = unsigned; +#endif +} + diff --git a/test/CXX/drs/dr13xx.cpp b/test/CXX/drs/dr13xx.cpp index 8c3e7f2a04ca1..28bebcbb607e6 100644 --- a/test/CXX/drs/dr13xx.cpp +++ b/test/CXX/drs/dr13xx.cpp @@ -3,6 +3,136 @@ // 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 +namespace dr1315 { // dr1315: partial + template <int I, int J> struct A {}; + template <int I> // expected-note {{non-deducible template parameter 'I'}} + struct A<I + 5, I * 2> {}; // expected-error {{contains a template parameter that cannot be deduced}} + template <int I> struct A<I, I> {}; + + template <int I, int J, int K> struct B; + template <int I, int K> struct B<I, I * 2, K> {}; // expected-note {{matches}} + B<1, 2, 3> b1; + + // Multiple declarations with the same dependent expression are equivalent + // for partial ordering purposes. + template <int I> struct B<I, I * 2, 2> { typedef int type; }; + B<1, 2, 2>::type b2; + + // Multiple declarations with differing dependent expressions are unordered. + template <int I, int K> struct B<I, I + 1, K> {}; // expected-note {{matches}} + B<1, 2, 4> b3; // expected-error {{ambiguous}} + + // FIXME: Under dr1315, this is perhaps valid, but that is not clear: this + // fails the "more specialized than the primary template" test because the + // dependent type of T::value is not the same as 'int'. + // A core issue will be opened to decide what is supposed to happen here. + template <typename T, int I> struct C; + template <typename T> struct C<T, T::value>; + // expected-error@-1 {{type of specialized non-type template argument depends on a template parameter of the partial specialization}} +} + +namespace dr1330 { // dr1330: 4.0 c++11 + // exception-specifications are parsed in a context where the class is complete. + struct A { + void f() throw(T) {} // expected-error 0-1{{C++1z}} expected-note 0-1{{noexcept}} + struct T {}; + +#if __cplusplus >= 201103L + void g() noexcept(&a == b) {} + static int a; + static constexpr int *b = &a; +#endif + }; + + void (A::*af1)() throw(A::T) = &A::f; // expected-error 0-1{{C++1z}} expected-note 0-1{{noexcept}} + void (A::*af2)() throw() = &A::f; // expected-error-re {{{{not superset|different exception spec}}}} + +#if __cplusplus >= 201103L + static_assert(noexcept(A().g()), ""); +#endif + + // Likewise, they're instantiated separately from an enclosing class template. + template<typename U> + struct B { + void f() throw(T, typename U::type) {} // expected-error 0-1{{C++1z}} expected-note 0-1{{noexcept}} + struct T {}; + +#if __cplusplus >= 201103L + void g() noexcept(&a == b && U::value) {} + static int a; + static constexpr int *b = &a; +#endif + }; + + B<int> bi; // ok + + struct P { + typedef int type; + static const int value = true; + }; + + void (B<P>::*bpf1)() throw(B<P>::T, int) = &B<P>::f; // expected-error 0-1{{C++1z}} expected-note 0-1{{noexcept}} +#if __cplusplus < 201103L + // expected-error@-2 {{not superset}} + // FIXME: We only delay instantiation in C++11 onwards. In C++98, something + // weird happens: instantiation of B<P> fails because it references T before + // it's instantiated, but the diagnostic is suppressed in + // Sema::FindInstantiatedDecl because we've already hit an error. This is + // obviously a bad way to react to this situation; we should still producing + // the "T has not yet been instantiated" error here, rather than giving + // confusing errors later on. +#endif + void (B<P>::*bpf2)() throw(int) = &B<P>::f; // expected-error 0-1{{C++1z}} expected-note 0-1{{noexcept}} +#if __cplusplus <= 201402L + // expected-error@-2 {{not superset}} +#else + // expected-warning@-4 {{not superset}} +#endif + void (B<P>::*bpf3)() = &B<P>::f; + void (B<P>::*bpf4)() throw() = &B<P>::f; +#if __cplusplus <= 201402L + // expected-error@-2 {{not superset}} +#else + // expected-error@-4 {{different exception specifications}} +#endif + +#if __cplusplus >= 201103L + static_assert(noexcept(B<P>().g()), ""); + struct Q { static const int value = false; }; + static_assert(!noexcept(B<Q>().g()), ""); +#endif + + template<typename T> int f() throw(typename T::error) { return 0; } // expected-error 1-4{{prior to '::'}} expected-note 0-1{{instantiation of}} +#if __cplusplus > 201402L + // expected-error@-2 0-1{{C++1z}} expected-note@-2 0-1{{noexcept}} +#endif + // An exception-specification is needed even if the function is only used in + // an unevaluated operand. + int f1 = sizeof(f<int>()); // expected-note {{instantiation of}} +#if __cplusplus >= 201103L + decltype(f<char>()) f2; // expected-note {{instantiation of}} + bool f3 = noexcept(f<float>()); // expected-note {{instantiation of}} +#endif + template int f<short>(); // expected-note {{instantiation of}} + + template<typename T> struct C { + C() throw(typename T::type); // expected-error 1-2{{prior to '::'}} +#if __cplusplus > 201402L + // expected-error@-2 0-1{{C++1z}} expected-note@-2 0-1{{noexcept}} +#endif + }; + struct D : C<void> {}; // ok +#if __cplusplus < 201103L + // expected-note@-2 {{instantiation of}} +#endif + void f(D &d) { d = d; } // ok + + // FIXME: In C++11 onwards, we should also note the declaration of 'e' as the + // line that triggers the use of E::E()'s exception specification. + struct E : C<int> {}; // expected-note {{in instantiation of}} + E e; +} + namespace dr1346 { // dr1346: 3.5 auto a(1); // expected-error 0-1{{extension}} auto b(1, 2); // expected-error {{multiple expressions}} expected-error 0-1{{extension}} diff --git a/test/CXX/drs/dr14xx.cpp b/test/CXX/drs/dr14xx.cpp index 9491f7da14760..9e724d9183460 100644 --- a/test/CXX/drs/dr14xx.cpp +++ b/test/CXX/drs/dr14xx.cpp @@ -342,4 +342,32 @@ namespace dr1490 { // dr1490: 3.7 c++11 char s[4]{"abc"}; // Ok std::initializer_list<char>{"abc"}; // expected-error {{expected unqualified-id}}} } // dr190 + +namespace dr1495 { // dr1495: 4.0 + // Deduction succeeds in both directions. + template<typename T, typename U> struct A {}; // expected-note {{template is declared here}} + template<typename T, typename U> struct A<U, T> {}; // expected-error {{class template partial specialization is not more specialized}} + + // Primary template is more specialized. + template<typename, typename...> struct B {}; // expected-note {{template is declared here}} + template<typename ...Ts> struct B<Ts...> {}; // expected-error {{not more specialized}} + + // Deduction fails in both directions. + template<int, typename, typename ...> struct C {}; // expected-note {{template is declared here}} + template<typename ...Ts> struct C<0, Ts...> {}; // expected-error {{not more specialized}} + +#if __cplusplus >= 201402L + // Deduction succeeds in both directions. + template<typename T, typename U> int a; // expected-note {{template is declared here}} + template<typename T, typename U> int a<U, T>; // expected-error {{variable template partial specialization is not more specialized}} + + // Primary template is more specialized. + template<typename, typename...> int b; // expected-note {{template is declared here}} + template<typename ...Ts> int b<Ts...>; // expected-error {{not more specialized}} + + // Deduction fails in both directions. + template<int, typename, typename ...> int c; // expected-note {{template is declared here}} + template<typename ...Ts> int c<0, Ts...>; // expected-error {{not more specialized}} +#endif +} #endif diff --git a/test/CXX/drs/dr158.cpp b/test/CXX/drs/dr158.cpp new file mode 100644 index 0000000000000..33f837ca06270 --- /dev/null +++ b/test/CXX/drs/dr158.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-linux -std=c++98 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux -std=c++11 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux -std=c++14 %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux -std=c++1z %s -O3 -disable-llvm-passes -pedantic-errors -emit-llvm -o - | FileCheck %s + +// dr158: yes + +// CHECK-LABEL: define {{.*}} @_Z1f +const int *f(const int * const *p, int **q) { + // CHECK: load i32**, {{.*}}, !tbaa ![[INTPTR_TBAA:[^,]*]] + const int *x = *p; + // CHECK: store i32* null, {{.*}}, !tbaa ![[INTPTR_TBAA]] + *q = 0; + return x; +} + +struct A {}; + +// CHECK-LABEL: define {{.*}} @_Z1g +const int *(A::*const *g(const int *(A::* const **p)[3], int *(A::***q)[3]))[3] { + // CHECK: load i64**, {{.*}}, !tbaa ![[MEMPTR_TBAA:[^,]*]] + const int *(A::*const *x)[3] = *p; + // CHECK: store i64* null, {{.*}}, !tbaa ![[MEMPTR_TBAA]] + *q = 0; + return x; +} + diff --git a/test/CXX/drs/dr15xx.cpp b/test/CXX/drs/dr15xx.cpp index 5f85a196fd6af..fb0d9334f6b6f 100644 --- a/test/CXX/drs/dr15xx.cpp +++ b/test/CXX/drs/dr15xx.cpp @@ -3,9 +3,223 @@ // 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 -#if __cplusplus < 201103L -// expected-no-diagnostics +namespace dr1512 { // dr1512: 4.0 + void f(char *p) { + if (p > 0) {} // expected-error {{ordered comparison between pointer and zero}} +#if __cplusplus >= 201103L + if (p > nullptr) {} // expected-error {{invalid operands}} #endif + } + bool g(int **x, const int **y) { + return x < y; + } + + template<typename T> T val(); + + template<typename A, typename B, typename C> void composite_pointer_type_is_base() { + typedef __typeof(true ? val<A>() : val<B>()) type; + typedef C type; + + typedef __typeof(val<A>() == val<B>()) cmp; + typedef __typeof(val<A>() != val<B>()) cmp; + typedef bool cmp; + } + + template<typename A, typename B, typename C> void composite_pointer_type_is_ord() { + composite_pointer_type_is_base<A, B, C>(); + + typedef __typeof(val<A>() < val<B>()) cmp; + typedef __typeof(val<A>() <= val<B>()) cmp; + typedef __typeof(val<A>() > val<B>()) cmp; + typedef __typeof(val<A>() >= val<B>()) cmp; + typedef bool cmp; + } + + template <typename A, typename B, typename C> + void composite_pointer_type_is_unord(int = 0) { + composite_pointer_type_is_base<A, B, C>(); + } + template <typename A, typename B, typename C> + void composite_pointer_type_is_unord(__typeof(val<A>() < val<B>()) * = 0); + template <typename A, typename B, typename C> + void composite_pointer_type_is_unord(__typeof(val<A>() <= val<B>()) * = 0); + template <typename A, typename B, typename C> + void composite_pointer_type_is_unord(__typeof(val<A>() > val<B>()) * = 0); + template <typename A, typename B, typename C> + void composite_pointer_type_is_unord(__typeof(val<A>() >= val<B>()) * = 0); + + // A call to this is ambiguous if a composite pointer type exists. + template<typename A, typename B> + void no_composite_pointer_type(__typeof((true ? val<A>() : val<B>()), void()) * = 0); + template<typename A, typename B> void no_composite_pointer_type(int = 0); + + struct A {}; + struct B : A {}; + struct C {}; + + void test() { +#if __cplusplus >= 201103L + using nullptr_t = decltype(nullptr); + composite_pointer_type_is_unord<nullptr_t, nullptr_t, nullptr_t>(); + no_composite_pointer_type<nullptr_t, int>(); + + composite_pointer_type_is_unord<nullptr_t, const char**, const char**>(); + composite_pointer_type_is_unord<const char**, nullptr_t, const char**>(); +#endif + + composite_pointer_type_is_ord<const int *, volatile void *, const volatile void*>(); + composite_pointer_type_is_ord<const void *, volatile int *, const volatile void*>(); + + composite_pointer_type_is_ord<const A*, volatile B*, const volatile A*>(); + composite_pointer_type_is_ord<const B*, volatile A*, const volatile A*>(); + + composite_pointer_type_is_unord<const int *A::*, volatile int *B::*, const volatile int *const B::*>(); + composite_pointer_type_is_unord<const int *B::*, volatile int *A::*, const volatile int *const B::*>(); + no_composite_pointer_type<int (A::*)(), int (C::*)()>(); + no_composite_pointer_type<const int (A::*)(), volatile int (C::*)()>(); + +#if __cplusplus > 201402 + composite_pointer_type_is_ord<int (*)() noexcept, int (*)(), int (*)()>(); + composite_pointer_type_is_ord<int (*)(), int (*)() noexcept, int (*)()>(); + composite_pointer_type_is_unord<int (A::*)() noexcept, int (A::*)(), int (A::*)()>(); + composite_pointer_type_is_unord<int (A::*)(), int (A::*)() noexcept, int (A::*)()>(); + // FIXME: This looks like a standard defect; these should probably all have type 'int (B::*)()'. + composite_pointer_type_is_unord<int (B::*)(), int (A::*)() noexcept, int (B::*)()>(); + composite_pointer_type_is_unord<int (A::*)() noexcept, int (B::*)(), int (B::*)()>(); + composite_pointer_type_is_unord<int (B::*)() noexcept, int (A::*)(), int (B::*)()>(); + composite_pointer_type_is_unord<int (A::*)(), int (B::*)() noexcept, int (B::*)()>(); + + // FIXME: It would be reasonable to permit these, with a common type of 'int (*const *)()'. + no_composite_pointer_type<int (**)() noexcept, int (**)()>(); + no_composite_pointer_type<int (**)(), int (**)() noexcept>(); + + // FIXME: It would be reasonable to permit these, with a common type of 'int (A::*)()'. + no_composite_pointer_type<int (A::*)() const, int (A::*)()>(); + no_composite_pointer_type<int (A::*)(), int (A::*)() const>(); + + // FIXME: It would be reasonable to permit these, with a common type of + // 'int (A::*)() &' and 'int (A::*)() &&', respectively. + no_composite_pointer_type<int (A::*)() &, int (A::*)()>(); + no_composite_pointer_type<int (A::*)(), int (A::*)() &>(); + no_composite_pointer_type<int (A::*)() &&, int (A::*)()>(); + no_composite_pointer_type<int (A::*)(), int (A::*)() &&>(); + + no_composite_pointer_type<int (A::*)() &&, int (A::*)() &>(); + no_composite_pointer_type<int (A::*)() &, int (A::*)() &&>(); + + no_composite_pointer_type<int (C::*)(), int (A::*)() noexcept>(); + no_composite_pointer_type<int (A::*)() noexcept, int (C::*)()>(); +#endif + } + + template<typename T> struct Wrap { operator T(); }; + void test_overload() { +#if __cplusplus >= 201103L + using nullptr_t = decltype(nullptr); + void(Wrap<nullptr_t>() == Wrap<nullptr_t>()); + void(Wrap<nullptr_t>() != Wrap<nullptr_t>()); + void(Wrap<nullptr_t>() < Wrap<nullptr_t>()); // expected-error {{invalid operands}} + void(Wrap<nullptr_t>() > Wrap<nullptr_t>()); // expected-error {{invalid operands}} + void(Wrap<nullptr_t>() <= Wrap<nullptr_t>()); // expected-error {{invalid operands}} + void(Wrap<nullptr_t>() >= Wrap<nullptr_t>()); // expected-error {{invalid operands}} + + // The wording change fails to actually disallow this. This is valid + // via the builtin operator<(int*, int*) etc. + void(Wrap<nullptr_t>() == Wrap<int*>()); + void(Wrap<nullptr_t>() != Wrap<int*>()); + void(Wrap<nullptr_t>() < Wrap<int*>()); + void(Wrap<nullptr_t>() > Wrap<int*>()); + void(Wrap<nullptr_t>() <= Wrap<int*>()); + void(Wrap<nullptr_t>() >= Wrap<int*>()); +#endif + } +} + +namespace dr1518 { // dr1518: 4.0 +#if __cplusplus >= 201103L +struct Z0 { // expected-note 0+ {{candidate}} + explicit Z0() = default; // expected-note 0+ {{here}} +}; +struct Z { // expected-note 0+ {{candidate}} + explicit Z(); // expected-note 0+ {{here}} + explicit Z(int); + explicit Z(int, int); // expected-note 0+ {{here}} +}; +template <class T> int Eat(T); // expected-note 0+ {{candidate}} +Z0 a; +Z0 b{}; +Z0 c = {}; // expected-error {{explicit in copy-initialization}} +int i = Eat<Z0>({}); // expected-error {{no matching function for call to 'Eat'}} + +Z c2 = {}; // expected-error {{explicit in copy-initialization}} +int i2 = Eat<Z>({}); // expected-error {{no matching function for call to 'Eat'}} +Z a1 = 1; // expected-error {{no viable conversion}} +Z a3 = Z(1); +Z a2(1); +Z *p = new Z(1); +Z a4 = (Z)1; +Z a5 = static_cast<Z>(1); +Z a6 = {4, 3}; // expected-error {{explicit in copy-initialization}} + +struct UserProvidedBaseCtor { // expected-note 0+ {{candidate}} + UserProvidedBaseCtor() {} +}; +struct DoesntInheritCtor : UserProvidedBaseCtor { // expected-note 0+ {{candidate}} + int x; +}; +DoesntInheritCtor I{{}, 42}; +#if __cplusplus <= 201402L +// expected-error@-2 {{no matching constructor}} +#endif + +struct BaseCtor { BaseCtor() = default; }; // expected-note 0+ {{candidate}} +struct InheritsCtor : BaseCtor { // expected-note 1+ {{candidate}} + using BaseCtor::BaseCtor; // expected-note 2 {{inherited here}} + int x; +}; +InheritsCtor II = {{}, 42}; // expected-error {{no matching constructor}} + +namespace std_example { + struct A { + explicit A() = default; // expected-note 2{{declared here}} + }; + + struct B : A { + explicit B() = default; // expected-note 2{{declared here}} + }; + + struct C { + explicit C(); // expected-note 2{{declared here}} + }; + + struct D : A { + C c; + explicit D() = default; // expected-note 2{{declared here}} + }; + + template <typename T> void f() { + T t; // ok + T u{}; // ok + T v = {}; // expected-error 4{{explicit}} + } + template <typename T> void g() { + void x(T t); // expected-note 4{{parameter}} + x({}); // expected-error 4{{explicit}} + } + + void test() { + f<A>(); // expected-note {{instantiation of}} + f<B>(); // expected-note {{instantiation of}} + f<C>(); // expected-note {{instantiation of}} + f<D>(); // expected-note {{instantiation of}} + g<A>(); // expected-note {{instantiation of}} + g<B>(); // expected-note {{instantiation of}} + g<C>(); // expected-note {{instantiation of}} + g<D>(); // expected-note {{instantiation of}} + } +} +#endif // __cplusplus >= 201103L +} namespace dr1550 { // dr1550: yes int f(bool b, int n) { diff --git a/test/CXX/drs/dr16xx.cpp b/test/CXX/drs/dr16xx.cpp index 65467e35e4d68..02aa5f9909eb3 100644 --- a/test/CXX/drs/dr16xx.cpp +++ b/test/CXX/drs/dr16xx.cpp @@ -3,10 +3,6 @@ // 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 -#if __cplusplus < 201103L -// expected-no-diagnostics -#endif - namespace dr1684 { // dr1684: 3.6 #if __cplusplus >= 201103L struct NonLiteral { // expected-note {{because}} @@ -44,6 +40,35 @@ namespace dr1631 { // dr1631: 3.7 #endif } +namespace dr1638 { // dr1638: yes +#if __cplusplus >= 201103L + template<typename T> struct A { + enum class E; // expected-note {{previous}} + enum class F : T; // expected-note 2{{previous}} + }; + + template<> enum class A<int>::E; + template<> enum class A<int>::E {}; + template<> enum class A<int>::F : int; + template<> enum class A<int>::F : int {}; + + template<> enum class A<short>::E : int; + template<> enum class A<short>::E : int {}; + + template<> enum class A<short>::F; // expected-error {{different underlying type}} + template<> enum class A<char>::E : char; // expected-error {{different underlying type}} + template<> enum class A<char>::F : int; // expected-error {{different underlying type}} + + enum class A<unsigned>::E; // expected-error {{template specialization requires 'template<>'}} expected-error {{nested name specifier}} + template enum class A<unsigned>::E; // expected-error {{enumerations cannot be explicitly instantiated}} + enum class A<unsigned>::E *e; // expected-error {{must use 'enum' not 'enum class'}} + + struct B { + friend enum class A<unsigned>::E; // expected-error {{must use 'enum' not 'enum class'}} + }; +#endif +} + namespace dr1645 { // dr1645: 3.9 #if __cplusplus >= 201103L struct A { // expected-note 2{{candidate}} @@ -60,3 +85,19 @@ namespace dr1645 { // dr1645: 3.9 constexpr B b(0, 0); // expected-error {{ambiguous}} #endif } + +namespace dr1653 { // dr1653: 4.0 c++17 + void f(bool b) { + ++b; + b++; +#if __cplusplus <= 201402L + // expected-warning@-3 {{deprecated}} expected-warning@-2 {{deprecated}} +#else + // expected-error@-5 {{incrementing expression of type bool}} expected-error@-4 {{incrementing expression of type bool}} +#endif + --b; // expected-error {{cannot decrement expression of type bool}} + b--; // expected-error {{cannot decrement expression of type bool}} + b += 1; // ok + b -= 1; // ok + } +} diff --git a/test/CXX/drs/dr18xx.cpp b/test/CXX/drs/dr18xx.cpp index bc72b67d1e0b7..436bccc8e42e3 100644 --- a/test/CXX/drs/dr18xx.cpp +++ b/test/CXX/drs/dr18xx.cpp @@ -7,11 +7,11 @@ // expected-no-diagnostics #endif -void dr1891() { // dr1891: 3.6 +void dr1891() { // dr1891: 4.0 #if __cplusplus >= 201103L int n; - auto a = []{}; // expected-note 2{{candidate}} - auto b = [=]{ return n; }; // expected-note 2{{candidate}} + auto a = []{}; // expected-note 2{{candidate}} expected-note 2{{here}} + auto b = [=]{ return n; }; // expected-note 2{{candidate}} expected-note 2{{here}} typedef decltype(a) A; typedef decltype(b) B; @@ -20,5 +20,10 @@ void dr1891() { // dr1891: 3.6 A x; // expected-error {{no matching constructor}} B y; // expected-error {{no matching constructor}} + + a = a; // expected-error {{copy assignment operator is implicitly deleted}} + a = static_cast<A&&>(a); // expected-error {{copy assignment operator is implicitly deleted}} + b = b; // expected-error {{copy assignment operator is implicitly deleted}} + b = static_cast<B&&>(b); // expected-error {{copy assignment operator is implicitly deleted}} #endif } diff --git a/test/CXX/drs/dr1xx.cpp b/test/CXX/drs/dr1xx.cpp index 8d368a5a54e85..9521f0a8b7841 100644 --- a/test/CXX/drs/dr1xx.cpp +++ b/test/CXX/drs/dr1xx.cpp @@ -35,7 +35,7 @@ namespace dr102 { // dr102: yes } // dr103: na -// dr104 FIXME: add codegen test +// dr104: na lib // dr105: na namespace dr106 { // dr106: sup 540 @@ -202,7 +202,7 @@ namespace dr116 { // dr116: yes } // dr117: na -// dr118 FIXME: add codegen test +// dr118 is in its own file. // dr119: na // dr120: na @@ -235,13 +235,11 @@ namespace dr125 { friend dr125_A (::dr125_B::dr125_C)(); // ok friend dr125_A::dr125_B::dr125_C(); // expected-error {{did you mean the constructor name 'dr125_B'?}} // expected-error@-1 {{missing exception specification}} -#if __cplusplus >= 201103L - // expected-error@-3 {{follows constexpr declaration}} expected-note@-10 {{here}} -#endif }; } namespace dr126 { // dr126: no +#if __cplusplus <= 201402L struct C {}; struct D : C {}; struct E : private C { friend class A; friend class B; }; @@ -314,12 +312,15 @@ namespace dr126 { // dr126: no virtual void y() throw(int*); // ok virtual void z() throw(long); // expected-error {{more lax}} }; +#else + void f() throw(int); // expected-error {{ISO C++1z does not allow}} expected-note {{use 'noexcept}} +#endif } namespace dr127 { // dr127: yes __extension__ typedef __decltype(sizeof(0)) size_t; template<typename T> struct A { - A() throw(int); + A() { throw 0; } void *operator new(size_t, const char * = 0); void operator delete(void *, const char *) { T::error; } // expected-error 2{{no members}} void operator delete(void *) { T::error; } @@ -579,11 +580,18 @@ namespace dr151 { // dr151: yes namespace dr152 { // dr152: yes struct A { - A(); // expected-note {{not viable}} + A(); // expected-note 0-2{{not viable}} explicit A(const A&); }; - A a1 = A(); // expected-error {{no matching constructor}} + A a1 = A(); +#if __cplusplus <= 201402L + // expected-error@-2 {{no matching constructor}} +#endif A a2((A())); + + A &f(); + A a3 = f(); // expected-error {{no matching constructor}} + A a4(f()); } // dr153: na @@ -600,7 +608,7 @@ namespace dr155 { // dr155: dup 632 struct S { int n; } s = { { 1 } }; // expected-warning {{braces around scalar initializer}} } -// dr158 FIXME write codegen test +// dr158 is in its own file. namespace dr159 { // dr159: 3.5 namespace X { void f(); } @@ -826,11 +834,20 @@ namespace dr176 { // dr176: yes namespace dr177 { // dr177: yes struct B {}; struct A { - A(A &); // expected-note {{not viable: expects an l-value}} - A(const B &); + A(A &); // expected-note 0-1{{not viable: expects an l-value}} + A(const B &); // expected-note 0-1{{not viable: no known conversion from 'dr177::A' to}} }; B b; - A a = b; // expected-error {{no viable constructor copying variable}} + A a = b; +#if __cplusplus <= 201402L + // expected-error@-2 {{no viable constructor copying variable}} +#endif + + struct C { C(C&); }; // expected-note {{not viable: no known conversion from 'dr177::D' to 'dr177::C &'}} + struct D : C {}; + struct E { operator D(); }; + E e; + C c = e; // expected-error {{no viable constructor copying variable of type 'dr177::D'}} } namespace dr178 { // dr178: yes diff --git a/test/CXX/drs/dr2xx.cpp b/test/CXX/drs/dr2xx.cpp index 25c853590ae66..a9f0c8fcc9995 100644 --- a/test/CXX/drs/dr2xx.cpp +++ b/test/CXX/drs/dr2xx.cpp @@ -620,7 +620,7 @@ namespace dr254 { // dr254: yes template<typename T> struct A { typedef typename T::type type; // ok even if this is a typedef-name, because // it's not an elaborated-type-specifier - typedef struct T::type foo; // expected-error {{elaborated type refers to a typedef}} + typedef struct T::type foo; // expected-error {{typedef 'type' cannot be referenced with a struct specifier}} }; struct B { struct type {}; }; struct C { typedef struct {} type; }; // expected-note {{here}} @@ -679,17 +679,13 @@ namespace dr258 { // dr258: yes } f; // expected-error {{abstract}} } -namespace dr259 { // dr259: yes c++11 +namespace dr259 { // dr259: 4.0 template<typename T> struct A {}; template struct A<int>; // expected-note {{previous}} template struct A<int>; // expected-error {{duplicate explicit instantiation}} - // FIXME: We only apply this DR in C++11 mode. - template<> struct A<float>; - template struct A<float>; -#if __cplusplus < 201103L - // expected-error@-2 {{extension}} expected-note@-3 {{here}} -#endif + template<> struct A<float>; // expected-note {{previous}} + template struct A<float>; // expected-warning {{has no effect}} template struct A<char>; // expected-note {{here}} template<> struct A<char>; // expected-error {{explicit specialization of 'dr259::A<char>' after instantiation}} @@ -702,11 +698,8 @@ namespace dr259 { // dr259: yes c++11 template<typename T> struct B; // expected-note {{here}} template struct B<int>; // expected-error {{undefined}} - template<> struct B<float>; - template struct B<float>; -#if __cplusplus < 201103L - // expected-error@-2 {{extension}} expected-note@-3 {{here}} -#endif + template<> struct B<float>; // expected-note {{previous}} + template struct B<float>; // expected-warning {{has no effect}} } // FIXME: When dr260 is resolved, also add tests for DR507. @@ -990,12 +983,32 @@ namespace dr289 { // dr289: yes namespace dr294 { // dr294: no void f() throw(int); +#if __cplusplus > 201402L + // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}} +#endif int main() { - (void)static_cast<void (*)() throw()>(f); // FIXME: ill-formed - (void)static_cast<void (*)() throw(int)>(f); // FIXME: ill-formed + (void)static_cast<void (*)() throw()>(f); // FIXME: ill-formed in C++14 and before +#if __cplusplus > 201402L + // FIXME: expected-error@-2 {{not allowed}} + // + // Irony: the above is valid in C++17 and beyond, but that's exactly when + // we reject it. In C++14 and before, this is ill-formed because an + // exception-specification is not permitted in a type-id. In C++17, this is + // valid because it's the inverse of a standard conversion sequence + // containing a function pointer conversion. (Well, it's actually not valid + // yet, as a static_cast is not permitted to reverse a function pointer + // conversion, but that is being changed by core issue). +#endif + (void)static_cast<void (*)() throw(int)>(f); // FIXME: ill-formed in C++14 and before +#if __cplusplus > 201402L + // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}} +#endif - void (*p)() throw() = f; // expected-error {{not superset}} + void (*p)() throw() = f; // expected-error-re {{{{not superset|different exception specification}}}} void (*q)() throw(int) = f; +#if __cplusplus > 201402L + // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}} +#endif } } @@ -1035,8 +1048,8 @@ namespace dr298 { // dr298: yes C::type i3; struct A a; - struct B b; // expected-error {{refers to a typedef}} - struct C c; // expected-error {{refers to a typedef}} + struct B b; // expected-error {{typedef 'B' cannot be referenced with a struct specifier}} + struct C c; // expected-error {{typedef 'C' cannot be referenced with a struct specifier}} B::B() {} // expected-error {{requires a type specifier}} B::A() {} // ok diff --git a/test/CXX/drs/dr4xx.cpp b/test/CXX/drs/dr4xx.cpp index b1c21f8631dd1..6046c4afefd55 100644 --- a/test/CXX/drs/dr4xx.cpp +++ b/test/CXX/drs/dr4xx.cpp @@ -90,7 +90,7 @@ namespace dr407 { // dr407: 3.8 struct S *p; { typedef struct S S; // expected-note {{here}} - struct S *p; // expected-error {{refers to a typedef}} + struct S *p; // expected-error {{typedef 'S' cannot be referenced with a struct specifier}} } } struct S {}; @@ -327,7 +327,7 @@ namespace dr420 { // dr420: yes namespace dr421 { // dr421: yes struct X { X(); int n; int &r; }; - int *p = &X().n; // expected-error {{taking the address of a temporary}} + int *p = &X().n; // expected-error-re {{{{taking the address of a temporary|cannot take the address of an rvalue}}}} int *q = &X().r; } @@ -508,9 +508,18 @@ namespace dr437 { // dr437: sup 1308 template<typename U> struct T : U {}; struct S { void f() throw(S); +#if __cplusplus > 201402L + // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}} +#endif void g() throw(T<S>); +#if __cplusplus > 201402L + // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}} +#endif struct U; void h() throw(U); +#if __cplusplus > 201402L + // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}} +#endif struct U {}; }; } @@ -553,12 +562,21 @@ namespace dr446 { // dr446: yes void(b ? a : a); b ? A() : a; // expected-error {{deleted}} b ? a : A(); // expected-error {{deleted}} - b ? A() : A(); // expected-error {{deleted}} + b ? A() : A(); +#if __cplusplus <= 201402L + // expected-error@-2 {{deleted}} +#endif void(b ? a : c); b ? a : C(); // expected-error {{deleted}} - b ? c : A(); // expected-error {{deleted}} - b ? A() : C(); // expected-error {{deleted}} + b ? c : A(); +#if __cplusplus <= 201402L + // expected-error@-2 {{deleted}} +#endif + b ? A() : C(); +#if __cplusplus <= 201402L + // expected-error@-2 {{deleted}} +#endif } } @@ -874,10 +892,12 @@ namespace dr479 { // dr479: yes void f() { throw S(); // expected-error@-1 {{temporary of type 'dr479::S' has private destructor}} - // expected-error@-2 {{calling a private constructor}} - // expected-error@-3 {{exception object of type 'dr479::S' has private destructor}} + // expected-error@-2 {{exception object of type 'dr479::S' has private destructor}} #if __cplusplus < 201103L - // expected-error@-5 {{C++98 requires an accessible copy constructor}} + // expected-error@-4 {{C++98 requires an accessible copy constructor}} +#endif +#if __cplusplus <= 201402L + // expected-error@-7 {{calling a private constructor}} (copy ctor) #endif } void g() { diff --git a/test/CXX/drs/dr5xx.cpp b/test/CXX/drs/dr5xx.cpp index e0bab57e5254b..f065128cd4bd8 100644 --- a/test/CXX/drs/dr5xx.cpp +++ b/test/CXX/drs/dr5xx.cpp @@ -8,6 +8,12 @@ // with -verify. __extension__ typedef __SIZE_TYPE__ size_t; void *operator new(size_t); // expected-error 0-1{{missing exception spec}} expected-note{{candidate}} +#if __cplusplus > 201402L +namespace std { + enum class align_val_t : size_t {}; +} +void *operator new(size_t, std::align_val_t); // expected-note{{candidate}} +#endif namespace dr500 { // dr500: dup 372 class D; @@ -857,14 +863,13 @@ namespace dr580 { // dr580: partial // dr582: na -namespace dr583 { // dr583: no +namespace dr583 { // dr583: 4.0 // see n3624 int *p; - // FIXME: These are all ill-formed. - bool b1 = p < 0; - bool b2 = p > 0; - bool b3 = p <= 0; - bool b4 = p >= 0; + bool b1 = p < 0; // expected-error {{ordered comparison between pointer and zero}} + bool b2 = p > 0; // expected-error {{ordered comparison between pointer and zero}} + bool b3 = p <= 0; // expected-error {{ordered comparison between pointer and zero}} + bool b4 = p >= 0; // expected-error {{ordered comparison between pointer and zero}} } // dr584: na @@ -948,6 +953,9 @@ namespace dr591 { // dr591: no namespace dr595 { // dr595: dup 1330 template<class T> struct X { void f() throw(T) {} +#if __cplusplus > 201402L + // expected-error@-2 {{ISO C++1z does not allow}} expected-note@-2 {{use 'noexcept}} +#endif }; struct S { X<S> xs; diff --git a/test/CXX/drs/dr6xx.cpp b/test/CXX/drs/dr6xx.cpp index 1d37a6d3e80c8..9dfcc7d6b4646 100644 --- a/test/CXX/drs/dr6xx.cpp +++ b/test/CXX/drs/dr6xx.cpp @@ -142,15 +142,21 @@ namespace dr615 { // dr615: yes static int n = f(); } -namespace dr616 { // dr616: no +namespace dr616 { // dr616: 4.0 #if __cplusplus >= 201103L struct S { int n; } s; - // FIXME: These should all be 'int &&' - using T = decltype(S().n); - using T = decltype(static_cast<S&&>(s).n); - using T = decltype(S().*&S::n); // expected-note 2{{previous}} - using T = decltype(static_cast<S&&>(s).*&S::n); // expected-error {{different type}} - using T = int&&; // expected-error {{different type}} + S f(); + using T = decltype((S().n)); + using T = decltype((static_cast<S&&>(s).n)); + using T = decltype((f().n)); + using T = decltype(S().*&S::n); + using T = decltype(static_cast<S&&>(s).*&S::n); + using T = decltype(f().*&S::n); + using T = int&&; + + using U = decltype(S().n); + using U = decltype(static_cast<S&&>(s).n); + using U = int; #endif } @@ -347,3 +353,66 @@ namespace dr639 { // dr639: yes void((i = 0) + (i = 0)); // expected-warning {{unsequenced}} } } + +namespace dr692 { // dr692: no + namespace temp_func_order_example2 { + template <typename T, typename U> struct A {}; + template <typename T, typename U> void f(U, A<U, T> *p = 0); // expected-note {{candidate}} + template <typename U> int &f(U, A<U, U> *p = 0); // expected-note {{candidate}} + template <typename T> void g(T, T = T()); + template <typename T, typename... U> void g(T, U...); // expected-error 0-1{{C++11}} + void h() { + int &r = f<int>(42, (A<int, int> *)0); + f<int>(42); // expected-error {{ambiguous}} + // FIXME: We should reject this due to ambiguity between the pack and the + // default argument. Only parameters with arguments are considered during + // partial ordering of function templates. + g(42); + } + } + + namespace temp_func_order_example3 { + template <typename T, typename... U> void f(T, U...); // expected-error 0-1{{C++11}} + template <typename T> void f(T); + template <typename T, typename... U> int &g(T *, U...); // expected-error 0-1{{C++11}} + template <typename T> void g(T); + void h(int i) { + // This is made ambiguous by dr692, but made valid again by dr1395. + f(&i); + int &r = g(&i); + } + } + + namespace temp_deduct_partial_example { + template <typename... Args> char &f(Args... args); // expected-error 0-1{{C++11}} + template <typename T1, typename... Args> short &f(T1 a1, Args... args); // expected-error 0-1{{C++11}} + template <typename T1, typename T2> int &f(T1 a1, T2 a2); + void g() { + char &a = f(); + short &b = f(1, 2, 3); + int &c = f(1, 2); + } + } + + namespace temp_deduct_type_example1 { + template <class T1, class ...Z> class S; // expected-error 0-1{{C++11}} + template <class T1, class ...Z> class S<T1, const Z&...>; // expected-error 0-1{{C++11}} + template <class T1, class T2> class S<T1, const T2&> {}; + S<int, const int&> s; + + // FIXME: This should select the first partial specialization. Deduction of + // the second from the first should succeed, because we should ignore the + // trailing pack in A with no corresponding P. + template<class T, class... U> struct A; // expected-error 0-1{{C++11}} + template<class T1, class T2, class... U> struct A<T1,T2*,U...>; // expected-note {{matches}} expected-error 0-1{{C++11}} + template<class T1, class T2> struct A<T1,T2> {}; // expected-note {{matches}} + template struct A<int, int*>; // expected-error {{ambiguous}} + } + + namespace temp_deduct_type_example3 { + // FIXME: This should select the first template, as in the case above. + template<class T, class... U> void f(T*, U...){} // expected-note {{candidate}} expected-error 0-1{{C++11}} + template<class T> void f(T){} // expected-note {{candidate}} + template void f(int*); // expected-error {{ambiguous}} + } +} diff --git a/test/CXX/except/except.spec/p2-places-1z.cpp b/test/CXX/except/except.spec/p2-places-1z.cpp new file mode 100644 index 0000000000000..619ea33b5349b --- /dev/null +++ b/test/CXX/except/except.spec/p2-places-1z.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++1z -fexceptions -fcxx-exceptions -fsyntax-only -verify %s + +// In C++1z, we can put an exception-specification on any function declarator; the +// corresponding paragraph from C++14 and before was deleted. +// expected-no-diagnostics + +void f() noexcept; +void (*fp)() noexcept; +void (**fpp)() noexcept; +void g(void (**pfa)() noexcept); +void (**h())() noexcept; + +template<typename T> struct A {}; +template<void() noexcept> struct B {}; +A<void() noexcept> a; +B<f> b; +auto *p = new decltype(f)**; diff --git a/test/CXX/except/except.spec/p2-places.cpp b/test/CXX/except/except.spec/p2-places.cpp index 67647fb043a98..ea842af898459 100644 --- a/test/CXX/except/except.spec/p2-places.cpp +++ b/test/CXX/except/except.spec/p2-places.cpp @@ -37,6 +37,8 @@ namespace dyn { // Pointer to function returning pointer to pointer to function with spec void (**(*h())())() throw(int); // expected-error {{not allowed beyond a single}} + // FIXME: Missing a lot of negative tests, primarily type-ids in various places + // We fail to diagnose all of those. } namespace noex { diff --git a/test/CXX/except/except.spec/p5-pointers.cpp b/test/CXX/except/except.spec/p5-pointers.cpp index fe4a264587f5a..dedc5bd376f92 100644 --- a/test/CXX/except/except.spec/p5-pointers.cpp +++ b/test/CXX/except/except.spec/p5-pointers.cpp @@ -41,25 +41,25 @@ 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}} + t1 = &s2; // expected-error {{not superset}} + t1 = &s3; // expected-error {{not superset}} 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}} + t4 = &s5; // expected-error {{not superset}} void (*t5)() = &s1; // valid t5 = &s2; // valid t5 = &s6; // valid t5 = &s7; // valid - t1 = t3; // expected-error {{not superset}} expected-error {{incompatible type}} + t1 = t3; // expected-error {{not superset}} t3 = t1; // valid void (*t6)() throw(B1); - t6 = t4; // expected-error {{not superset}} expected-error {{incompatible type}} + t6 = t4; // expected-error {{not superset}} t4 = t6; // valid t5 = t1; // valid - t1 = t5; // expected-error {{not superset}} expected-error {{incompatible type}} + t1 = t5; // expected-error {{not superset}} // return types and arguments must match exactly, no inheritance allowed void (*(*t7)())() throw(B1) = &s8; // valid diff --git a/test/CXX/expr/expr.cond/p4.cpp b/test/CXX/expr/expr.cond/p4.cpp new file mode 100644 index 0000000000000..4d0cf3538cf05 --- /dev/null +++ b/test/CXX/expr/expr.cond/p4.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++98 -verify %s +// RUN: %clang_cc1 -std=c++1z -verify %s + +// expected-no-diagnostics + +struct A { A(); A(int); }; +void f() { + const A a; + true ? a : 0; +} diff --git a/test/CXX/expr/expr.const/p2-0x.cpp b/test/CXX/expr/expr.const/p2-0x.cpp index fd15960647ca0..6d46bf5d77dd9 100644 --- a/test/CXX/expr/expr.const/p2-0x.cpp +++ b/test/CXX/expr/expr.const/p2-0x.cpp @@ -33,11 +33,11 @@ struct NonConstexpr3 { int m : NonConstexpr2().n; // expected-error {{constant expression}} expected-note {{undefined constructor 'NonConstexpr2'}} }; struct NonConstexpr4 { - NonConstexpr4(); // expected-note {{declared here}} + NonConstexpr4(); 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}} + int n : NonConstexpr4().n; // expected-error {{constant expression}} expected-note {{non-literal type 'NonConstexpr4' cannot be used in a constant expression}} }; // - an invocation of an undefined constexpr function or an undefined @@ -321,7 +321,7 @@ namespace LValueToRValue { // 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(f().i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} static_assert(((volatile const S&&)(S)0).i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}} } @@ -461,14 +461,14 @@ namespace UnspecifiedRelations { 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}} + constexpr bool u5 = p < (int*)0; // expected-error {{constant expression}} + constexpr bool u6 = p <= (int*)0; // expected-error {{constant expression}} + constexpr bool u7 = p > (int*)0; // expected-error {{constant expression}} + constexpr bool u8 = p >= (int*)0; // expected-error {{constant expression}} + constexpr bool u9 = (int*)0 < q; // expected-error {{constant expression}} + constexpr bool u10 = (int*)0 <= q; // expected-error {{constant expression}} + constexpr bool u11 = (int*)0 > q; // expected-error {{constant expression}} + constexpr bool u12 = (int*)0 >= q; // expected-error {{constant expression}} void f(), g(); constexpr void (*pf)() = &f, (*pg)() = &g; @@ -522,7 +522,7 @@ namespace UnspecifiedRelations { constexpr void *null = 0; constexpr void *pv = (void*)&s.a; constexpr void *qv = (void*)&s.b; - constexpr bool v1 = null < 0; + constexpr bool v1 = null < (int*)0; constexpr bool v2 = null < pv; // expected-error {{constant expression}} constexpr bool v3 = null == pv; // ok constexpr bool v4 = qv == pv; // ok diff --git a/test/CXX/expr/expr.const/p3-0x.cpp b/test/CXX/expr/expr.const/p3-0x.cpp index d9d84853ebae9..731e0c312fa13 100644 --- a/test/CXX/expr/expr.const/p3-0x.cpp +++ b/test/CXX/expr/expr.const/p3-0x.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++1z -verify %s // A converted constant expression of type T is a core constant expression, int nonconst = 8; // expected-note 3 {{here}} @@ -40,10 +41,10 @@ const E e10 = E10; template<E> struct T {}; T<e10> s10; -// integral promotions, and +// integral promotions, enum class EE { EE32 = ' ', EE65 = 'A', EE1 = (short)1, EE5 = E5 }; -// integral conversions other than narrowing conversions +// integral conversions other than narrowing conversions, int b(unsigned n) { switch (n) { case E6: @@ -74,12 +75,22 @@ using Int = A<-3>; // expected-error {{template argument evaluates to -3, which // Note, conversions from integral or unscoped enumeration types to bool are // integral conversions as well as boolean conversions. +// FIXME: Per core issue 1407, this is not correct. 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'}} +// function pointer conversions [C++17] +void noexcept_false() noexcept(false); +void noexcept_true() noexcept(true); +Val<decltype(&noexcept_false), &noexcept_true> remove_noexcept; +Val<decltype(&noexcept_true), &noexcept_false> add_noexcept; +#if __cplusplus > 201402L +// expected-error@-2 {{value of type 'void (*)() noexcept(false)' is not implicitly convertible to 'void (*)() noexcept'}} +#endif + // (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 { diff --git a/test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp b/test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp new file mode 100644 index 0000000000000..8701a00d5cf01 --- /dev/null +++ b/test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + + +// p3 +// 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). +// p4 +// Otherwise, an expression e can be explicitly converted to a type T using a +// static_cast of the form static_cast<T>(e) if the declaration T t(e); is +// well-formed, for some invented temporary variable t (8.5). [...] +struct A { }; +struct B : A { }; + +struct C { explicit operator A&&(); }; +struct D { operator B(); }; + +template<typename T> T& lvalue(); +template<typename T> T&& xvalue(); +template <typename T> T prvalue(); + +void test(A &a, B &b) { + A &&ar0 = static_cast<A&&>(prvalue<A>()); + A &&ar1 = static_cast<A&&>(prvalue<B>()); + A &&ar2 = static_cast<A&&>(lvalue<C>()); + A &&ar3 = static_cast<A&&>(xvalue<C>()); + A &&ar4 = static_cast<A&&>(prvalue<C>()); + A &&ar5 = static_cast<A&&>(lvalue<D>()); + A &&ar6 = static_cast<A&&>(xvalue<D>()); + A &&ar7 = static_cast<A&&>(prvalue<D>()); + + A &&ar8 = static_cast<A&&>(prvalue<const A>()); // expected-error {{binding value of type 'const A' to reference to type 'A' drops 'const' qualifier}} + A &&ar9 = static_cast<A&&>(lvalue<const A>()); // expected-error {{cannot cast from lvalue of type 'const A'}} + A &&ar10 = static_cast<A&&>(xvalue<const A>()); // expected-error {{cannot cast from rvalue of type 'const A'}} + + const A &&ar11 = static_cast<const A&&>(prvalue<A>()); + const A &&ar12 = static_cast<const A&&>(prvalue<B>()); + const A &&ar13 = static_cast<const A&&>(lvalue<C>()); + const A &&ar14 = static_cast<const A&&>(xvalue<C>()); + const A &&ar15 = static_cast<const A&&>(prvalue<C>()); + const A &&ar16 = static_cast<const A&&>(lvalue<D>()); + + const A &&ar17 = static_cast<const A&&>(prvalue<A const volatile>()); // expected-error {{binding value of type 'const volatile A' to reference to type 'const A' drops 'volatile' qualifier}} +} diff --git a/test/CXX/expr/expr.post/expr.static.cast/p7.cpp b/test/CXX/expr/expr.post/expr.static.cast/p7.cpp new file mode 100644 index 0000000000000..fd8e478b5193b --- /dev/null +++ b/test/CXX/expr/expr.post/expr.static.cast/p7.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s -fcxx-exceptions + +void (*p)() noexcept; +void (*q)(); + +void f() { + // FIXME: This seems like a bad rule. + p = static_cast<decltype(p)>(q); // expected-error {{not allowed}} + q = static_cast<decltype(q)>(p); +} 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 40360e40694c1..1dbcbf498031d 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp @@ -7,7 +7,7 @@ struct MoveOnly { template<typename T> T &&move(T&); void test_special_member_functions(MoveOnly mo, int i) { - auto lambda1 = [i]() { }; // expected-note {{lambda expression begins here}} expected-note 2{{candidate}} + auto lambda1 = [i]() { }; // expected-note 2{{lambda expression begins here}} expected-note 2{{candidate}} // Default constructor decltype(lambda1) lambda2; // expected-error{{no matching constructor}} @@ -16,7 +16,7 @@ void test_special_member_functions(MoveOnly mo, int i) { lambda1 = lambda1; // expected-error{{copy assignment operator is implicitly deleted}} // Move assignment operator - lambda1 = move(lambda1); + lambda1 = move(lambda1); // expected-error{{copy assignment operator is implicitly deleted}} // Copy constructor decltype(lambda1) lambda3 = lambda1; diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp index 8b43cefa92c06..90a3aec50cb38 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify +// RUN: %clang_cc1 -fsyntax-only -std=c++1z %s -verify void test_conversion() { int (*fp1)(int) = [](int x) { return x + 1; }; @@ -9,6 +10,15 @@ void test_conversion() { volatile const auto lambda2 = [](int x) { }; // expected-note{{but method is not marked volatile}} void (*fp4)(int) = lambda2; // expected-error{{no viable conversion}} + + void (*fp5)(int) noexcept = [](int x) { }; +#if __cplusplus > 201402L + // expected-error@-2 {{no viable}} expected-note@-2 {{candidate}} + void (*fp5a)(int) noexcept = [](auto x) { }; + // expected-error@-1 {{no viable}} expected-note@-1 {{candidate}} + void (*fp5b)(int) noexcept = [](auto x) noexcept { }; +#endif + void (*fp6)(int) noexcept = [](int x) noexcept { }; } void test_no_conversion() { diff --git a/test/CXX/expr/expr.unary/expr.delete/p10.cpp b/test/CXX/expr/expr.unary/expr.delete/p10.cpp new file mode 100644 index 0000000000000..aad2747dd32f2 --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.delete/p10.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +using size_t = decltype(sizeof(0)); +namespace std { enum class align_val_t : size_t {}; } + +// Aligned version is preferred over unaligned version, +// unsized version is preferred over sized version. +template<unsigned Align> +struct alignas(Align) A { + void operator delete(void*); + void operator delete(void*, std::align_val_t) = delete; // expected-note {{here}} + + void operator delete(void*, size_t) = delete; + void operator delete(void*, size_t, std::align_val_t) = delete; +}; +void f(A<__STDCPP_DEFAULT_NEW_ALIGNMENT__> *p) { delete p; } +void f(A<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2> *p) { delete p; } // expected-error {{deleted}} + +template<unsigned Align> +struct alignas(Align) B { + void operator delete(void*, size_t); + void operator delete(void*, size_t, std::align_val_t) = delete; // expected-note {{here}} +}; +void f(B<__STDCPP_DEFAULT_NEW_ALIGNMENT__> *p) { delete p; } +void f(B<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2> *p) { delete p; } // expected-error {{deleted}} diff --git a/test/CXX/expr/expr.unary/expr.new/p14.cpp b/test/CXX/expr/expr.unary/expr.new/p14.cpp new file mode 100644 index 0000000000000..6537cdcfeafa0 --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.new/p14.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -std=c++1z -fsized-deallocation -fexceptions %s -verify + +using size_t = decltype(sizeof(0)); +namespace std { enum class align_val_t : size_t {}; } + +struct Arg {} arg; + +// If the type is aligned, first try with an alignment argument and then +// without. If not, never consider supplying an alignment. + +template<unsigned Align, typename ...Ts> +struct alignas(Align) Unaligned { + void *operator new(size_t, Ts...) = delete; // expected-note 4{{deleted}} +}; +auto *ua = new Unaligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__>; // expected-error {{deleted}} +auto *ub = new Unaligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2>; // expected-error {{deleted}} +auto *uap = new (arg) Unaligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__, Arg>; // expected-error {{deleted}} +auto *ubp = new (arg) Unaligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2, Arg>; // expected-error {{deleted}} + +template<unsigned Align, typename ...Ts> +struct alignas(Align) Aligned { + void *operator new(size_t, std::align_val_t, Ts...) = delete; // expected-note 2{{deleted}} expected-note 2{{not viable}} +}; +auto *aa = new Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__>; // expected-error {{no matching}} +auto *ab = new Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2>; // expected-error {{deleted}} +auto *aap = new (arg) Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__, Arg>; // expected-error {{no matching}} +auto *abp = new (arg) Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2, Arg>; // expected-error {{deleted}} + +// If both are available, we prefer the aligned version for an overaligned +// type, and only use the unaligned version for a non-overaligned type. + +template<unsigned Align, typename ...Ts> +struct alignas(Align) Both1 { + void *operator new(size_t, Ts...); // expected-note 2{{not viable}} + void *operator new(size_t, std::align_val_t, Ts...) = delete; // expected-note 2{{deleted}} +}; +template<unsigned Align, typename ...Ts> +struct alignas(Align) Both2 { + void *operator new(size_t, Ts...) = delete; // expected-note 2{{deleted}} + void *operator new(size_t, std::align_val_t, Ts...); // expected-note 2{{not viable}} +}; +auto *b1a = new Both1<__STDCPP_DEFAULT_NEW_ALIGNMENT__>; +auto *b1b = new Both1<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2>; // expected-error {{deleted}} +auto *b2a = new Both2<__STDCPP_DEFAULT_NEW_ALIGNMENT__>; // expected-error {{deleted}} +auto *b2b = new Both2<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2>; +auto *b1ap = new (arg) Both1<__STDCPP_DEFAULT_NEW_ALIGNMENT__, Arg>; +auto *b1bp = new (arg) Both1<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2, Arg>; // expected-error {{deleted}} +auto *b2ap = new (arg) Both2<__STDCPP_DEFAULT_NEW_ALIGNMENT__, Arg>; // expected-error {{deleted}} +auto *b2bp = new (arg) Both2<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2, Arg>; + +// Note that the aligned form can select a function with a parameter different +// from std::align_val_t. + +struct alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2) WeirdAlignedAlloc1 { + void *operator new(size_t, ...) = delete; // expected-note 2{{deleted}} +}; +auto *waa1 = new WeirdAlignedAlloc1; // expected-error {{deleted}} +auto *waa1p = new (arg) WeirdAlignedAlloc1; // expected-error {{deleted}} + +struct alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2) WeirdAlignedAlloc2 { + template<typename ...T> + void *operator new(size_t, T...) { + using U = void(T...); // expected-note 2{{previous}} + using U = void; // expected-error {{different types ('void' vs 'void (std::align_val_t)')}} \ + expected-error {{different types ('void' vs 'void (std::align_val_t, Arg)')}} + } +}; +auto *waa2 = new WeirdAlignedAlloc2; // expected-note {{instantiation of}} +auto *waa2p = new (arg) WeirdAlignedAlloc2; // expected-note {{instantiation of}} diff --git a/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp b/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp index eca1ec7901999..13676a8a07cec 100644 --- a/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp +++ b/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp @@ -1,6 +1,10 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fexceptions %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 -fexceptions %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z -fexceptions %s typedef __SIZE_TYPE__ size_t; +namespace std { enum class align_val_t : size_t {}; } + struct S { // Placement allocation function: static void* operator new(size_t, size_t); @@ -9,5 +13,56 @@ struct S { }; void testS() { - S* p = new (0) S; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}} + S* p = new (0) S; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}} +} + +struct T { + // Placement allocation function: + static void* operator new(size_t, size_t); + // Usual (non-placement) deallocation function: + static void operator delete(void*); + // Placement deallocation function: + static void operator delete(void*, size_t); +}; + +void testT() { + T* p = new (0) T; // ok +} + +#if __cplusplus > 201402L +struct U { + // Placement allocation function: + static void* operator new(size_t, size_t, std::align_val_t); + // Placement deallocation function: + static void operator delete(void*, size_t, std::align_val_t); // expected-note{{declared here}} +}; + +void testU() { + U* p = new (0, std::align_val_t(0)) U; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}} +} + +struct V { + // Placement allocation function: + static void* operator new(size_t, size_t, std::align_val_t); + // Usual (non-placement) deallocation function: + static void operator delete(void*, std::align_val_t); + // Placement deallocation function: + static void operator delete(void*, size_t, std::align_val_t); +}; + +void testV() { + V* p = new (0, std::align_val_t(0)) V; +} + +struct W { + // Placement allocation function: + static void* operator new(size_t, size_t, std::align_val_t); + // Usual (non-placement) deallocation functions: + static void operator delete(void*); + static void operator delete(void*, size_t, std::align_val_t); // expected-note {{declared here}} +}; + +void testW() { + W* p = new (0, std::align_val_t(0)) W; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}} } +#endif diff --git a/test/CXX/expr/p13.cpp b/test/CXX/expr/p13.cpp new file mode 100644 index 0000000000000..0f22ce0b7cebc --- /dev/null +++ b/test/CXX/expr/p13.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s -fexceptions -fcxx-exceptions -Wno-dynamic-exception-spec + +struct X {}; +struct Y : X {}; + +using A = void (*)() noexcept; +using B = void (*)(); +using C = void (X::*)() noexcept; +using D = void (X::*)(); +using E = void (Y::*)() noexcept; +using F = void (Y::*)(); + +void f(A a, B b, C c, D d, E e, F f, bool k) { + a = k ? a : b; // expected-error {{different exception specifications}} + b = k ? a : b; + + c = k ? c : d; // expected-error {{different exception specifications}} + d = k ? c : d; + + e = k ? c : f; // expected-error {{different exception specifications}} + e = k ? d : e; // expected-error {{different exception specifications}} + f = k ? c : f; + f = k ? d : e; + + const A ak = a; + const B bk = b; + const A &ak2 = k ? ak : ak; + const A &ak3 = k ? ak : bk; // expected-error {{could not bind}} + const B &bk3 = k ? ak : bk; +} + +namespace dynamic_exception_spec { + // Prior to P0012, we had: + // "[...] the target entity shall allow at least the exceptions allowed + // by the source value in the assignment or initialization" + // + // There's really only one way we can coherently apply this to conditional + // expressions: this must hold no matter which branch was taken. + using X = void (*)() throw(int); + using Y = void (*)() throw(float); + using Z = void (*)() throw(int, float); + void g(X x, Y y, Z z, bool k) { + x = k ? X() : Y(); // expected-warning {{not superset}} + y = k ? X() : Y(); // expected-warning {{not superset}} + z = k ? X() : Y(); + + x = k ? x : y; // expected-warning {{not superset}} + y = k ? x : y; // expected-warning {{not superset}} + z = k ? x : y; + } +} diff --git a/test/CXX/over/over.built/p15.cpp b/test/CXX/over/over.built/p15.cpp new file mode 100644 index 0000000000000..64ed3e7b83ded --- /dev/null +++ b/test/CXX/over/over.built/p15.cpp @@ -0,0 +1,83 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare + +struct A { operator decltype(nullptr)(); }; +struct B { operator const int *(); }; +void f(A a, B b, volatile int *pi) { + (void)(a == a); + (void)(a != a); + (void)(a < a); // expected-error {{invalid operands}} + (void)(a > a); // expected-error {{invalid operands}} + (void)(a <= a); // expected-error {{invalid operands}} + (void)(a >= a); // expected-error {{invalid operands}} + + (void)(a == b); + (void)(a != b); + // FIXME: These cases were intended to be made ill-formed by N3624, but it + // fails to actually achieve this goal. + (void)(a < b); + (void)(a > b); + (void)(a <= b); + (void)(a >= b); + + (void)(b == a); + (void)(b != a); + // FIXME: These cases were intended to be made ill-formed by N3624, but it + // fails to actually achieve this goal. + (void)(b < a); + (void)(b > a); + (void)(b <= a); + (void)(b >= a); + + (void)(a == pi); + (void)(a != pi); + // FIXME: These cases were intended to be made ill-formed by N3624, but it + // fails to actually achieve this goal. + (void)(a < pi); + (void)(a > pi); + (void)(a <= pi); + (void)(a >= pi); + + (void)(pi == a); + (void)(pi != a); + // FIXME: These cases were intended to be made ill-formed by N3624, but it + // fails to actually achieve this goal. + (void)(pi < a); + (void)(pi > a); + (void)(pi <= a); + (void)(pi >= a); + + (void)(b == pi); + (void)(b != pi); + (void)(b < pi); + (void)(b > pi); + (void)(b <= pi); + (void)(b >= pi); + + (void)(pi == b); + (void)(pi != b); + (void)(pi < b); + (void)(pi > b); + (void)(pi <= b); + (void)(pi >= b); + + (void)(b == b); + (void)(b != b); + (void)(b < b); + (void)(b > b); + (void)(b <= b); + (void)(b >= b); + + (void)(pi == pi); + (void)(pi != pi); + (void)(pi < pi); + (void)(pi > pi); + (void)(pi <= pi); + (void)(pi >= pi); +} + +// FIXME: This is wrong: the type T = 'const volatile int * const * const *' +// would work here, and there exists a builtin candidate for that type. +struct C { operator const int ***(); }; +void g(C c, volatile int ***p) { + (void)(c < p); // expected-error {{invalid operands}} +} diff --git a/test/CXX/over/over.built/p16.cpp b/test/CXX/over/over.built/p16.cpp new file mode 100644 index 0000000000000..139e864475244 --- /dev/null +++ b/test/CXX/over/over.built/p16.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare + +struct A { operator decltype(nullptr)(); }; +struct B { operator int A::*(); }; +void f(A a, B b, int A::*pi) { + (void)(a == a); + (void)(a != a); + (void)(a < a); // expected-error {{invalid operands}} + (void)(a > a); // expected-error {{invalid operands}} + (void)(a <= a); // expected-error {{invalid operands}} + (void)(a >= a); // expected-error {{invalid operands}} + + (void)(a == b); + (void)(a != b); + (void)(a < b); // expected-error {{invalid operands}} + (void)(a > b); // expected-error {{invalid operands}} + (void)(a <= b); // expected-error {{invalid operands}} + (void)(a >= b); // expected-error {{invalid operands}} + + (void)(b == a); + (void)(b != a); + (void)(b < a); // expected-error {{invalid operands}} + (void)(b > a); // expected-error {{invalid operands}} + (void)(b <= a); // expected-error {{invalid operands}} + (void)(b >= a); // expected-error {{invalid operands}} + + (void)(a == pi); + (void)(a != pi); + (void)(a < pi); // expected-error {{invalid operands}} + (void)(a > pi); // expected-error {{invalid operands}} + (void)(a <= pi); // expected-error {{invalid operands}} + (void)(a >= pi); // expected-error {{invalid operands}} + + (void)(pi == a); + (void)(pi != a); + (void)(pi < a); // expected-error {{invalid operands}} + (void)(pi > a); // expected-error {{invalid operands}} + (void)(pi <= a); // expected-error {{invalid operands}} + (void)(pi >= a); // expected-error {{invalid operands}} + + (void)(b == pi); + (void)(b != pi); + (void)(b < pi); // expected-error {{invalid operands}} + (void)(b > pi); // expected-error {{invalid operands}} + (void)(b <= pi); // expected-error {{invalid operands}} + (void)(b >= pi); // expected-error {{invalid operands}} + + (void)(pi == b); + (void)(pi != b); + (void)(pi < b); // expected-error {{invalid operands}} + (void)(pi > b); // expected-error {{invalid operands}} + (void)(pi <= b); // expected-error {{invalid operands}} + (void)(pi >= b); // expected-error {{invalid operands}} + + (void)(b == b); + (void)(b != b); + (void)(b < b); // expected-error {{invalid operands}} + (void)(b > b); // expected-error {{invalid operands}} + (void)(b <= b); // expected-error {{invalid operands}} + (void)(b >= b); // expected-error {{invalid operands}} + + (void)(pi == pi); + (void)(pi != pi); + (void)(pi < pi); // expected-error {{invalid operands}} + (void)(pi > pi); // expected-error {{invalid operands}} + (void)(pi <= pi); // expected-error {{invalid operands}} + (void)(pi >= pi); // expected-error {{invalid operands}} +} + +// FIXME: This is wrong: type T = 'const volatile int * const A::* const B::*' +// would work here, and there exists a builtin candidate for that type. +struct C { operator const int *A::*B::*(); }; +void g(C c, volatile int *A::*B::*p) { + (void)(c == p); // expected-error {{invalid operands}} +} diff --git a/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.scs/p3.cpp b/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.scs/p3.cpp new file mode 100644 index 0000000000000..df2fc2cd2e82b --- /dev/null +++ b/test/CXX/over/over.match/over.match.best/over.best.ics/over.ics.scs/p3.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +void f(void() noexcept); // expected-note {{no known conversion from 'void ()' to 'void (*)() noexcept'}} +void f(void()) = delete; // expected-note {{explicitly deleted}} + +void g(); +void h() noexcept; + +void test() { + f(g); // expected-error {{call to deleted}} + f(h); +} diff --git a/test/CXX/over/over.oper/over.literal/p6.cpp b/test/CXX/over/over.oper/over.literal/p6.cpp index 6bfb8560d6889..9ecf9ccccb14c 100644 --- a/test/CXX/over/over.oper/over.literal/p6.cpp +++ b/test/CXX/over/over.oper/over.literal/p6.cpp @@ -1,9 +1,11 @@ // RUN: %clang_cc1 -std=c++11 %s -verify +// expected-note@+1 {{extern "C" language linkage specification begins here}} 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}} +// expected-note@-1 {{extern "C" language linkage specification begins here}} -extern "C" { +extern "C" { // expected-note 4 {{extern "C" language linkage specification begins here}} void operator "" _c(const char *); // expected-error {{must have C++ linkage}} template<char...> void operator "" _d(); // expected-error {{must have C++ linkage}} namespace N { diff --git a/test/CXX/over/over.over/p1.cpp b/test/CXX/over/over.over/p1.cpp index 10c60da013cbc..e31a2c5067562 100644 --- a/test/CXX/over/over.over/p1.cpp +++ b/test/CXX/over/over.over/p1.cpp @@ -1,7 +1,9 @@ -// RUN: %clang_cc1 -fsyntax-only %s +// RUN: %clang_cc1 -fsyntax-only -DNOEXCEPT= -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++1z -DNOEXCEPT= -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++1z -DNOEXCEPT=noexcept -verify %s -template<typename T> T f0(T); -int f0(int); +template<typename T> T f0(T) NOEXCEPT; +int f0(int) NOEXCEPT; // -- an object or reference being initialized struct S { @@ -92,3 +94,18 @@ Y1<f0> y1; Y1<&f0> y1a; Y2<f0> y2; Y3<f0> y3; + +#if __cplusplus > 201402L +namespace MixedNoexcept { + inline namespace A { + void f() noexcept; // expected-note {{candidate}} + } + inline namespace B { + void f(); // expected-note {{candidate}} + } + void (*p)() noexcept = &f; // ok + void (*q)() = &f; // expected-error {{ambiguous}} +} +#else +// expected-no-diagnostics +#endif diff --git a/test/CXX/special/class.copy/implicit-move-def.cpp b/test/CXX/special/class.copy/implicit-move-def.cpp index f344b0cc6a0f3..7a6a1ee984e92 100644 --- a/test/CXX/special/class.copy/implicit-move-def.cpp +++ b/test/CXX/special/class.copy/implicit-move-def.cpp @@ -110,8 +110,8 @@ void move_VirtualWithEmptyBase(VirtualWithEmptyBase &x, VirtualWithEmptyBase &y) // CHECK-CTOR: call {{.*}} @_ZN1FC1EOS_ // CHECK-CTOR: call {{.*}} @_ZN1EC1EOS_ // array loop -// CHECK-CTOR: br i1 // CHECK-CTOR: call {{.*}} @_ZN1FC1EOS_ +// CHECK-CTOR: br i1 // CHECK-CTOR: define linkonce_odr {{.*}} @_ZN1GC2EOS_ // CHECK-CTOR: call {{.*}} @_ZN1EC1EOS_ diff --git a/test/CXX/special/class.copy/p20.cpp b/test/CXX/special/class.copy/p20.cpp index 8dfb7ca8a068d..4f17879ecfb70 100644 --- a/test/CXX/special/class.copy/p20.cpp +++ b/test/CXX/special/class.copy/p20.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s struct ConstCopy { ConstCopy(); diff --git a/test/CXX/special/class.dtor/p3-0x.cpp b/test/CXX/special/class.dtor/p3-0x.cpp index 2d7eba490bc8e..f6a64260e0df5 100644 --- a/test/CXX/special/class.dtor/p3-0x.cpp +++ b/test/CXX/special/class.dtor/p3-0x.cpp @@ -176,4 +176,4 @@ struct TVC : VX template <typename T> TVC<T>::~TVC() {} -// CHECK: attributes [[ATTRGRP]] = { nounwind{{.*}} } +// CHECK: attributes [[ATTRGRP]] = { noinline nounwind{{.*}} } diff --git a/test/CXX/special/class.dtor/p5-0x.cpp b/test/CXX/special/class.dtor/p5-0x.cpp index e32279ef125bb..595784f0d5f9d 100644 --- a/test/CXX/special/class.dtor/p5-0x.cpp +++ b/test/CXX/special/class.dtor/p5-0x.cpp @@ -90,7 +90,7 @@ class D1 { public: virtual ~D1() = default; // expected-note {{here}} } d1; // ok -struct D2 : D1 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}} \ +struct D2 : D1 { // expected-note 2{{virtual destructor requires an unambiguous, accessible 'operator delete'}} \ // expected-error {{deleted function '~D2' cannot override a non-deleted}} // implicitly-virtual destructor } d2; // expected-error {{deleted function}} diff --git a/test/CXX/special/class.dtor/p9.cpp b/test/CXX/special/class.dtor/p9.cpp index 42a4236a4a079..e812491fbb4b3 100644 --- a/test/CXX/special/class.dtor/p9.cpp +++ b/test/CXX/special/class.dtor/p9.cpp @@ -1,7 +1,9 @@ -// RUN: %clang_cc1 -fsyntax-only -triple %itanium_abi_triple -verify %s -// RUN: %clang_cc1 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify %s +// RUN: %clang_cc1 -fsyntax-only -triple %itanium_abi_triple -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -triple %itanium_abi_triple -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify -std=c++11 %s -typedef typeof(sizeof(int)) size_t; +typedef __typeof(sizeof(int)) size_t; // PR7803 namespace test0 { @@ -29,13 +31,13 @@ namespace test0 { namespace test1 { class A { public: - static void operator delete(void *p) {}; // expected-note {{member 'operator delete' declared here}} + static void operator delete(void *p) {}; virtual ~A(); }; class B : protected A { public: - static void operator delete(void *, size_t) {}; // expected-note {{member 'operator delete' declared here}} + static void operator delete(void *, size_t) {}; ~B(); }; @@ -47,7 +49,20 @@ namespace test1 { ~C(); }; - C::~C() {} // expected-error {{multiple suitable 'operator delete' functions in 'C'}} + // We assume that the intent is to treat C::operator delete(void*, size_t) as + // /not/ being a usual deallocation function, as it would be if it were + // declared with in C directly. + C::~C() {} + + struct D { + void operator delete(void*); // expected-note {{member 'operator delete' declared here}} + void operator delete(void*, ...); // expected-note {{member 'operator delete' declared here}} + virtual ~D(); + }; + // FIXME: The standard doesn't say this is ill-formed, but presumably either + // it should be or the variadic operator delete should not be a usual + // deallocation function. + D::~D() {} // expected-error {{multiple suitable 'operator delete' functions in 'D'}} } // ...at the point of definition of a virtual destructor... @@ -63,6 +78,7 @@ namespace test2 { }; B::~B() {} // expected-error {{no suitable member 'operator delete' in 'B'}} +#if __cplusplus < 201103L 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}} @@ -70,6 +86,15 @@ namespace test2 { void test() { C c; // expected-note {{first required here}} } +#else + struct CBase { virtual ~CBase(); }; // expected-note {{overridden virtual function is here}} + struct C : CBase { // expected-error {{deleted function '~C' cannot override a non-deleted function}} expected-note 2{{requires an unambiguous, accessible 'operator delete'}} + static void operator delete(void*, const int &); + }; + void test() { + C c; // expected-error {{attempt to use a deleted function}} + } +#endif } // PR7346 diff --git a/test/CXX/special/class.init/class.inhctor.init/p1.cpp b/test/CXX/special/class.init/class.inhctor.init/p1.cpp index e07d879df8f1c..1f4362740b00e 100644 --- a/test/CXX/special/class.init/class.inhctor.init/p1.cpp +++ b/test/CXX/special/class.init/class.inhctor.init/p1.cpp @@ -87,6 +87,13 @@ namespace vbase { D d2(0, 0); // expected-error {{deleted}} } +namespace vbase_of_vbase { + struct V { V(int); }; + struct W : virtual V { using V::V; }; + struct X : virtual W, virtual V { using W::W; }; + X x(0); +} + namespace constexpr_init_order { struct Param; struct A { diff --git a/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp b/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp index d6a2169a5baf9..c33bf0eba231b 100644 --- a/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp +++ b/test/CXX/stmt.stmt/stmt.select/stmt.if/p2.cpp @@ -46,6 +46,11 @@ namespace ccce { if constexpr (N) {} // expected-error {{cannot be narrowed}} } template void g<5>(); // expected-note {{instantiation of}} + void h() { + if constexpr (4.3) {} // expected-error{{conversion from 'double' to 'bool' is not allowed in a converted constant expression}} + constexpr void *p = nullptr; + if constexpr (p) {} // expected-error{{conversion from 'void *const' to 'bool' is not allowed in a converted constant expression}} + } } namespace generic_lambda { diff --git a/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp b/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp index 249563e7d9bf1..5341290a1446e 100644 --- a/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp +++ b/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp @@ -1,3 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s // RUN: %clang_cc1 -fsyntax-only -verify %s // C++0x [temp.arg.nontype] p5: @@ -45,15 +49,23 @@ namespace pointer_to_object_parameters { operator int() const; }; - template<X const *Ptr> struct A2; // expected-note{{template parameter is declared here}} + template<X const *Ptr> struct A2; // expected-note 0-1{{template parameter is declared here}} - X *X_ptr; + X *X_ptr; // expected-note 0-1{{declared here}} X an_X; X array_of_Xs[10]; - A2<X_ptr> *a12; // expected-error{{must have its address taken}} + A2<X_ptr> *a12; +#if __cplusplus < 201103L + // expected-error@-2 {{must have its address taken}} +#else + // expected-error@-4 {{not a constant expression}} expected-note@-4 {{read of non-constexpr variable}} +#endif 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}} + A2<(&an_X)> *a13_3; +#if __cplusplus < 201103L + // expected-warning@-2 {{address non-type template argument cannot be surrounded by parentheses}} +#endif // PR6244 struct X1 {} X1v; @@ -62,12 +74,24 @@ namespace pointer_to_object_parameters { 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 *bar; // expected-note 0-1{{declared here}} + template <int *> struct zed {}; // expected-note 0-2{{template parameter is declared here}} + void g(zed<bar>*); +#if __cplusplus < 201103L + // expected-error@-2 {{must have its address taken}} +#else + // expected-error@-4 {{not a constant expression}} expected-note@-4 {{read of non-constexpr variable}} +#endif - int baz; - void g2(zed<baz>*); // expected-error{{must have its address taken}} + int baz; // expected-note 0-1{{declared here}} + void g2(zed<baz>*); +#if __cplusplus < 201103L + // expected-error@-2 {{must have its address taken}} +#elif __cplusplus <= 201402L + // expected-error@-4 {{not a constant expression}} expected-note@-4 {{read of non-const variable}} +#else + // expected-error@-6 {{not implicitly convertible to 'int *'}} +#endif void g3(zed<&baz>*); // okay } @@ -78,9 +102,9 @@ namespace pointer_to_object_parameters { // 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 <int& N> struct S0 { }; // expected-note 0-3{{template parameter is declared here}} + template <const int& N> struct S1 { }; // expected-note 0-2{{template parameter is declared here}} + template <volatile int& N> struct S2 { }; // expected-note 0-2{{template parameter is declared here}} template <const volatile int& N> struct S3 { }; int i; extern const int ci; @@ -88,19 +112,19 @@ namespace reference_parameters { extern const volatile int cvi; void test() { S0<i> s0; - S0<ci> s0c; // expected-error{{reference binding of non-type template parameter of type 'int &' to template argument of type '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}} + S0<ci> s0c; // expected-error{{type 'const int'}} + S0<vi> s0v; // expected-error{{type 'volatile int'}} + S0<cvi> s0cv; // expected-error{{type 'const volatile int'}} 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}} + S1<vi> s1v; // expected-error{{type 'volatile int'}} + S1<cvi> s1cv; // expected-error{{type 'const volatile int'}} 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<ci> s2c; // expected-error{{type 'const int'}} 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}} + S2<cvi> s2cv; // expected-error{{type 'const volatile int'}} S3<i> s3; S3<ci> s3c; @@ -125,9 +149,12 @@ namespace reference_parameters { } namespace PR6749 { - template <int& i> struct foo {}; // expected-note{{template parameter is declared here}} + template <int& i> struct foo {}; // expected-note 0-1{{template parameter is declared here}} int x, &y = x; - foo<y> f; // expected-error{{is not an object}} + foo<y> f; +#if __cplusplus <= 201402L + // expected-error@-2 {{is not an object}} +#endif } } @@ -138,16 +165,21 @@ namespace reference_parameters { // 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}} + template<int (*)(int)> struct X0 { }; // expected-note 0-3{{template parameter is declared here}} int f(int); int f(float); int g(float); - int (*funcptr)(int); + int (*funcptr)(int); // expected-note 0-1{{declared here}} 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}} + void x0c(X0<g>); // expected-error-re{{type 'int (float)' {{.*}}convert{{.*}} 'int (*)(int)'}} + void x0d(X0<&g>); // expected-error-re{{type 'int (*)(float)' {{.*}}convert{{.*}} 'int (*)(int)'}} + void x0e(X0<funcptr>); +#if __cplusplus < 201103L + // expected-error@-2 {{must have its address taken}} +#else + // expected-error@-4 {{not a constant expression}} expected-note@-4 {{read of non-constexpr variable}} +#endif } // -- For a non-type template-parameter of type reference to function, no @@ -155,16 +187,23 @@ namespace pointer_to_function { // 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}} + template<int (&)(int)> struct X0 { }; // expected-note 0-4{{template parameter is declared here}} int f(int); int f(float); int g(float); int (*funcptr)(int); void x0a(X0<f>); +#if __cplusplus <= 201402L 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)'}} +#else + void x0b(X0<&f>); // expected-error{{value of type '<overloaded function type>' is not implicitly convertible to 'int (&)(int)'}} + void x0c(X0<g>); // expected-error{{value of type 'int (float)' is not implicitly convertible to 'int (&)(int)'}} + void x0d(X0<&g>); // expected-error{{value of type 'int (*)(float)' is not implicitly convertible to 'int (&)(int)'}} + void x0e(X0<funcptr>); // expected-error{{value of type 'int (*)(int)' is not implicitly convertible to 'int (&)(int)'}} +#endif } // -- 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 @@ -181,10 +220,10 @@ namespace pointer_to_member_function { float h(float); }; - template<int (Y::*)(int)> struct X0 {}; // expected-note{{template parameter is declared here}} + template<int (Y::*)(int)> struct X0 {}; // expected-note 0-1{{template parameter is declared here}} X0<&Y::f> x0a; X0<&Y::g> x0b; - X0<&Y::h> x0c; // expected-error-re{{non-type template argument of type 'float (pointer_to_member_function::Y::*)(float){{( __attribute__\(\(thiscall\)\))?}}' cannot be converted to a value of type 'int (pointer_to_member_function::Y::*)(int){{( __attribute__\(\(thiscall\)\))?}}'}} + X0<&Y::h> x0c; // expected-error-re{{type 'float (pointer_to_member_function::Y::*)(float){{( __attribute__\(\(thiscall\)\))?}}' {{.*}} convert{{.*}} 'int (pointer_to_member_function::Y::*)(int){{( __attribute__\(\(thiscall\)\))?}}'}} } // -- For a non-type template-parameter of type pointer to data member, @@ -195,9 +234,14 @@ 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}} + template<int Y::*> struct X0 {}; // expected-note 0-1{{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::*'}} + X0<&Y::x> x0b; +#if __cplusplus <= 201402L + // expected-error@-2 {{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::*'}} +#else + // expected-error@-4 {{conversion from 'int pointer_to_member_data::X::*' to 'int pointer_to_member_data::Y::*' is not allowed in a converted constant expression}} +#endif // Test qualification conversions template<const int Y::*> struct X1 {}; diff --git a/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp b/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp index aa1e2d443fddb..52fbd94574229 100644 --- a/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp +++ b/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp @@ -2,7 +2,10 @@ 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}} - +template<int ...Values> // expected-note {{non-deducible}} +struct X1<0, Values+1 ...>; // expected-error{{contains a template parameter that cannot be deduced}} +template<typename T, int ...Values> struct X2; // expected-note {{here}} +template<int ...Values> struct X2<X1<Values...>, Values+1 ...> {}; // ok (DR1315) +X2<X1<1, 2, 3>, 2, 3, 4> x2; // ok +X2<X1<1, 2, 3>, 2, 3, 4, 5> x3; // expected-error {{undefined template}} diff --git a/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp b/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp index 2651f9942091a..388a80ee765c8 100644 --- a/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp +++ b/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp @@ -21,15 +21,16 @@ template<template<typename> class...X> int v4<X...>; template<typename Outer> struct X { template<typename Inner> static int y; - template<typename Inner> static int y<Outer>; // expected-warning {{cannot be deduced}} expected-note {{'Inner'}} + // FIXME: It would be preferable to only diagnose this once. + template<typename Inner> static int y<Outer>; // expected-error 3{{cannot be deduced}} expected-note 3{{'Inner'}} template<typename Inner> static int y<Inner>; // expected-error {{does not specialize}} + + template<typename, int> static int z; + template<Outer N> static int z<int, N>; // expected-error {{not implicitly convertible}} }; -template<typename Outer> template<typename Inner> int X<Outer>::y<Outer>; // expected-warning {{cannot be deduced}} expected-note {{'Inner'}} +template<typename Outer> template<typename Inner> int X<Outer>::y<Outer>; // expected-error {{cannot be deduced}} expected-note {{'Inner'}} template<typename Outer> template<typename Inner> int X<Outer>::y<Inner>; // expected-error {{does not specialize}} +template<> template<typename Inner> int X<int>::y<Inner>; // expected-error {{does not specialize}} expected-note {{instantiation of}} -// FIXME: Merging this with the above class causes an assertion failure when -// instantiating one of the bogus partial specializations. -template<typename Outer> struct Y { - template<typename Inner> static int y; -}; -template<> template<typename Inner> int Y<int>::y<Inner>; // expected-error {{does not specialize}} +X<int> xi; +X<int*> xf; // expected-note {{instantiation of}} diff --git a/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp b/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp index 215f48d9d8e60..332357bb36a82 100644 --- a/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp +++ b/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp @@ -28,4 +28,4 @@ X2& get_X2() { return X0<X2>::value; // expected-note{{instantiation}} } -template<typename T> T x; // expected-warning{{variable templates are a C++14 extension}} +template<typename T> T x; // expected-warning 0-1{{variable templates are a C++14 extension}} diff --git a/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/test/CXX/temp/temp.decls/temp.friend/p1.cpp index 640d03d4c96f0..f1f3f7016242c 100644 --- a/test/CXX/temp/temp.decls/temp.friend/p1.cpp +++ b/test/CXX/temp/temp.decls/temp.friend/p1.cpp @@ -174,7 +174,7 @@ namespace test7 { // This shouldn't crash. template <class T> class D { - friend class A; // expected-error {{elaborated type refers to a template}} + friend class A; // expected-error {{template 'A' cannot be referenced with a class specifier}} }; template class D<int>; } diff --git a/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp b/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp index a466be0a61de9..a990c82564aa4 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp @@ -108,10 +108,10 @@ namespace PR9021b { namespace PartialSpecialization { template<typename T, typename U, typename V = U> - struct X0; // expected-note{{template is declared here}} + struct X0; // expected-note 2{{template is declared here}} template<typename ...Ts> - struct X0<Ts...> { + struct X0<Ts...> { // expected-error {{class template partial specialization is not more specialized than the primary template}} }; X0<int> x0i; // expected-error{{too few template arguments for class template 'X0'}} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp index 9fd3df59d103e..f7103a33cc72d 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp @@ -32,8 +32,11 @@ namespace PR6707 { static const unsigned char ten = 10; template<typename T, T Value, typename U> void f2(X<T, Value>, X<U, Value>); + // expected-note@-1 {{candidate template ignored: deduced values of conflicting types for parameter 'Value' (10 of type 'int' vs. 10 of type 'char')}} + // expected-note@-2 {{candidate template ignored: deduced values of conflicting types for parameter 'Value' (10 of type 'char' vs. 10 of type 'int')}} void g2() { - f2(X<int, 10>(), X<char, ten>()); + f2(X<int, 10>(), X<char, ten>()); // expected-error {{no matching}} + f2(X<char, 10>(), X<int, ten>()); // expected-error {{no matching}} } } diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp index 132d61814227a..e7b665a341371 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p4.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s namespace PR8598 { template<class T> struct identity { typedef T type; }; @@ -19,3 +19,38 @@ namespace PR12132 { fun(&A::x); } } + +#if __cplusplus > 201402L +namespace noexcept_conversion { + template<typename R> void foo(R()); + template<typename R> void bar(R()) = delete; + template<typename R> void bar(R() noexcept) {} + void f() throw() { + foo(&f); + bar(&f); + } + // There is no corresponding rule for references. + // We consider this to be a defect, and allow deduction to succeed in this + // case. FIXME: Check this should be accepted once the DR is resolved. + template<typename R> void baz(R(&)()); + void g() { + baz(f); + } + + // But there is one for member pointers. + template<typename R, typename C, typename ...A> void quux(R (C::*)(A...)); + struct Q { void f(int, char) noexcept { quux(&Q::f); } }; + + void g1() noexcept; + void g2(); + template <class T> int h(T *, T *); // expected-note {{deduced conflicting types for parameter 'T' ('void () noexcept' vs. 'void ()')}} + int x = h(g1, g2); // expected-error {{no matching function}} + + // FIXME: It seems like a defect that B is not deducible here. + template<bool B> int i(void () noexcept(B)); // expected-note 2{{couldn't infer template argument 'B'}} + int i1 = i(g1); // expected-error {{no matching function}} + int i2 = i(g2); // expected-error {{no matching function}} +} +#else +// expected-no-diagnostics +#endif diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp index 4dca820c1929c..b45ed96d14456 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only %s +// RUN: %clang_cc1 -fsyntax-only %s -verify struct AnyT { template<typename T> @@ -11,34 +11,54 @@ void test_cvqual_ref(AnyT 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; + operator T***() const { + T x = 0; // expected-note 2{{declared const here}} + x = 0; // expected-error 2{{const-qualified type}} + T ***p; + return p; } }; struct X { }; void test_deduce_with_qual(AnyThreeLevelPtr a3) { - int * const * const * const ip = a3; + int * const * const * const ip1 = a3; + // FIXME: This is wrong; we are supposed to deduce 'T = int' here. + const int * const * const * const ip2 = a3; // expected-note {{instantiation of}} + // This one is correct, though. + const double * * * ip3 = a3; // expected-note {{instantiation of}} } 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) + // This is correct: we don't need a qualification conversion here, so we + // deduce 'T = const float'. + T x = 0; // expected-note {{declared const here}} + x = 0; // expected-error {{const-qualified type}} return 0; } }; void test_deduce_ptrmem_with_qual(AnyPtrMem apm) { - const float X::* pm = apm; + const float X::* pm = apm; // expected-note {{instantiation of}} +} + +struct TwoLevelPtrMem { + template<typename Class1, typename Class2, typename T> + operator T Class1::*Class2::*() const + { + T x = 0; // expected-note 2{{declared const here}} + x = 0; // expected-error 2{{const-qualified type}} + return 0; + } +}; + +void test_deduce_two_level_ptrmem_with_qual(TwoLevelPtrMem apm) { + // FIXME: This is wrong: we should deduce T = 'float' + const float X::* const X::* pm2 = apm; // expected-note {{instantiation of}} + // This is correct: we don't need a qualification conversion, so we directly + // deduce T = 'const double' + const double X::* X::* pm1 = apm; // expected-note {{instantiation of}} } diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p5.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p5.cpp new file mode 100644 index 0000000000000..8821d538dcbed --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p5.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +template<typename T, bool B> using Fn = T () noexcept(B); + +// - If the original A is a function pointer type, A can be "pointer to +// function" even if the deduced A is "pointer to noexcept function". +struct A { + template<typename T> operator Fn<T, false>*(); // expected-note {{candidate}} +}; +struct B { + template<typename T> operator Fn<T, true>*(); +}; +void (*p1)() = A(); +void (*p2)() = B(); +void (*p3)() noexcept = A(); // expected-error {{no viable conversion}} +void (*p4)() noexcept = B(); + +// - If the original A is a pointer to member function type, A can be "pointer +// to member of type function" even if the deduced A is "pointer to member of +// type noexcept function". +struct C { + template<typename T> operator Fn<T, false> A::*(); // expected-note {{candidate}} +}; +struct D { + template<typename T> operator Fn<T, true> A::*(); +}; +void (A::*q1)() = C(); +void (A::*q2)() = D(); +void (A::*q3)() noexcept = C(); // expected-error {{no viable conversion}} +void (A::*q4)() noexcept = D(); + +// There is no corresponding rule for references. +// FIXME: This seems like a defect. +// FIXME: We don't actually implement the final check for equal types at all! +// Instead, we handle the matching via [over.ics.user]p3: +// "If the user-defined conversion is specified by a specialization of a +// conversion function template, the second standard conversion sequence +// shall have exact match rank." +// Note that this *does* allow discarding noexcept, since that conversion has +// Exact Match rank. +struct E { + template<typename T> operator Fn<T, false>&(); // expected-note {{candidate}} +}; +struct F { + template<typename T> operator Fn<T, true>&(); +}; +void (&r1)() = E(); +void (&r2)() = F(); +void (&r3)() noexcept = E(); // expected-error {{no viable conversion}} +void (&r4)() noexcept = F(); + +// FIXME: We reject this for entirely the wrong reason. We incorrectly succeed +// in deducing T = void, U = G::B, and only fail due to [over.ics.user]p3. +struct G { + template<typename, typename> struct A {}; + template<typename U> struct A<U, int> : A<U, void> {}; + struct B { typedef int type; }; + + template<typename T, typename U = B> operator A<T, typename U::type> *(); // expected-note {{candidate function [with T = void, U = G::B]}} +}; +G::A<void, void> *g = G(); // expected-error {{no viable conversion}} diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp index b807a0ff9f112..54a54b0c486b6 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp @@ -32,7 +32,7 @@ namespace PackExpansionNotAtEnd { 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 cannot be deduced; this partial specialization will never be used}} + struct UselessPartialSpec<Types..., Tail>; // expected-error{{class template partial specialization contains template parameters that cannot be deduced; this partial specialization will never be used}} } namespace DeduceNonTypeTemplateArgsInArray { diff --git a/test/CXX/temp/temp.spec/no-body.cpp b/test/CXX/temp/temp.spec/no-body.cpp index 4ec18fdf820f4..6d1b82fe1898a 100644 --- a/test/CXX/temp/temp.spec/no-body.cpp +++ b/test/CXX/temp/temp.spec/no-body.cpp @@ -43,7 +43,7 @@ namespace good { // Only good in C++98/03 namespace unsupported { #ifndef FIXING - template struct y; // expected-error {{elaborated type refers to a template}} + template struct y; // expected-error {{template 'y' cannot be referenced with a struct specifier}} #endif } diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp index d12feeff0bbca..ec2e380864bff 100644 --- a/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp +++ b/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp @@ -223,8 +223,8 @@ namespace spec_vs_expl_inst { namespace SID { template <typename STRING_TYPE> class BasicStringPiece; - template <> class BasicStringPiece<int> { }; - template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} + template <> class BasicStringPiece<int> { }; // expected-note {{previous template specialization is here}} + template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} expected-warning {{has no effect}} extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} } @@ -252,8 +252,8 @@ namespace spec_vs_expl_inst { 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>; + template <> class BasicStringPiece<int> { }; // expected-note {{previous}} + template class BasicStringPiece<int>; // expected-warning {{has no effect}} } // The same again, with a defined template class. @@ -267,8 +267,8 @@ namespace spec_vs_expl_inst { namespace SID_WithDefinedTemplate { template <typename STRING_TYPE> class BasicStringPiece {}; - template <> class BasicStringPiece<int> { }; - template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} + template <> class BasicStringPiece<int> { }; // expected-note {{previous}} + template class BasicStringPiece<int>; // expected-note {{explicit instantiation definition is here}} expected-warning {{has no effect}} extern template class BasicStringPiece<int>; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} } @@ -283,7 +283,7 @@ namespace spec_vs_expl_inst { 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>'}} + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'BasicStringPiece<int>'}} } namespace DIS_WithDefinedTemplate { @@ -304,23 +304,23 @@ namespace spec_vs_expl_inst { 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-note {{previous}} + template class BasicStringPiece<int>; // expected-note {{previous explicit instantiation is here}} expected-warning {{has no effect}} 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>'}} + template <> class BasicStringPiece<int> { }; // expected-note {{previous definition is here}} expected-note {{previous}} + template class BasicStringPiece<int>; // expected-warning {{has no effect}} + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of '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>'}} + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'BasicStringPiece<int>'}} } namespace SDIS { @@ -328,7 +328,7 @@ namespace spec_vs_expl_inst { 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>'}} + template <> class BasicStringPiece<int> { }; // expected-error {{redefinition of 'BasicStringPiece<int>'}} } } diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp index 772aef6b585a4..ac040ccb3d645 100644 --- a/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp @@ -1,6 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s // RUN: %clang_cc1 -fsyntax-only -verify %s -struct IntHolder { // expected-note{{here}} // expected-note 2{{candidate constructor (the implicit copy constructor)}} +struct IntHolder { // expected-note 0-1{{here}} expected-note 2-4{{candidate constructor (the implicit}} IntHolder(int); // expected-note 2{{candidate constructor}} }; @@ -12,8 +14,13 @@ struct X { // expected-note{{here}} void g() { } - struct Inner { // expected-error{{implicit default}} + struct Inner { +#if __cplusplus >= 201103L + T value; // expected-note {{has no default constructor}} +#else + // expected-error@-4 {{implicit default}} T value; // expected-note {{member is declared here}} +#endif }; static T value; @@ -26,7 +33,12 @@ 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}} + X<IntHolder, int>::Inner inner; +#if __cplusplus >= 201103L + // expected-error@-2 {{call to implicitly-deleted}} +#else + // expected-note@-4 {{first required here}} +#endif return X<IntHolder, int>::value; // expected-note{{instantiation}} } diff --git a/test/CXX/temp/temp.spec/temp.explicit/p4.cpp b/test/CXX/temp/temp.spec/temp.explicit/p4.cpp index 09c428e01df3b..0a8a0ce9ff18e 100644 --- a/test/CXX/temp/temp.spec/temp.explicit/p4.cpp +++ b/test/CXX/temp/temp.spec/temp.explicit/p4.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s template<typename T> void f0(T); // expected-note{{here}} template void f0(int); // expected-error{{explicit instantiation of undefined function template}} @@ -17,19 +18,19 @@ template void X0<int>::f1(); // expected-error{{explicit instantiation of undefi 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 f0(long); // expected-warning{{explicit instantiation of 'f0<long>' that occurs after an explicit specialization has no effect}} 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 void X0<long>::f1(); // expected-warning{{explicit instantiation of 'f1' that occurs after an explicit specialization has no effect}} 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 struct X0<long>::Inner; // expected-warning{{explicit instantiation of 'Inner' that occurs after an explicit specialization has no effect}} 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 long X0<long>::value; // expected-warning{{explicit instantiation of 'value' that occurs after an explicit specialization has no effect}} 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}} +template struct X0<double>; // expected-warning{{explicit instantiation of 'X0<double>' that occurs after an explicit specialization has no effect}} // PR 6458 namespace test0 { @@ -43,6 +44,6 @@ namespace test0 { // inappropriately instantiating this template. void *ptr = x; } - extern template class foo<char>; // expected-warning {{extern templates are a C++11 extension}} + extern template class foo<char>; // expected-warning 0-1{{extern templates are a C++11 extension}} template class foo<char>; } diff --git a/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp b/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp index 38dc367b227eb..9bdccc8e73246 100644 --- a/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp +++ b/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-optzns -emit-llvm -std=c++11 -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -O1 -disable-llvm-passes -emit-llvm -std=c++11 -o - %s | FileCheck %s template<typename T> struct X0 { |
