// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++98 %s -verify=expected,cxx98-14,cxx98-11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 %s -verify=expected,cxx98-14,cxx98-11,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 %s -verify=expected,cxx98-14,since-cxx14,since-cxx11,cxx14 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++17 %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++2a %s -verify=expected,since-cxx14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors namespace dr705 { // dr705: yes namespace N { struct S {}; void f(S); // #dr705-f } void g() { N::S s; f(s); // ok (f)(s); // expected-error@-1 {{use of undeclared identifier 'f'}} // expected-note@#dr705-f {{'N::f' declared here}} } } namespace dr712 { // dr712: partial void use(int); void f() { const int a = 0; // #dr712-f-a struct X { void g(bool cond) { use(a); use((a)); use(cond ? a : a); // FIXME: should only warn once use((cond, a)); // expected-warning@-1 {{left operand of comma operator has no effect}} // expected-warning@-2 {{left operand of comma operator has no effect}} (void)a; // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'dr712::f'}} FIXME // expected-note@#dr712-f-a {{'a' declared here}} (void)(a); // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'dr712::f'}} FIXME // expected-note@#dr712-f-a {{'a' declared here}} (void)(cond ? a : a); // #dr712-ternary // expected-error@#dr712-ternary {{reference to local variable 'a' declared in enclosing function 'dr712::f'}} FIXME // expected-note@#dr712-f-a {{'a' declared here}} // expected-error@#dr712-ternary {{reference to local variable 'a' declared in enclosing function 'dr712::f'}} FIXME // expected-note@#dr712-f-a {{'a' declared here}} (void)(cond, a); // #dr712-comma // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'dr712::f'}} FIXME // expected-note@#dr712-f-a {{'a' declared here}} // expected-warning@#dr712-comma {{left operand of comma operator has no effect}} } }; } #if __cplusplus >= 201103L void g() { struct A { int n; }; constexpr A a = {0}; // #dr712-g-a struct X { void g(bool cond) { use(a.n); use(a.*&A::n); (void)a.n; // since-cxx11-error@-1 {{reference to local variable 'a' declared in enclosing function 'dr712::g'}} FIXME // since-cxx11-note@#dr712-g-a {{'a' declared here}} (void)(a.*&A::n); // since-cxx11-error@-1 {{reference to local variable 'a' declared in enclosing function 'dr712::g'}} FIXME // since-cxx11-note@#dr712-g-a {{'a' declared here}} } }; } #endif } namespace dr727 { // dr727: partial struct A { template struct C; // #dr727-C template void f(); // #dr727-f template static int N; // #dr727-N // cxx98-11-error@-1 {{variable templates are a C++14 extension}} template<> struct C; template<> void f(); template<> static int N; template struct C; template static int N; struct B { template<> struct C; // expected-error@-1 {{class template specialization of 'C' not in class 'A' or an enclosing namespace}} // expected-note@#dr727-C {{explicitly specialized declaration is here}} template<> void f(); // expected-error@-1 {{no function template matches function template specialization 'f'}} template<> static int N; // expected-error@-1 {{variable template specialization of 'N' not in class 'A' or an enclosing namespace}} // expected-note@#dr727-N {{explicitly specialized declaration is here}} template struct C; // expected-error@-1 {{class template partial specialization of 'C' not in class 'A' or an enclosing namespace}} // expected-note@#dr727-C {{explicitly specialized declaration is here}} template static int N; // expected-error@-1 {{variable template partial specialization of 'N' not in class 'A' or an enclosing namespace}} // expected-note@#dr727-N {{explicitly specialized declaration is here}} template<> struct A::C; // expected-error@-1 {{class template specialization of 'C' not in class 'A' or an enclosing namespace}} // expected-note@#dr727-C {{explicitly specialized declaration is here}} template<> void A::f(); // expected-error@-1 {{o function template matches function template specialization 'f'}} // expected-error@-2 {{non-friend class member 'f' cannot have a qualified name}} template<> static int A::N; // expected-error@-1 {{non-friend class member 'N' cannot have a qualified name}} // expected-error@-2 {{variable template specialization of 'N' not in class 'A' or an enclosing namespace}} // expected-note@#dr727-N {{explicitly specialized declaration is here}} template struct A::C; // expected-error@-1 {{class template partial specialization of 'C' not in class 'A' or an enclosing namespace}} // expected-note@#dr727-C {{explicitly specialized declaration is here}} template static int A::N; // expected-error@-1 {{non-friend class member 'N' cannot have a qualified name}} // expected-error@-2 {{variable template partial specialization of 'N' not in class 'A' or an enclosing namespace}} // expected-note@#dr727-N {{explicitly specialized declaration is here}} }; }; template<> struct A::C; template<> void A::f(); template<> int A::N; template struct A::C; template int A::N; namespace C { template<> struct A::C; // expected-error@-1 {{class template specialization of 'C' not in class 'A' or an enclosing namespace}} // expected-note@#dr727-C {{explicitly specialized declaration is here}} template<> void A::f(); // expected-error@-1 {{function template specialization of 'f' not in class 'A' or an enclosing namespace}} // expected-note@#dr727-f {{explicitly specialized declaration is here}} template<> int A::N; // expected-error@-1 {{variable template specialization of 'N' not in class 'A' or an enclosing namespace}} // expected-note@#dr727-N {{explicitly specialized declaration is here}} template struct A::C; // expected-error@-1 {{class template partial specialization of 'C' not in class 'A' or an enclosing namespace}} // expected-note@#dr727-C {{explicitly specialized declaration is here}} template int A::N; // expected-error@-1 {{variable template partial specialization of 'N' not in class 'A' or an enclosing namespace}} // expected-note@#dr727-N {{explicitly specialized declaration is here}} } template struct D { template struct C { typename T::error e; }; // expected-error@-1 {{type 'float' cannot be used prior to '::' because it has no members}} // expected-note@#dr727-C-float {{in instantiation of template class 'dr727::D::C' requested here}} template void f() { T::error; } // expected-error@-1 {{type 'float' cannot be used prior to '::' because it has no members}} // expected-note@#dr727-f-float {{in instantiation of function template specialization 'dr727::D::f' requested here}} template static const int N = T::error; // cxx98-11-error@-1 {{variable templates are a C++14 extension}} // expected-error@-2 {{type 'float' cannot be used prior to '::' because it has no members}} // expected-note@#dr727-N-float {{in instantiation of static data member 'dr727::D::N' requested here}} template<> struct C {}; template<> void f() {} template<> static const int N; template struct C {}; template static const int N; template struct E { template<> void f() {} // expected-error@-1 {{no candidate function template was found for dependent member function template specialization}} }; }; void d(D di) { D::C(); di.f(); int a = D::N; D::C(); int b = D::N; D::C(); // #dr727-C-float di.f(); // #dr727-f-float int c = D::N; // #dr727-N-float } namespace mixed_inner_outer_specialization { #if __cplusplus >= 201103L template struct A { template constexpr int f() const { return 1; } template<> constexpr int f<0>() const { return 2; } }; template<> template constexpr int A<0>::f() const { return 3; } template<> template<> constexpr int A<0>::f<0>() const { return 4; } static_assert(A<1>().f<1>() == 1, ""); static_assert(A<1>().f<0>() == 2, ""); static_assert(A<0>().f<1>() == 3, ""); static_assert(A<0>().f<0>() == 4, ""); #endif #if __cplusplus >= 201402L template struct B { template static const int u = 1; template<> static const int u<0> = 2; // #dr727-u0 // Note that in C++17 onwards, these are implicitly inline, and so the // initializer of v<0> is not instantiated with the declaration. In // C++14, v<0> is a non-defining declaration and its initializer is // instantiated with the class. template static constexpr int v = 1; template<> static constexpr int v<0> = 2; // #dr727-v0 template static const inline int w = 1; // cxx14-error@-1 {{inline variables are a C++17 extension}} template<> static const inline int w<0> = 2; // cxx14-error@-1 {{inline variables are a C++17 extension}} }; template<> template constexpr int B<0>::u = 3; template<> template<> constexpr int B<0>::u<0> = 4; // since-cxx14-error@-1 {{static data member 'u' already has an initializer}} // since-cxx14-note@#dr727-u0 {{previous initialization is here}} template<> template constexpr int B<0>::v = 3; template<> template<> constexpr int B<0>::v<0> = 4; // cxx14-error@-1 {{static data member 'v' already has an initializer}} // cxx14-note@#dr727-v0 {{previous initialization is here}} template<> template constexpr int B<0>::w = 3; template<> template<> constexpr int B<0>::w<0> = 4; static_assert(B<1>().u<1> == 1, ""); static_assert(B<1>().u<0> == 2, ""); static_assert(B<0>().u<1> == 3, ""); static_assert(B<1>().v<1> == 1, ""); static_assert(B<1>().v<0> == 2, ""); static_assert(B<0>().v<1> == 3, ""); static_assert(B<0>().v<0> == 4, ""); // cxx14-error@-1 {{static assertion failed due to requirement 'dr727::mixed_inner_outer_specialization::B<0>().v<0> == 4'}} // cxx14-note@-2 {{expression evaluates to '2 == 4'}} static_assert(B<1>().w<1> == 1, ""); static_assert(B<1>().w<0> == 2, ""); static_assert(B<0>().w<1> == 3, ""); static_assert(B<0>().w<0> == 4, ""); #endif } template struct Collision { // FIXME: Missing diagnostic for duplicate function explicit specialization declaration. template int f1(); template<> int f1(); template<> int f1(); // FIXME: Missing diagnostic for fucntion redefinition! template int f2(); template<> int f2() {} template<> int f2() {} template static int v1; // cxx98-11-error@-1 {{variable templates are a C++14 extension}} template<> static int v1; // #dr727-v1-T template<> static int v1; // expected-error@-1 {{duplicate member 'v1'}} // expected-note@#dr727-Collision-int-int {{in instantiation of template class 'dr727::Collision' requested here}} // expected-note@#dr727-v1-T {{previous}} template static inline int v2; // cxx98-11-error@-1 {{variable templates are a C++14 extension}} // cxx98-14-error@-2 {{inline variables are a C++17 extension}} template<> static inline int v2; // #dr727-v2-T // cxx98-14-error@-1 {{inline variables are a C++17 extension}} template<> static inline int v2; // cxx98-14-error@-1 {{inline variables are a C++17 extension}} // expected-error@-2 {{duplicate member 'v2'}} // expected-note@#dr727-v2-T {{previous declaration is here}} // FIXME: Missing diagnostic for duplicate class explicit specialization. template struct S1; template<> struct S1; template<> struct S1; template struct S2; template<> struct S2 {}; // #dr727-S2-T template<> struct S2 {}; // expected-error@-1 {{redefinition of 'S2'}} // expected-note@#dr727-S2-T {{previous}} }; Collision c; // #dr727-Collision-int-int } namespace dr777 { // dr777: 3.7 #if __cplusplus >= 201103L template void f(int i = 0, T ...args) {} void ff() { f(); } template void g(int i = 0, T ...args, T ...args2) {} template void h(int i = 0, T ...args, int j = 1) {} #endif }