diff options
Diffstat (limited to 'test/CXX')
30 files changed, 687 insertions, 82 deletions
diff --git a/test/CXX/class.access/class.friend/p1.cpp b/test/CXX/class.access/class.friend/p1.cpp index b6a1bcdab926..b335b0a8c884 100644 --- a/test/CXX/class.access/class.friend/p1.cpp +++ b/test/CXX/class.access/class.friend/p1.cpp @@ -11,12 +11,11 @@ // friends members of the befriending class. struct S { static void f(); }; // expected-note 2 {{'S' declared here}} -S* g() { return 0; } +S* g() { return 0; } // expected-note 2 {{'g' declared here}} struct X { friend struct S; - friend S* g(); // expected-note 2 {{'g' declared here}} - // FIXME: The above two notes would be better attached to line 11. + friend S* g(); }; void test1() { diff --git a/test/CXX/class.access/class.friend/p11.cpp b/test/CXX/class.access/class.friend/p11.cpp index 0d25c59c9b62..0deead19a0fb 100644 --- a/test/CXX/class.access/class.friend/p11.cpp +++ b/test/CXX/class.access/class.friend/p11.cpp @@ -19,17 +19,16 @@ namespace test1 { } namespace test2 { - void bar(); // expected-note {{'::test2::bar' declared here}} + void bar(); // expected-note 3{{'::test2::bar' declared here}} - void foo() { // expected-note {{'::test2::foo' declared here}} + void foo() { // expected-note 2{{'::test2::foo' declared here}} struct S1 { friend void foo(); // expected-error {{no matching function 'foo' found in local scope; did you mean '::test2::foo'?}} }; void foo(); // expected-note {{local declaration nearly matches}} struct S2 { - friend void foo(); // expected-note{{'::test2::foo' declared here}} - // TODO: the above note should go on line 24 + friend void foo(); }; { @@ -47,8 +46,6 @@ namespace test2 { struct S4 { friend void bar(); // expected-error {{no matching function 'bar' found in local scope; did you mean '::test2::bar'?}} - // expected-note@-1 {{'::test2::bar' declared here}} - // TODO: the above note should go on line 22 }; { void bar(); } @@ -81,8 +78,6 @@ namespace test2 { struct S9 { struct Inner { friend void baz(); // expected-error {{no matching function 'baz' found in local scope; did you mean 'bar'?}} - // expected-note@-1 {{'::test2::bar' declared here}} - // TODO: the above note should go on line 22 }; }; diff --git a/test/CXX/class.access/class.friend/p3-cxx0x.cpp b/test/CXX/class.access/class.friend/p3-cxx0x.cpp index 5a1ab49321d0..9aabdbe540a6 100644 --- a/test/CXX/class.access/class.friend/p3-cxx0x.cpp +++ b/test/CXX/class.access/class.friend/p3-cxx0x.cpp @@ -52,14 +52,25 @@ struct { // Ill-formed int friend; // expected-error {{'friend' must appear first in a non-function declaration}} unsigned friend int; // expected-error {{'friend' must appear first in a non-function declaration}} - const volatile friend int; // expected-error {{'friend' must appear first in a non-function declaration}} + const volatile friend int; // expected-error {{'friend' must appear first in a non-function declaration}} \ + // expected-error {{'const' is invalid in friend declarations}} \ + // expected-error {{'volatile' is invalid in friend declarations}} int friend; // expected-error {{'friend' must appear first in a non-function declaration}} + friend const int; // expected-error {{'const' is invalid in friend declarations}} + friend volatile int; // expected-error {{'volatile' is invalid in friend declarations}} + template <typename T> friend const class X; // expected-error {{'const' is invalid in friend declarations}} + // C++ doesn't have restrict and _Atomic, but they're both the same sort + // of qualifier. + typedef int *PtrToInt; + friend __restrict PtrToInt; // expected-error {{'restrict' is invalid in friend declarations}} \ + // expected-error {{restrict requires a pointer or reference}} + friend _Atomic int; // expected-error {{'_Atomic' is invalid in friend declarations}} // OK int friend foo(void); + const int friend foo2(void); friend int; - friend const volatile int; friend float; diff --git a/test/CXX/class.derived/class.abstract/p16.cpp b/test/CXX/class.derived/class.abstract/p16.cpp index 80396a96d9ec..fe31b7321bd0 100644 --- a/test/CXX/class.derived/class.abstract/p16.cpp +++ b/test/CXX/class.derived/class.abstract/p16.cpp @@ -44,8 +44,8 @@ struct G : D {}; // expected-error@-3 {{deleted function 'operator=' cannot override a non-deleted function}} // expected-note@-4 {{while declaring the implicit move assignment operator for 'G'}} // expected-note@-5 {{move assignment operator of 'G' is implicitly deleted because base class 'D' has an inaccessible move assignment operator}} -struct H : D { - H &operator=(H&&) = default; +struct H : D { // expected-note {{deleted because base class 'D' has an inaccessible move assignment}} + H &operator=(H&&) = default; // expected-warning {{implicitly deleted}} // 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/class.friend/p1.cpp b/test/CXX/class/class.friend/p1.cpp index 037fc3dadb96..08498c07330e 100644 --- a/test/CXX/class/class.friend/p1.cpp +++ b/test/CXX/class/class.friend/p1.cpp @@ -51,9 +51,9 @@ class A { friend class A::AInner; // this is okay as an extension friend class AInner; // okay, refers to ::AInner - friend void Derived::missing_member(); // expected-error {{no function named 'missing_member' with type 'void ()' was found in the specified scope}} + friend void Derived::missing_member(); // expected-error {{friend declaration of 'missing_member' does not match any declaration in 'Derived'}} - friend void Derived::base_member(); // expected-error {{no function named 'base_member' with type 'void ()' was found in the specified scope}} + friend void Derived::base_member(); // expected-error {{friend declaration of 'base_member' does not match any declaration in 'Derived'}} friend int Base::typedeffed_member(); // okay: should look through typedef diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp index 49c418a68764..43de9343bd4d 100644 --- a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp @@ -32,6 +32,35 @@ void g() { // OK, warning suppressed. (void)fp(); } + +namespace PR31526 { +typedef E (*fp1)(); +typedef S (*fp2)(); + +typedef S S_alias; +typedef S_alias (*fp3)(); + +typedef fp2 fp2_alias; + +void f() { + fp1 one; + fp2 two; + fp3 three; + fp2_alias four; + + one(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + two(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + three(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + four(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + // These are all okay because of the explicit cast to void. + (void)one(); + (void)two(); + (void)three(); + (void)four(); +} +} // namespace PR31526 + #ifdef EXT // expected-warning@4 {{use of the 'nodiscard' attribute is a C++17 extension}} // expected-warning@8 {{use of the 'nodiscard' attribute is a C++17 extension}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp index 3986dc9565c3..ffc408cddbf4 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions %s -// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y %s +// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions -Werror=c++2a-extensions %s +// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y -Werror=c++2a-extensions %s +// RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++2a -DCXX1Y -DCXX2A %s namespace N { typedef char C; @@ -78,7 +79,12 @@ struct T2 { }; struct T3 { constexpr T3 &operator=(const T3&) const = default; - // expected-error@-1 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}} +#ifndef CXX2A + // expected-error@-2 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}} +#else + // expected-warning@-4 {{explicitly defaulted copy assignment operator is implicitly deleted}} + // expected-note@-5 {{function is implicitly deleted because its declared type does not match the type of an implicit copy assignment operator}} +#endif }; #endif struct U { @@ -129,9 +135,22 @@ constexpr int DisallowedStmtsCXX1Y_2() { x: return 0; } +constexpr int DisallowedStmtsCXX1Y_2_1() { + try { + return 0; + } catch (...) { + merp: goto merp; // expected-error {{statement not allowed in constexpr function}} + } +} constexpr int DisallowedStmtsCXX1Y_3() { // - a try-block, - try {} catch (...) {} // expected-error {{statement not allowed in constexpr function}} + try {} catch (...) {} +#ifndef CXX2A + // expected-error@-2 {{use of this statement in a constexpr function is a C++2a extension}} +#ifndef CXX1Y + // expected-error@-4 {{use of this statement in a constexpr function is a C++14 extension}} +#endif +#endif return 0; } constexpr int DisallowedStmtsCXX1Y_4() { diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp index 9c1cab54b617..54aabe6ef376 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions %s -// RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y %s +// RUN: %clang_cc1 -verify -std=c++11 -fcxx-exceptions -Werror=c++1y-extensions -Werror=c++2a-extensions %s +// RUN: %clang_cc1 -verify -std=c++1y -fcxx-exceptions -DCXX1Y -Werror=c++2a-extensions %s +// RUN: %clang_cc1 -verify -std=c++2a -fcxx-exceptions -DCXX1Y -DCXX2A %s namespace N { typedef char C; @@ -49,8 +50,14 @@ namespace IndirectVBase { // - its function-body shall not be a function-try-block; struct U { constexpr U() - try // expected-error {{function try block not allowed in constexpr constructor}} + try +#ifndef CXX2A + // expected-error@-2 {{function try block in constexpr constructor is a C++2a extension}} +#endif : u() { +#ifndef CXX1Y + // expected-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}} +#endif } catch (...) { throw; } diff --git a/test/CXX/dcl.decl/dcl.decomp/p3.cpp b/test/CXX/dcl.decl/dcl.decomp/p3.cpp index b7092e3af023..b3f0cf187446 100644 --- a/test/CXX/dcl.decl/dcl.decomp/p3.cpp +++ b/test/CXX/dcl.decl/dcl.decomp/p3.cpp @@ -36,7 +36,7 @@ void no_get_2() { auto [a0, a1, a2] = A(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit initialization of binding declaration 'a0'}} } -template<int> float &get(A); +template<int> float &get(A); // expected-note 2 {{no known conversion}} 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}} @@ -57,7 +57,7 @@ void no_tuple_element_3() { 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> auto get(B) -> int (&)[N + 1]; // expected-note 2 {{no known conversion}} 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> {}; @@ -138,19 +138,25 @@ int member_get() { return c; } -struct D { template<int> struct get {}; }; // expected-note {{declared here}} +struct D { + // FIXME: Emit a note here explaining why this was ignored. + template<int> struct get {}; +}; 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}} + auto [d] = D(); // expected-error {{no matching function for call to 'get'}} expected-note {{in implicit init}} } -struct E { int get(); }; +struct E { + // FIXME: Emit a note here explaining why this was ignored. + 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}} + auto [e] = E(); // expected-error {{no matching function for call to 'get'}} expected-note {{in implicit init}} } namespace ADL { @@ -230,3 +236,62 @@ namespace constant { } static_assert(g() == 4); // expected-error {{constant}} expected-note {{in call to 'g()'}} } + +// P0961R1 +struct InvalidMemberGet { + int get(); + template <class T> int get(); + struct get {}; +}; +template <> struct std::tuple_size<InvalidMemberGet> { static constexpr size_t value = 1; }; +template <> struct std::tuple_element<0, InvalidMemberGet> { typedef float type; }; +template <size_t> float get(InvalidMemberGet) { return 0; } +int f() { + InvalidMemberGet img; + auto [x] = img; + typedef decltype(x) same_as_float; + typedef float same_as_float; +} + +struct ValidMemberGet { + int get(); + template <class T> int get() { return 0; } + template <size_t N> float get() { return 0; } +}; +template <> struct std::tuple_size<ValidMemberGet> { static constexpr size_t value = 1; }; +template <> struct std::tuple_element<0, ValidMemberGet> { typedef float type; }; +// Don't use this one; we should use the member get. +template <size_t N> int get(ValidMemberGet) { static_assert(N && false, ""); } +int f2() { + ValidMemberGet img; + auto [x] = img; + typedef decltype(x) same_as_float; + typedef float same_as_float; +} + +struct Base1 { + int get(); // expected-note{{member found by ambiguous name lookup}} +}; +struct Base2 { + template<int> int get(); // expected-note{{member found by ambiguous name lookup}} +}; +struct Derived : Base1, Base2 {}; + +template <> struct std::tuple_size<Derived> { static constexpr size_t value = 1; }; +template <> struct std::tuple_element<0, Derived> { typedef int type; }; + +auto [x] = Derived(); // expected-error{{member 'get' found in multiple base classes of different types}} + +struct Base { + template<int> int get(); +}; +struct UsingGet : Base { + using Base::get; +}; + +template <> struct std::tuple_size<UsingGet> { + static constexpr size_t value = 1; +}; +template <> struct std::tuple_element<0, UsingGet> { typedef int type; }; + +auto [y] = UsingGet(); diff --git a/test/CXX/dcl.decl/dcl.decomp/p4.cpp b/test/CXX/dcl.decl/dcl.decomp/p4.cpp index c461eb6f54b7..f14c0d02c16e 100644 --- a/test/CXX/dcl.decl/dcl.decomp/p4.cpp +++ b/test/CXX/dcl.decl/dcl.decomp/p4.cpp @@ -20,15 +20,15 @@ namespace NonPublicMembers { int a; // expected-note 2{{declared private here}} }; - struct NonPublic3 : private A {}; // expected-note {{constrained by private inheritance}} + struct NonPublic3 : private A {}; // expected-note {{declared private here}} 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'}} + auto [a1] = NonPublic1(); // expected-error {{cannot decompose protected member 'a' of 'NonPublicMembers::NonPublic1'}} + auto [a2] = NonPublic2(); // expected-error {{cannot decompose private member 'a' of 'NonPublicMembers::NonPublic2'}} + auto [a3] = NonPublic3(); // expected-error {{cannot decompose members of inaccessible base class 'A' of 'NonPublicMembers::NonPublic3'}} + auto [a4] = NonPublic4(); // expected-error {{cannot decompose private member 'a' of 'NonPublicMembers::NonPublic2'}} } } @@ -198,3 +198,44 @@ namespace std_example { same<decltype((x)), const int&> same1; same<decltype((y)), const volatile double&> same2; } + +namespace p0969r0 { + struct A { + int x; + int y; + }; + struct B : private A { // expected-note {{declared private here}} + void test_member() { + auto &[x, y] = *this; + } + friend void test_friend(B); + }; + void test_friend(B b) { + auto &[x, y] = b; + } + void test_external(B b) { + auto &[x, y] = b; // expected-error {{cannot decompose members of inaccessible base class 'p0969r0::A' of 'p0969r0::B'}} + } + + struct C { + int x; + protected: + int y; // expected-note {{declared protected here}} expected-note {{can only access this member on an object of type 'p0969r0::D'}} + void test_member() { + auto &[x, y] = *this; + } + friend void test_friend(struct D); + }; + struct D : C { + static void test_member(D d, C c) { + auto &[x1, y1] = d; + auto &[x2, y2] = c; // expected-error {{cannot decompose protected member 'y' of 'p0969r0::C'}} + } + }; + void test_friend(D d) { + auto &[x, y] = d; + } + void test_external(D d) { + auto &[x, y] = d; // expected-error {{cannot decompose protected member 'y' of 'p0969r0::C'}} + } +} diff --git a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp index 51993307cfff..3f2bc569edf6 100644 --- a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp +++ b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p1.cpp @@ -1,15 +1,30 @@ // RUN: %clang_cc1 -verify %s -std=c++11 +// RUN: %clang_cc1 -verify %s -std=c++17 +// RUN: %clang_cc1 -verify %s -std=c++2a // A function that is explicitly defaulted shall struct A { // -- be a special member function, A(int) = default; // expected-error {{only special member functions may be defaulted}} + A(A) = default; // expected-error {{must pass its first argument by reference}} // -- have the same declared function type as if it had been implicitly // declared void operator=(const A &) = default; // expected-error {{must return 'A &'}} - A(...) = default; // expected-error {{cannot be variadic}} - A(const A &, ...) = default; // expected-error {{cannot be variadic}} + A(...) = default; + A(const A &, ...) = default; + A &operator=(const A&) const = default; + A &operator=(A) const = default; // expected-error {{must be an lvalue refe}} +#if __cplusplus <= 201703L + // expected-error@-5 {{cannot be variadic}} + // expected-error@-5 {{cannot be variadic}} + // expected-error@-5 {{may not have 'const'}} + // expected-error@-5 {{may not have 'const'}} +#else + // expected-warning@-10 {{implicitly deleted}} expected-note@-10 {{declared type does not match the type of an implicit default constructor}} + // expected-warning@-10 {{implicitly deleted}} expected-note@-10 {{declared type does not match the type of an implicit copy constructor}} + // expected-warning@-10 {{implicitly deleted}} expected-note@-10 {{declared type does not match the type of an implicit copy assignment}} +#endif // (except for possibly differing ref-qualifiers A &operator=(A &&) & = default; @@ -23,3 +38,35 @@ struct A { A(double = 0.0) = default; // expected-error {{cannot have default arguments}} A(const A & = 0) = default; // expected-error {{cannot have default arguments}} }; + +struct A2 { + A2(...); + A2(const A2 &, ...); + A2 &operator=(const A2&) const; +}; +A2::A2(...) = default; // expected-error {{cannot be variadic}} +A2::A2(const A2&, ...) = default; // expected-error {{cannot be variadic}} +A2 &A2::operator=(const A2&) const = default; // expected-error {{may not have 'const'}} + +struct B { + B(B&); + B &operator=(B&); +}; +struct C : B { + C(const C&) = default; + C &operator=(const C&) = default; +#if __cplusplus <= 201703L + // expected-error@-3 {{is const, but a member or base requires it to be non-const}} + // expected-error@-3 {{is const, but a member or base requires it to be non-const}} +#else + // expected-warning@-6 {{implicitly deleted}} expected-note@-6 {{type does not match}} + // expected-warning@-6 {{implicitly deleted}} expected-note@-6 {{type does not match}} +#endif +}; + +struct D : B { // expected-note 2{{base class}} + D(const D&); + D &operator=(const D&); +}; +D::D(const D&) = default; // expected-error {{would delete}} expected-error {{is const, but}} +D &D::operator=(const D&) = default; // expected-error {{would delete}} expected-error {{is const, but}} diff --git a/test/CXX/drs/dr13xx.cpp b/test/CXX/drs/dr13xx.cpp index f193c8e024fb..208ab8a03b0a 100644 --- a/test/CXX/drs/dr13xx.cpp +++ b/test/CXX/drs/dr13xx.cpp @@ -226,10 +226,10 @@ namespace dr1330 { // dr1330: 4 c++11 #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; +#if __cplusplus >= 201103L + E e; // expected-note {{needed here}} +#endif } namespace dr1346 { // dr1346: 3.5 diff --git a/test/CXX/drs/dr1xx.cpp b/test/CXX/drs/dr1xx.cpp index a92501128b5f..26ab67d54d31 100644 --- a/test/CXX/drs/dr1xx.cpp +++ b/test/CXX/drs/dr1xx.cpp @@ -401,13 +401,12 @@ namespace dr136 { // dr136: 3.4 extern "C" void k(int, int, int, int); // expected-note {{previous declaration is here}} namespace NSA { struct A { - friend void dr136::k(int, int, int, int = 0); // expected-error {{friend declaration specifying a default argument must be the only declaration}} \ - // expected-note {{previous declaration is here}} + friend void dr136::k(int, int, int, int = 0); // expected-error {{friend declaration specifying a default argument must be the only declaration}} }; } namespace NSB { struct A { - friend void dr136::k(int, int, int = 0, int); // expected-error {{friend declaration specifying a default argument must be the only declaration}} + friend void dr136::k(int, int, int = 0, int); // expected-error {{missing default argument on parameter}} }; } struct B { diff --git a/test/CXX/drs/dr22xx.cpp b/test/CXX/drs/dr22xx.cpp index 021707d876b7..70a26db757c3 100644 --- a/test/CXX/drs/dr22xx.cpp +++ b/test/CXX/drs/dr22xx.cpp @@ -15,3 +15,14 @@ struct AnonBitfieldQualifiers { const volatile unsigned i3 : 1; }; } + +#if __cplusplus >= 201103L +namespace dr2211 { // dr2211: 8 +void f() { + int a; + auto f = [a](int a) { (void)a; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}} + // expected-note@-1{{variable 'a' is explicitly captured here}} + auto g = [=](int a) { (void)a; }; +} +} +#endif diff --git a/test/CXX/drs/dr2xx.cpp b/test/CXX/drs/dr2xx.cpp index 4e745ef2f4d0..b69c014b587f 100644 --- a/test/CXX/drs/dr2xx.cpp +++ b/test/CXX/drs/dr2xx.cpp @@ -718,7 +718,7 @@ namespace dr261 { // dr261: no A() {} }; - // FIXME: These are ill-formed, with a required diagnostic, for the same + // FIXME: This is ill-formed, with a required diagnostic, for the same // reason. struct B { inline void operator delete(void*) __attribute__((unused)); @@ -726,7 +726,7 @@ namespace dr261 { // dr261: no }; struct C { inline void operator delete(void*) __attribute__((unused)); - virtual ~C() {} + virtual ~C() {} // expected-warning {{'operator delete' was marked unused but was used}} }; struct D { diff --git a/test/CXX/drs/dr5xx.cpp b/test/CXX/drs/dr5xx.cpp index c20a873fc1c7..2099612e23f3 100644 --- a/test/CXX/drs/dr5xx.cpp +++ b/test/CXX/drs/dr5xx.cpp @@ -740,17 +740,17 @@ namespace dr573 { // dr573: no namespace dr574 { // dr574: yes struct A { - A &operator=(const A&) const; // expected-note {{does not match because it is const}} + A &operator=(const A&) const; // expected-note {{different qualifiers}} }; struct B { - B &operator=(const B&) volatile; // expected-note {{nearly matches}} + B &operator=(const B&) volatile; // expected-note {{different qualifiers}} }; #if __cplusplus >= 201103L struct C { - C &operator=(const C&) &; // expected-note {{not viable}} expected-note {{nearly matches}} expected-note {{here}} + C &operator=(const C&) &; // expected-note {{not viable}} expected-note {{candidate}} expected-note {{here}} }; struct D { - D &operator=(const D&) &&; // expected-note {{not viable}} expected-note {{nearly matches}} expected-note {{here}} + D &operator=(const D&) &&; // expected-note {{not viable}} expected-note {{candidate}} expected-note {{here}} }; void test(C c, D d) { c = c; diff --git a/test/CXX/drs/dr6xx.cpp b/test/CXX/drs/dr6xx.cpp index c3c867b7a54d..b4247b22607d 100644 --- a/test/CXX/drs/dr6xx.cpp +++ b/test/CXX/drs/dr6xx.cpp @@ -492,7 +492,13 @@ namespace dr647 { // dr647: yes struct C { constexpr C(NonLiteral); constexpr C(NonLiteral, int) {} // expected-error {{not a literal type}} - constexpr C() try {} catch (...) {} // expected-error {{function try block}} + constexpr C() try {} catch (...) {} +#if __cplusplus <= 201703L + // expected-error@-2 {{function try block in constexpr constructor is a C++2a extension}} +#endif +#if __cplusplus < 201402L + // expected-error@-5 {{use of this statement in a constexpr constructor is a C++14 extension}} +#endif }; struct D { @@ -757,8 +763,8 @@ namespace dr666 { // dr666: yes #if __cplusplus >= 201103L namespace dr667 { // dr667: yes struct A { - A() = default; - int &r; + A() = default; // expected-warning {{explicitly defaulted default constructor is implicitly deleted}} + int &r; // expected-note {{because field 'r' of reference type 'int &' would not be initialized}} }; static_assert(!__is_trivially_constructible(A), ""); @@ -833,7 +839,7 @@ namespace dr673 { // dr673: yes F *f; // expected-error {{unknown type name}} } -namespace dr674 { // dr674: no +namespace dr674 { // dr674: 8 template<typename T> int f(T); int g(int); @@ -843,22 +849,50 @@ namespace dr674 { // dr674: no template<typename T> int h(T); class X { - // FIXME: This should deduce dr674::f<int>. - friend int dr674::f(int); // expected-error {{does not match any}} + friend int dr674::f(int); friend int dr674::g(int); friend int dr674::h<>(int); - int n; + int n; // expected-note 2{{private}} }; template<typename T> int f(T) { return X().n; } int g(int) { return X().n; } - template<typename T> int g(T) { return X().n; } - int h(int) { return X().n; } + template<typename T> int g(T) { return X().n; } // expected-error {{private}} + int h(int) { return X().n; } // expected-error {{private}} template<typename T> int h(T) { return X().n; } template int f(int); - template int g(int); + template int g(int); // expected-note {{in instantiation of}} template int h(int); + + + struct Y { + template<typename T> int f(T); + + int g(int); + template<typename T> int g(T); + + int h(int); + template<typename T> int h(T); + }; + + class Z { + friend int Y::f(int); + friend int Y::g(int); + friend int Y::h<>(int); + int n; // expected-note 2{{private}} + }; + + template<typename T> int Y::f(T) { return Z().n; } + int Y::g(int) { return Z().n; } + template<typename T> int Y::g(T) { return Z().n; } // expected-error {{private}} + int Y::h(int) { return Z().n; } // expected-error {{private}} + template<typename T> int Y::h(T) { return Z().n; } + + // FIXME: Should the <> be required here? + template int Y::f<>(int); + template int Y::g<>(int); // expected-note {{in instantiation of}} + template int Y::h<>(int); } namespace dr675 { // dr675: dup 739 diff --git a/test/CXX/expr/expr.const/p6.cpp b/test/CXX/expr/expr.const/p6.cpp new file mode 100644 index 000000000000..a8fc7754e7db --- /dev/null +++ b/test/CXX/expr/expr.const/p6.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -std=c++17 -verify %s + +template<typename T> int not_constexpr() { return T::error; } +template<typename T> constexpr int is_constexpr() { return T::error; } // expected-error {{'::'}} + +template<typename T> int not_constexpr_var = T::error; +template<typename T> constexpr int is_constexpr_var = T::error; // expected-error {{'::'}} +template<typename T> const int is_const_var = T::error; // expected-error {{'::'}} +template<typename T> const volatile int is_const_volatile_var = T::error; +template<typename T> T is_dependent_var = T::error; // expected-error {{'::'}} +template<typename T> int &is_reference_var = T::error; // expected-error {{'::'}} +template<typename T> float is_float_var = T::error; + +void test() { + // Do not instantiate functions referenced in unevaluated operands... + (void)sizeof(not_constexpr<long>()); + (void)sizeof(is_constexpr<long>()); + (void)sizeof(not_constexpr_var<long>); + (void)sizeof(is_constexpr_var<long>); + (void)sizeof(is_const_var<long>); + (void)sizeof(is_const_volatile_var<long>); + (void)sizeof(is_dependent_var<long>); + (void)sizeof(is_dependent_var<const long>); + (void)sizeof(is_reference_var<long>); + (void)sizeof(is_float_var<long>); + + // ... but do if they are potentially constant evaluated, and refer to + // constexpr functions or to variables usable in constant expressions. + (void)sizeof(int{not_constexpr<int>()}); + (void)sizeof(int{is_constexpr<int>()}); // expected-note {{instantiation of}} + (void)sizeof(int{not_constexpr_var<int>}); + (void)sizeof(int{is_constexpr_var<int>}); // expected-note {{instantiation of}} + (void)sizeof(int{is_const_var<int>}); // expected-note {{instantiation of}} + (void)sizeof(int{is_const_volatile_var<int>}); + (void)sizeof(int{is_dependent_var<int>}); + (void)sizeof(int{is_dependent_var<const int>}); // expected-note {{instantiation of}} + (void)sizeof(int{is_reference_var<int>}); // expected-note {{instantiation of}} + (void)sizeof(int{is_float_var<int>}); // expected-error {{cannot be narrowed}} expected-note {{cast}} +} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp index 551c100ff7af..7fc86e810927 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp @@ -15,8 +15,8 @@ public: void capture_by_copy(NonCopyable nc, NonCopyable &ncr, const NonConstCopy nco) { (void)[nc] { }; // expected-error{{capture of variable 'nc' as type 'NonCopyable' calls private copy constructor}} - (void)[=] { - ncr.foo(); // expected-error{{capture of variable 'ncr' as type 'NonCopyable' calls private copy constructor}} + (void)[=] { // expected-error{{capture of variable 'ncr' as type 'NonCopyable' calls private copy constructor}} + ncr.foo(); }(); [nco] {}(); // expected-error{{no matching constructor for initialization of 'const NonConstCopy'}} diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp index 31213c9ebc33..2bb75df7ac6a 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp @@ -88,8 +88,8 @@ namespace p2 { template<typename R, typename T> void odr_used2(R &r, Boom<T> boom) { const std::type_info &ti - = typeid([=,&r] () -> R& { - boom.tickle(); // expected-note{{in instantiation of member function}} + = typeid([=,&r] () -> R& { // expected-note{{in instantiation of member function 'p2::Boom<float>::Boom' requested here}} + boom.tickle(); return r; }()); } @@ -139,11 +139,11 @@ namespace NonLocalLambdaInstantation { } template<typename T> - struct X2 { + struct X2 { // expected-note{{in instantiation of default member initializer 'NonLocalLambdaInstantation::X2<int *>::x'}} int x = []{ return T(); }(); // expected-error{{cannot initialize a member subobject of type 'int' with an rvalue of type 'int *'}} }; X2<int> x2i; X2<float> x2f; - X2<int*> x2ip; // expected-note{{in instantiation of default member initializer 'NonLocalLambdaInstantation::X2<int *>::x'}} + X2<int*> x2ip; // expected-note {{in evaluation of exception spec}} } diff --git a/test/CXX/special/class.copy/p12-0x.cpp b/test/CXX/special/class.copy/p12-0x.cpp index 1b23b5a4b179..a0ef49d9b64d 100644 --- a/test/CXX/special/class.copy/p12-0x.cpp +++ b/test/CXX/special/class.copy/p12-0x.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -verify %s +// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-defaulted-function-deleted // expected-no-diagnostics diff --git a/test/CXX/special/class.copy/p23-cxx11.cpp b/test/CXX/special/class.copy/p23-cxx11.cpp index ac21cc61a2c5..0b9652b50fcf 100644 --- a/test/CXX/special/class.copy/p23-cxx11.cpp +++ b/test/CXX/special/class.copy/p23-cxx11.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify %s -std=c++11 +// RUN: %clang_cc1 -verify %s -std=c++11 -Wno-defaulted-function-deleted struct Trivial {}; diff --git a/test/CXX/special/class.ctor/p5-0x.cpp b/test/CXX/special/class.ctor/p5-0x.cpp index 061a3d1f0738..5fa61008e8b7 100644 --- a/test/CXX/special/class.ctor/p5-0x.cpp +++ b/test/CXX/special/class.ctor/p5-0x.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -Wno-defaulted-function-deleted struct DefaultedDefCtor1 {}; struct DefaultedDefCtor2 { DefaultedDefCtor2() = default; }; diff --git a/test/CXX/special/class.dtor/p5-0x.cpp b/test/CXX/special/class.dtor/p5-0x.cpp index 595784f0d5f9..f69baca53bf3 100644 --- a/test/CXX/special/class.dtor/p5-0x.cpp +++ b/test/CXX/special/class.dtor/p5-0x.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -std=c++11 %s +// RUN: %clang_cc1 -verify -std=c++11 %s -Wno-defaulted-function-deleted struct NonTrivDtor { ~NonTrivDtor(); diff --git a/test/CXX/special/class.temporary/p6.cpp b/test/CXX/special/class.temporary/p6.cpp new file mode 100644 index 000000000000..077385fb7aaa --- /dev/null +++ b/test/CXX/special/class.temporary/p6.cpp @@ -0,0 +1,240 @@ +// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s --implicit-check-not='call{{.*}}dtor' + +namespace std { + typedef decltype(sizeof(int)) size_t; + + template <class E> + struct initializer_list { + const E *begin; + size_t size; + initializer_list() : begin(nullptr), size(0) {} + }; +} + +void then(); + +struct dtor { + ~dtor(); +}; + +dtor ctor(); + +auto &&lambda = [a = {ctor()}] {}; +// CHECK-LABEL: define +// CHECK: call {{.*}}ctor +// CHECK: call {{.*}}atexit{{.*}}global_array_dtor + +// CHECK-LABEL: define{{.*}}global_array_dtor +// CHECK: call {{.*}}dtor + +// [lifetime extension occurs if the object was obtained by] +// -- a temporary materialization conversion +// CHECK-LABEL: ref_binding +void ref_binding() { + // CHECK: call {{.*}}ctor + auto &&x = ctor(); + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: } +} + +// -- ( expression ) +// CHECK-LABEL: parens +void parens() { + // CHECK: call {{.*}}ctor + auto &&x = ctor(); + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: } +} + +// -- subscripting of an array +// CHECK-LABEL: array_subscript_1 +void array_subscript_1() { + using T = dtor[1]; + // CHECK: call {{.*}}ctor + auto &&x = T{ctor()}[0]; + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: } +} +// CHECK-LABEL: array_subscript_2 +void array_subscript_2() { + using T = dtor[1]; + // CHECK: call {{.*}}ctor + auto &&x = ((dtor*)T{ctor()})[0]; + // CHECK: call {{.*}}dtor + // CHECK: call {{.*}}then + then(); + // CHECK: } +} + +struct with_member { dtor d; ~with_member(); }; +struct with_ref_member { dtor &&d; ~with_ref_member(); }; + +// -- a class member access using the . operator [...] +// CHECK-LABEL: member_access_1 +void member_access_1() { + // CHECK: call {{.*}}ctor + auto &&x = with_member{ctor()}.d; + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}with_member + // CHECK: } +} +// CHECK-LABEL: member_access_2 +void member_access_2() { + // CHECK: call {{.*}}ctor + auto &&x = with_ref_member{ctor()}.d; + // CHECK: call {{.*}}with_ref_member + // CHECK: call {{.*}}dtor + // CHECK: call {{.*}}then + then(); + // CHECK: } +} +// CHECK-LABEL: member_access_3 +void member_access_3() { + // CHECK: call {{.*}}ctor + auto &&x = (&(const with_member&)with_member{ctor()})->d; + // CHECK: call {{.*}}with_member + // CHECK: call {{.*}}then + then(); + // CHECK: } +} + +// -- a pointer-to-member operation using the .* operator [...] +// CHECK-LABEL: member_ptr_access_1 +void member_ptr_access_1() { + // CHECK: call {{.*}}ctor + auto &&x = with_member{ctor()}.*&with_member::d; + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}with_member + // CHECK: } +} +// CHECK-LABEL: member_ptr_access_2 +void member_ptr_access_2() { + // CHECK: call {{.*}}ctor + auto &&x = (&(const with_member&)with_member{ctor()})->*&with_member::d; + // CHECK: call {{.*}}with_member + // CHECK: call {{.*}}then + then(); + // CHECK: } +} + +// -- a [named] cast [...] +// CHECK-LABEL: static_cast +void test_static_cast() { + // CHECK: call {{.*}}ctor + auto &&x = static_cast<dtor&&>(ctor()); + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: } +} +// CHECK-LABEL: const_cast +void test_const_cast() { + // CHECK: call {{.*}}ctor + auto &&x = const_cast<dtor&&>(ctor()); + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: } +} +// CHECK-LABEL: reinterpret_cast +void test_reinterpret_cast() { + // CHECK: call {{.*}}ctor + auto &&x = reinterpret_cast<dtor&&>(static_cast<dtor&&>(ctor())); + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: } +} +// CHECK-LABEL: dynamic_cast +void test_dynamic_cast() { + // CHECK: call {{.*}}ctor + auto &&x = dynamic_cast<dtor&&>(ctor()); + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: } +} + +// -- [explicit cast notation is defined in terms of the above] +// CHECK-LABEL: c_style_cast +void c_style_cast() { + // CHECK: call {{.*}}ctor + auto &&x = (dtor&&)ctor(); + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: } +} +// CHECK-LABEL: function_style_cast +void function_style_cast() { + // CHECK: call {{.*}}ctor + using R = dtor&&; + auto &&x = R(ctor()); + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: } +} + +// -- a conditional operator +// CHECK-LABEL: conditional +void conditional(bool b) { + // CHECK: call {{.*}}ctor + // CHECK: call {{.*}}ctor + auto &&x = b ? (dtor&&)ctor() : (dtor&&)ctor(); + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: call {{.*}}dtor + // CHECK: } +} + +// -- a comma expression +// CHECK-LABEL: comma +void comma() { + // CHECK: call {{.*}}ctor + auto &&x = (true, (dtor&&)ctor()); + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: } +} + + +// This applies recursively: if an object is lifetime-extended and contains a +// reference, the referent is also extended. +// CHECK-LABEL: init_capture_ref +void init_capture_ref() { + // CHECK: call {{.*}}ctor + auto x = [&a = (const dtor&)ctor()] {}; + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: } +} +// CHECK-LABEL: init_capture_ref_indirect +void init_capture_ref_indirect() { + // CHECK: call {{.*}}ctor + auto x = [&a = (const dtor&)ctor()] {}; + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: } +} +// CHECK-LABEL: init_capture_init_list +void init_capture_init_list() { + // CHECK: call {{.*}}ctor + auto x = [a = {ctor()}] {}; + // CHECK: call {{.*}}then + then(); + // CHECK: call {{.*}}dtor + // CHECK: } +} diff --git a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp index 34202494c0d8..f42fc9b6e5aa 100644 --- a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp +++ b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp @@ -108,7 +108,7 @@ void g() { extern int incomplete[]; for (auto a : incomplete) // expected-error {{cannot use incomplete type 'int []' as a range}} ; - extern struct Incomplete also_incomplete[2]; // expected-note {{forward declaration}} + extern struct Incomplete also_incomplete[2]; // expected-note 2{{forward declaration}} for (auto &a : also_incomplete) // expected-error {{cannot use incomplete type 'struct Incomplete [2]' as a range}} ; @@ -150,9 +150,9 @@ void g() { struct NoEnd { null_t begin(); }; - for (auto u : NoBegin()) { // expected-error {{range type 'NoBegin' has 'end' member but no 'begin' member}} + for (auto u : NoBegin()) { // expected-error {{no viable 'begin' function available}} } - for (auto u : NoEnd()) { // expected-error {{range type 'NoEnd' has 'begin' member but no 'end' member}} + for (auto u : NoEnd()) { // expected-error {{no viable 'end' function available}} } struct NoIncr { @@ -271,3 +271,58 @@ namespace rdar13712739 { template void foo(const int&); // expected-note{{in instantiation of function template specialization}} } + +namespace p0962r1 { + namespace NA { + struct A { + void begin(); + }; + int *begin(A); + int *end(A); + } + + namespace NB { + struct B { + void end(); + }; + int *begin(B); + int *end(B); + } + + namespace NC { + struct C { + void begin(); + }; + int *begin(C); + } + + namespace ND { + struct D { + void end(); + }; + int *end(D); + } + + namespace NE { + struct E { + void begin(); // expected-note {{member is not a candidate because range type 'p0962r1::NE::E' has no 'end' member}} + }; + int *end(E); + } + + namespace NF { + struct F { + void end(); // expected-note {{member is not a candidate because range type 'p0962r1::NF::F' has no 'begin' member}} + }; + int *begin(F); + } + + void use(NA::A a, NB::B b, NC::C c, ND::D d, NE::E e, NF::F f) { + for (auto x : a) {} + for (auto x : b) {} + for (auto x : c) {} // expected-error {{no viable 'end' function}} + for (auto x : d) {} // expected-error {{no viable 'begin' function}} + for (auto x : e) {} // expected-error {{no viable 'begin' function}} + for (auto x : f) {} // expected-error {{no viable 'end' function}} + } +} diff --git a/test/CXX/stmt.stmt/stmt.select/p3.cpp b/test/CXX/stmt.stmt/stmt.select/p3.cpp index 7a6a408ec955..4804cc559d00 100644 --- a/test/CXX/stmt.stmt/stmt.select/p3.cpp +++ b/test/CXX/stmt.stmt/stmt.select/p3.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -// RUN: %clang_cc1 -fsyntax-only -std=c++1z -Wc++14-compat -verify %s -DCPP17 +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -std=c++1z -Wc++14-compat -verify %s -DCPP17 int f(); @@ -71,7 +71,6 @@ void whileInitStatement() { // last loop above. It would be nice to remove this. void whileInitStatement2() { while (; false) {} // expected-error {{expected expression}} - // expected-warning@-1 {{expression result unused}} - // expected-error@-2 {{expected ';' after expression}} - // expected-error@-3 {{expected expression}} + // expected-error@-1 {{expected ';' after expression}} + // expected-error@-2 {{expected expression}} } diff --git a/test/CXX/temp/temp.param/p2.cpp b/test/CXX/temp/temp.param/p2.cpp index 656bd26ff08d..c70b1d354f7c 100644 --- a/test/CXX/temp/temp.param/p2.cpp +++ b/test/CXX/temp/temp.param/p2.cpp @@ -8,14 +8,17 @@ template<class T> struct X; template<typename T> struct X; -// typename followed by aqualified-id denotes the type in a non-type +// typename followed by a qualified-id denotes the type in a non-type // parameter-declaration. template<typename T, typename T::type Value> struct Y0; template<typename T, typename X<T>::type Value> struct Y1; +template<typename T typename U> struct Y2; // expected-error{{expected ',' or '>'}} +template<typename T U> struct Y3; // expected-error{{expected a qualified name after 'typename'}} expected-error{{expected ',' or '>'}} +template<typedef T typename U> struct Y4; // expected-error{{expected template parameter}} expected-note {{did you mean to use 'typename'?}} expected-error{{expected ',' or '>'}} // A storage class shall not be specified in a template-parameter declaration. template<static int Value> struct Z; //expected-error{{invalid declaration specifier}} -template<typedef int Value> struct Z0; //expected-error{{expected template parameter}} expected-error{{expected identifier}} expected-error{{extraneous 'template<>' in declaration of struct 'Z0'}} expected-note{{did you mean to use 'typename'?}} +template<typedef int Value> struct Z0; //expected-error{{invalid declaration specifier}} template<extern inline int Value> struct Z1; //expected-error2{{invalid declaration specifier}} template<virtual int Value> struct Z2; //expected-error{{invalid declaration specifier}} template<explicit int Value> struct Z3; //expected-error{{invalid declaration specifier}} @@ -43,6 +46,6 @@ template<auto> struct Z13; // OK // Make sure that we properly disambiguate non-type template parameters that // start with 'class'. class X1 { }; -template<class X1 *xptr> struct Y2 { }; +template<class X1 *xptr> struct X2 { }; // FIXME: add the example from p2 diff --git a/test/CXX/temp/temp.param/p3.cpp b/test/CXX/temp/temp.param/p3.cpp index c3c93396cb13..f709630504cd 100644 --- a/test/CXX/temp/temp.param/p3.cpp +++ b/test/CXX/temp/temp.param/p3.cpp @@ -16,7 +16,7 @@ template<template<class T> class Y> struct X1 { // [Note: because of the name lookup rules, a template-parameter that // could be interpreted as either a non-type template-parameter or a // type-parameter (because its identifier is the name of an already -// existing class) is taken as a type-parameter. For example, +// existing class) is taken as a type-parameter. For example, class T { /* ... */ }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}} #if __cplusplus >= 201103L // C++11 or later // expected-note@-2 {{candidate constructor (the implicit move constructor) not viable}} @@ -27,7 +27,7 @@ int i; template<class T, T i> struct X2 { void f(T t) { - T t1 = i; //template-parameters T and i + T t1 = i; // template-parameters T and i ::T t2 = ::i; // global namespace members T and i \ // expected-error{{no viable conversion}} } diff --git a/test/CXX/temp/temp.spec/temp.inst/p7.cpp b/test/CXX/temp/temp.spec/temp.inst/p7.cpp new file mode 100644 index 000000000000..5145dafdc5b4 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.inst/p7.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -verify -std=c++17 %s + +template<typename T> constexpr int f() { return T::value; } // expected-error {{'::'}} +template<bool B, typename T> void g(decltype(B ? f<T>() : 0)); +template<bool B, typename T> void g(...); +template<bool B, typename T> void h(decltype(int{B ? f<T>() : 0})); // expected-note {{instantiation of}} +template<bool B, typename T> void h(...); +void x() { + g<false, int>(0); // ok + g<true, int>(0); // ok + h<false, int>(0); // expected-note {{while substituting}} +} |