From 222e2a7620e6520ffaf4fc4e69d79c18da31542e Mon Sep 17 00:00:00 2001 From: "Zancanaro; Carlo" Date: Mon, 24 Sep 2012 09:58:17 +1000 Subject: Add the clang library to the repo (with some of my changes, too). --- .../CXX/temp/temp.spec/temp.expl.spec/examples.cpp | 334 +++++++++++++++++++++ .../test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp | 99 ++++++ .../test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp | 7 + .../test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp | 8 + .../test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp | 6 + .../test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp | 42 +++ .../test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp | 33 ++ .../test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp | 38 +++ .../test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp | 34 +++ .../test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp | 20 ++ .../test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp | 30 ++ .../CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp | 302 +++++++++++++++++++ .../test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp | 252 ++++++++++++++++ .../test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp | 14 + .../test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp | 30 ++ .../test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp | 13 + .../test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp | 58 ++++ .../temp/temp.spec/temp.expl.spec/p5-example.cpp | 34 +++ .../test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp | 61 ++++ .../test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp | 63 ++++ .../test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp | 14 + 21 files changed, 1492 insertions(+) create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp (limited to 'clang/test/CXX/temp/temp.spec/temp.expl.spec') diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp new file mode 100644 index 0000000..aecbfb5 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp @@ -0,0 +1,334 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR5907 { + template struct identity { typedef T type; }; + struct A { A(); }; + identity::type::A() { } + + struct B { void f(); }; + template struct C { typedef B type; }; + + void C::type::f() { } +} + +namespace PR9421 { + namespace N { template struct S { void f(); }; } + typedef N::S T; + namespace N { template<> void T::f() {} } +} + +namespace PR8277 { + template< typename S > + struct C + { + template< int > + void F( void ) + { + } + }; + + template< typename S > + struct D + { + typedef C< int > A; + }; + + typedef D< int >::A A; + + template<> + template<> + void A::F< 0 >( void ) + { + } +} + +namespace PR8277b { + template struct C { + void f(); + }; + template struct D { + typedef C A; + }; + template<> void D::A::f() { + } +} + +namespace PR8708 { + template struct A { + template struct B { + // #2 + void f(); + }; + }; + + // #A specialize the member template for + // implicit instantiation of A, + // leaving the member template "unspecialized" + // (14.7.3/16). Specialization uses the syntax + // for explicit specialization (14.7.3/14) + template<> template + struct A::B { + // #1 + void g(); + }; + + // #1 define its function g. There is an enclosing + // class template, so we write template<> for each + // specialized template (14.7.3/15). + template<> template + void A::B::g() { } + + // #2 define the unspecialized member template's + // f + template template + void A::B::f() { } + + + // specialize the member template again, now + // specializing the member too. This specializes + // #A + template<> template<> + struct A::B { + // #3 + void h(); + }; + + // defines #3. There is no enclosing class template, so + // we write no "template<>". + void A::B::h() { } + + void test() { + // calls #1 + A::B a; a.g(); + + // calls #2 + A::B b; b.f(); + + // calls #3 + A::B c; c.h(); + } +} + +namespace PR9482 { + namespace N1 { + template struct S { + void foo() {} + }; + } + + namespace N2 { + typedef N1::S X; + } + + namespace N1 { + template<> void N2::X::foo() {} + } +} + +namespace PR9668 { + namespace First + { + template + class Bar + { + protected: + + static const bool static_bool; + }; + } + + namespace Second + { + class Foo; + } + + typedef First::Bar Special; + + namespace + First + { + template<> + const bool Special::static_bool(false); + } +} + +namespace PR9877 { + template + struct X + { + struct Y; + }; + + template<> struct X<0>::Y { static const int Z = 1; }; + template<> struct X<1>::Y { static const int Z = 1; }; + + const int X<0>::Y::Z; + template<> const int X<1>::Y::Z; // expected-error{{extraneous 'template<>' in declaration of variable 'Z'}} +} + +namespace PR9913 { + templatestruct S; + templatestruct S { + template class F; + }; + + template + template + class S::F{}; +} + +namespace template_class_spec_perClassDecl_nested +{ + template struct A { + template struct B { + template struct C { + static void foo(); + }; + }; + }; + + template <> struct A { + template struct B { + template struct C { + static void foo(); + }; + }; + }; + + template <> template struct A::B::C { + static void foo(); + }; + + template <> template <> struct A::B::C { + static void foo(); + }; + + template <> template<> template struct A::B::C { + static void foo(); + }; +} + + +namespace spec_vs_expl_inst { + + // Test all permutations of Specialization, + // explicit instantiation Declaration, and explicit instantiation defInition. + + namespace SDI { // PR11558 + template class BasicStringPiece; + template <> class BasicStringPiece { }; + extern template class BasicStringPiece; + template class BasicStringPiece; + } + + namespace SID { + template class BasicStringPiece; + template <> class BasicStringPiece { }; + template class BasicStringPiece; // expected-note {{explicit instantiation definition is here}} + extern template class BasicStringPiece; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + } + + namespace ISD { + template class BasicStringPiece; // expected-note {{template is declared here}} + template class BasicStringPiece; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::ISD::BasicStringPiece'}} + template <> class BasicStringPiece { }; + extern template class BasicStringPiece; + } + + namespace IDS { + template class BasicStringPiece; // expected-note {{template is declared here}} + template class BasicStringPiece; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::IDS::BasicStringPiece'}} // expected-note {{explicit instantiation definition is here}} + extern template class BasicStringPiece; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + template <> class BasicStringPiece { }; + } + + namespace DIS { + template class BasicStringPiece; // expected-note {{template is declared here}} + extern template class BasicStringPiece; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::DIS::BasicStringPiece'}} + template class BasicStringPiece; + template <> class BasicStringPiece { }; + } + + namespace DSI { + template class BasicStringPiece; // expected-note {{template is declared here}} + extern template class BasicStringPiece; // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::DSI::BasicStringPiece'}} + template <> class BasicStringPiece { }; + template class BasicStringPiece; + } + + // The same again, with a defined template class. + + namespace SDI_WithDefinedTemplate { + template class BasicStringPiece {}; + template <> class BasicStringPiece { }; + extern template class BasicStringPiece; + template class BasicStringPiece; + } + + namespace SID_WithDefinedTemplate { + template class BasicStringPiece {}; + template <> class BasicStringPiece { }; + template class BasicStringPiece; // expected-note {{explicit instantiation definition is here}} + extern template class BasicStringPiece; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + } + + namespace ISD_WithDefinedTemplate { + template class BasicStringPiece {}; + template class BasicStringPiece; // expected-note {{explicit instantiation first required here}} + template <> class BasicStringPiece { }; // expected-error {{explicit specialization of 'spec_vs_expl_inst::ISD_WithDefinedTemplate::BasicStringPiece' after instantiation}} + extern template class BasicStringPiece; + } + + namespace IDS_WithDefinedTemplate { + template class BasicStringPiece {}; + template class BasicStringPiece; // expected-note {{explicit instantiation definition is here}} expected-note {{previous definition is here}} + extern template class BasicStringPiece; // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}} + template <> class BasicStringPiece { }; // expected-error {{redefinition of 'spec_vs_expl_inst::IDS_WithDefinedTemplate::BasicStringPiece'}} + } + + namespace DIS_WithDefinedTemplate { + template class BasicStringPiece {}; + extern template class BasicStringPiece; // expected-note {{explicit instantiation first required here}} + template class BasicStringPiece; + template <> class BasicStringPiece { }; // expected-error {{explicit specialization of 'spec_vs_expl_inst::DIS_WithDefinedTemplate::BasicStringPiece' after instantiation}} + } + + namespace DSI_WithDefinedTemplate { + template class BasicStringPiece {}; + extern template class BasicStringPiece; // expected-note {{explicit instantiation first required here}} + template <> class BasicStringPiece { }; // expected-error {{explicit specialization of 'spec_vs_expl_inst::DSI_WithDefinedTemplate::BasicStringPiece' after instantiation}} + template class BasicStringPiece; + } + + // And some more random tests. + + namespace SII_WithDefinedTemplate { + template class BasicStringPiece {}; + template <> class BasicStringPiece { }; + template class BasicStringPiece; // expected-note {{previous explicit instantiation is here}} + template class BasicStringPiece; // expected-error {{duplicate explicit instantiation of 'BasicStringPiece'}} + } + + namespace SIS { + template class BasicStringPiece; + template <> class BasicStringPiece { }; // expected-note {{previous definition is here}} + template class BasicStringPiece; + template <> class BasicStringPiece { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SIS::BasicStringPiece'}} + } + + namespace SDS { + template class BasicStringPiece; + template <> class BasicStringPiece { }; // expected-note {{previous definition is here}} + extern template class BasicStringPiece; + template <> class BasicStringPiece { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SDS::BasicStringPiece'}} + } + + namespace SDIS { + template class BasicStringPiece; + template <> class BasicStringPiece { }; // expected-note {{previous definition is here}} + extern template class BasicStringPiece; + template class BasicStringPiece; + template <> class BasicStringPiece { }; // expected-error {{redefinition of 'spec_vs_expl_inst::SDIS::BasicStringPiece'}} + } + +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp new file mode 100644 index 0000000..3843c0d --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp @@ -0,0 +1,99 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// This test creates cases where implicit instantiations of various entities +// would cause a diagnostic, but provides expliict specializations for those +// entities that avoid the diagnostic. The intent is to verify that +// implicit instantiations do not occur (because the explicit specialization +// is used instead). +struct NonDefaultConstructible { + NonDefaultConstructible(int); +}; + + +// C++ [temp.expl.spec]p1: +// An explicit specialization of any of the following: + +// -- function template +template void f0(T) { + T t; +} + +template<> void f0(NonDefaultConstructible) { } + +void test_f0(NonDefaultConstructible NDC) { + f0(NDC); +} + +// -- class template +template +struct X0 { + static T member; + + void f1(T t) { + t = 17; + } + + struct Inner : public T { }; + + template + struct InnerTemplate : public T { }; + + template + void ft1(T t, U u); +}; + +template +template +void X0::ft1(T t, U u) { + t = u; +} + +template T X0::member; + +template<> struct X0 { }; +X0 test_X0; + + +// -- member function of a class template +template<> void X0::f1(void *) { } + +void test_spec(X0 xvp, void *vp) { + xvp.f1(vp); +} + +// -- static data member of a class template +template<> +NonDefaultConstructible X0::member = 17; + +NonDefaultConstructible &get_static_member() { + return X0::member; +} + +// -- member class of a class template +template<> +struct X0::Inner { }; + +X0::Inner inner0; + +// -- member class template of a class template +template<> +template<> +struct X0::InnerTemplate { }; + +X0::InnerTemplate inner_template0; + +// -- member function template of a class template +template<> +template<> +void X0::ft1(void*, const void*) { } + +void test_func_template(X0 xvp, void *vp, const void *cvp) { + xvp.ft1(vp, cvp); +} + +// example from the standard: +template class stream; +template<> class stream { /* ... */ }; +template class Array { /* ... */ }; +template void sort(Array& v) { /* ... */ } +template<> void sort(Array&) ; diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp new file mode 100644 index 0000000..b81c1e7 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template class X; +template<> class X; // expected-note{{forward}} +X* p; + +X x; // expected-error{{incomplete type}} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp new file mode 100644 index 0000000..5fa2f62 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template class Array { /* ... */ }; +template void sort(Array& v); + +// explicit specialization for sort(Array&) +// with deduced template-argument of type int +template<> void sort(Array&); diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp new file mode 100644 index 0000000..fb6d1be --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +template void f(T); + +template<> void f(int) { } +void f(int) { } diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp new file mode 100644 index 0000000..121cb8e --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s + +template void f(T) { /* ... */ } +template inline void g(T) { /* ... */ } + +// CHECK: define void @_Z1gIiEvT_ +template<> void g<>(int) { /* ... */ } + +template +struct X { + void f() { } + void g(); + void h(); +}; + +template +void X::g() { +} + +template +inline void X::h() { +} + +// CHECK: define void @_ZN1XIiE1fEv +template<> void X::f() { } + +// CHECK: define void @_ZN1XIiE1hEv +template<> void X::h() { } + +// CHECK: define linkonce_odr void @_Z1fIiEvT_ +template<> inline void f<>(int) { /* ... */ } + +// CHECK: define linkonce_odr void @_ZN1XIiE1gEv +template<> inline void X::g() { } + +void test(X xi) { + f(17); + g(17); + xi.f(); + xi.g(); + xi.h(); +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp new file mode 100644 index 0000000..72f33df --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct NonDefaultConstructible { + NonDefaultConstructible(const NonDefaultConstructible&); // expected-note{{candidate constructor}} +}; + +template +struct X { + static T member; +}; + +template +T X::member; // expected-error{{no matching constructor}} + +// Okay; this is a declaration, not a definition. +template<> +NonDefaultConstructible X::member; + +NonDefaultConstructible &test(bool b) { + return b? X::member // expected-note{{instantiation}} + : X::member; +} + +namespace rdar9422013 { + template + struct X { + struct Inner { + static unsigned array[17]; + }; + }; + + template<> unsigned X<1>::Inner::array[]; // okay +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp new file mode 100644 index 0000000..c7597e9 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template struct A { + void f(T); + template void g1(T, X1); + template void g2(T, X2); + void h(T) { } +}; + +// specialization +template<> void A::f(int); + +// out of class member template definition +template template void A::g1(T, X1) { } + +// member template specialization +template<> template void A::g1(int, X1); + +// member template specialization +template<> template<> + void A::g1(int, char); // X1 deduced as char + +template<> template<> + void A::g2(int, char); // X2 specified as char + // member specialization even if defined in class definition + +template<> void A::h(int) { } + +namespace PR10024 { + template + struct Test{ + template + void get(U i) {} + }; + + template + template <> + void Test::get(double i) {} // expected-error{{cannot specialize (with 'template<>') a member of an unspecialized template}} +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp new file mode 100644 index 0000000..56231e2 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template +class A { + template class B { + void mf(); + }; +}; + +template<> template<> class A::B; +template<> template<> void A::B::mf(); + +template<> void A::B::mf(); // expected-error{{requires 'template<>'}} + +namespace test1 { + template class A { + static int foo; + static int bar; + }; + typedef A AA; + + template <> int AA::foo = 0; + int AA::bar = 1; // expected-error {{template specialization requires 'template<>'}} + int A::bar = 2; // expected-error {{template specialization requires 'template<>'}} + + template <> class A { + public: + static int foo; + static int bar; + }; + + typedef A AB; + template <> int AB::foo = 0; // expected-error{{extraneous 'template<>'}} + int AB::bar = 1; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp new file mode 100644 index 0000000..4d175a8 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template class A { + template class B { + template void mf1(T3); + void mf2(); + }; +}; + +template<> template +class A::B { }; + +template<> template<> template + void A::B::mf1(T t) { } + +template<> template<> template +void A::B::mf1(T t) { } // expected-error{{does not match}} + +// FIXME: This diagnostic could probably be better. +template template<> + void A::B::mf2() { } // expected-error{{does not refer}} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp new file mode 100644 index 0000000..1c2ea7e --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template +struct X { + template struct Inner { }; + + template void f(T, U) { } +}; + +template<> template +struct X::Inner { + U member; +}; + +template<> template +void X::f(int x, U y) { + x = y; // expected-error{{incompatible type}} +} + +void test(X xi, X xl, float *fp) { + X::Inner xii; + xii.member = fp; + xi.f(17, 25); + xi.f(17, 3.14159); + xi.f(17, fp); // expected-note{{instantiation}} + X::Inner xli; + + xli.member = fp; // expected-error{{no member}} + xl.f(17, fp); // okay +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp new file mode 100644 index 0000000..b0a19fb --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-0x.cpp @@ -0,0 +1,302 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// This test creates cases where implicit instantiations of various entities +// would cause a diagnostic, but provides expliict specializations for those +// entities that avoid the diagnostic. The specializations are alternately +// declarations and definitions, and the intent of this test is to verify +// that we allow specializations only in the appropriate namespaces (and +// nowhere else). +struct NonDefaultConstructible { + NonDefaultConstructible(int); +}; + + +// C++ [temp.expl.spec]p1: +// An explicit specialization of any of the following: + +// -- function template +namespace N0 { + template void f0(T) { + T t; + } + + template<> void f0(NonDefaultConstructible) { } + + void test_f0(NonDefaultConstructible NDC) { + f0(NDC); + } + + template<> void f0(int); + template<> void f0(long); +} + +template<> void N0::f0(int) { } // okay + +namespace N1 { + template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}} +} + +template<> void N0::f0(double) { } + +struct X1 { + template void f(T); + + template<> void f(int); // expected-error{{in class scope}} +}; + +// -- class template +namespace N0 { + +template +struct X0 { // expected-note {{here}} + static T member; + + void f1(T t) { + t = 17; + } + + struct Inner : public T { }; // expected-note 2{{here}} + + template + struct InnerTemplate : public T { }; // expected-note 1{{explicitly specialized}} \ + // expected-error{{base specifier}} + + template + void ft1(T t, U u); +}; + +} + +template +template +void N0::X0::ft1(T t, U u) { + t = u; +} + +template T N0::X0::member; + +template<> struct N0::X0 { }; +N0::X0 test_X0; + +namespace N1 { + template<> struct N0::X0 { }; // expected-error{{class template specialization of 'X0' must originally be declared in namespace 'N0'}} +} + +namespace N0 { + template<> struct X0; +} + +template<> struct N0::X0 { + void f1(void *); +}; + +// -- member function of a class template +template<> void N0::X0::f1(void *) { } + +void test_spec(N0::X0 xvp, void *vp) { + xvp.f1(vp); +} + +namespace N0 { + template<> void X0::f1(void *) { } // expected-error{{no function template matches}} + + template<> void X0::f1(const volatile void*); +} + +void test_x0_cvvoid(N0::X0 x0, const volatile void *cvp) { + x0.f1(cvp); // okay: we've explicitly specialized +} + +// -- static data member of a class template +namespace N0 { + // This actually tests p15; the following is a declaration, not a definition. + template<> + NonDefaultConstructible X0::member; + + template<> long X0::member = 17; + + template<> float X0::member; + + template<> double X0::member; +} + +NonDefaultConstructible &get_static_member() { + return N0::X0::member; +} + +template<> int N0::X0::member; + +template<> float N0::X0::member = 3.14f; + +namespace N1 { + template<> double N0::X0::member = 3.14; // expected-error{{does not enclose namespace}} +} + +// -- member class of a class template +namespace N0 { + + template<> + struct X0::Inner { }; + + template<> + struct X0::Inner { }; + + template<> + struct X0::Inner; + + template<> + struct X0::Inner; + + template<> + struct X0::Inner; // expected-note{{forward declaration}} +} + +template<> +struct N0::X0::Inner { }; + +template<> +struct N0::X0::Inner { }; + +namespace N1 { + template<> + struct N0::X0::Inner { }; // expected-error{{member class specialization}} + + template<> + struct N0::X0::Inner { }; // expected-error{{member class specialization}} +}; + +N0::X0::Inner inner0; +N0::X0::Inner inner1; +N0::X0::Inner inner2; +N0::X0::Inner inner3; +N0::X0::Inner inner4; // expected-error{{incomplete}} + +// -- member class template of a class template +namespace N0 { + template<> + template<> + struct X0::InnerTemplate { }; + + template<> template<> + struct X0::InnerTemplate; // expected-note{{forward declaration}} + + template<> template<> + struct X0::InnerTemplate; + + template<> template<> + struct X0::InnerTemplate; +} + +template<> template<> +struct N0::X0::InnerTemplate { }; // okay + +template<> template<> +struct N0::X0::InnerTemplate { }; + +namespace N1 { + template<> template<> + struct N0::X0::InnerTemplate { }; // expected-error{{enclosing}} +} + +N0::X0::InnerTemplate inner_template0; +N0::X0::InnerTemplate inner_template1; // expected-error{{incomplete}} +N0::X0::InnerTemplate inner_template2; +N0::X0::InnerTemplate inner_template3; // expected-note{{instantiation}} + +// -- member function template of a class template +namespace N0 { + template<> + template<> + void X0::ft1(void*, const void*) { } + + template<> template<> + void X0::ft1(void *, int); + + template<> template<> + void X0::ft1(void *, unsigned); + + template<> template<> + void X0::ft1(void *, long); +} + +template<> template<> +void N0::X0::ft1(void *, unsigned) { } // okay + +template<> template<> +void N0::X0::ft1(void *, float) { } + +namespace N1 { + template<> template<> + void N0::X0::ft1(void *, long) { } // expected-error{{does not enclose namespace}} +} + + +void test_func_template(N0::X0 xvp, void *vp, const void *cvp, + int i, unsigned u) { + xvp.ft1(vp, cvp); + xvp.ft1(vp, i); + xvp.ft1(vp, u); +} + +namespace has_inline_namespaces { + inline namespace inner { + template void f(T&); + + template + struct X0 { + struct MemberClass; + + void mem_func(); + + template + struct MemberClassTemplate; + + template + void mem_func_template(U&); + + static int value; + }; + } + + struct X1; + struct X2; + + // An explicit specialization whose declarator-id is not qualified + // shall be declared in the nearest enclosing namespace of the + // template, or, if the namespace is inline (7.3.1), any namespace + // from its enclosing namespace set. + template<> void f(X1&); + template<> void f(X2&); + + template<> struct X0 { }; + + template<> struct X0::MemberClass { }; + + template<> void X0::mem_func(); + + template<> template struct X0::MemberClassTemplate { }; + + template<> template void X0::mem_func_template(T&) { } + + template<> int X0::value = 12; +} + +struct X3; +struct X4; + +template<> void has_inline_namespaces::f(X3&); +template<> void has_inline_namespaces::f(X4&); + +template<> struct has_inline_namespaces::X0 { }; + +template<> struct has_inline_namespaces::X0::MemberClass { }; + +template<> void has_inline_namespaces::X0::mem_func(); + +template<> template +struct has_inline_namespaces::X0::MemberClassTemplate { }; + +template<> template +void has_inline_namespaces::X0::mem_func_template(T&) { } + +template<> int has_inline_namespaces::X0::value = 13; diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp new file mode 100644 index 0000000..c972bf7 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp @@ -0,0 +1,252 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// This test creates cases where implicit instantiations of various entities +// would cause a diagnostic, but provides expliict specializations for those +// entities that avoid the diagnostic. The specializations are alternately +// declarations and definitions, and the intent of this test is to verify +// that we allow specializations only in the appropriate namespaces (and +// nowhere else). +struct NonDefaultConstructible { + NonDefaultConstructible(int); +}; + + +// C++ [temp.expl.spec]p1: +// An explicit specialization of any of the following: + +// -- function template +namespace N0 { + template void f0(T) { // expected-note{{here}} + T t; + } + + template<> void f0(NonDefaultConstructible) { } + + void test_f0(NonDefaultConstructible NDC) { + f0(NDC); + } + + template<> void f0(int); + template<> void f0(long); +} + +template<> void N0::f0(int) { } // okay + +namespace N1 { + template<> void N0::f0(long) { } // expected-error{{does not enclose namespace}} +} + +template<> void N0::f0(double); // expected-warning{{C++11 extension}} +template<> void N0::f0(double) { } + +struct X1 { + template void f(T); + + template<> void f(int); // expected-error{{in class scope}} +}; + +// -- class template +namespace N0 { + +template +struct X0 { // expected-note 2{{here}} + static T member; // expected-note{{here}} + + void f1(T t) { // expected-note{{explicitly specialized declaration is here}} + t = 17; + } + + struct Inner : public T { }; // expected-note 3{{here}} + + template + struct InnerTemplate : public T { }; // expected-note 2{{explicitly specialized}} \ + // expected-error{{base specifier}} + + template + void ft1(T t, U u); // expected-note{{explicitly specialized}} +}; + +} + +template +template +void N0::X0::ft1(T t, U u) { + t = u; +} + +template T N0::X0::member; + +template<> struct N0::X0 { }; // expected-warning{{C++11 extension}} +N0::X0 test_X0; + +namespace N1 { + template<> struct N0::X0 { }; // expected-error{{originally}} +} + +namespace N0 { + template<> struct X0; +} + +template<> struct N0::X0 { + void f1(void *); +}; + +// -- member function of a class template +template<> void N0::X0::f1(void *) { } // expected-warning{{member function specialization}} + +void test_spec(N0::X0 xvp, void *vp) { + xvp.f1(vp); +} + +namespace N0 { + template<> void X0::f1(void *) { } // expected-error{{no function template matches}} + + template<> void X0::f1(const volatile void*); +} + +void test_x0_cvvoid(N0::X0 x0, const volatile void *cvp) { + x0.f1(cvp); // okay: we've explicitly specialized +} + +// -- static data member of a class template +namespace N0 { + // This actually tests p15; the following is a declaration, not a definition. + template<> + NonDefaultConstructible X0::member; + + template<> long X0::member = 17; + + template<> float X0::member; + + template<> double X0::member; +} + +NonDefaultConstructible &get_static_member() { + return N0::X0::member; +} + +template<> int N0::X0::member; // expected-warning{{C++11 extension}} + +template<> float N0::X0::member = 3.14f; + +namespace N1 { + template<> double N0::X0::member = 3.14; // expected-error{{does not enclose namespace}} +} + +// -- member class of a class template +namespace N0 { + + template<> + struct X0::Inner { }; + + template<> + struct X0::Inner { }; + + template<> + struct X0::Inner; + + template<> + struct X0::Inner; + + template<> + struct X0::Inner; // expected-note{{forward declaration}} +} + +template<> +struct N0::X0::Inner { }; // expected-warning{{C++11 extension}} + +template<> +struct N0::X0::Inner { }; + +namespace N1 { + template<> + struct N0::X0::Inner { }; // expected-error{{member class specialization}} + + template<> + struct N0::X0::Inner { }; // expected-error{{member class specialization}} +}; + +N0::X0::Inner inner0; +N0::X0::Inner inner1; +N0::X0::Inner inner2; +N0::X0::Inner inner3; +N0::X0::Inner inner4; // expected-error{{incomplete}} + +// -- member class template of a class template +namespace N0 { + template<> + template<> + struct X0::InnerTemplate { }; + + template<> template<> + struct X0::InnerTemplate; // expected-note{{forward declaration}} + + template<> template<> + struct X0::InnerTemplate; + + template<> template<> + struct X0::InnerTemplate; +} + +template<> template<> +struct N0::X0::InnerTemplate { }; // okay + +template<> template<> +struct N0::X0::InnerTemplate { }; // expected-warning{{class template specialization}} + +namespace N1 { + template<> template<> + struct N0::X0::InnerTemplate { }; // expected-error{{enclosing}} +} + +N0::X0::InnerTemplate inner_template0; +N0::X0::InnerTemplate inner_template1; // expected-error{{incomplete}} +N0::X0::InnerTemplate inner_template2; +N0::X0::InnerTemplate inner_template3; // expected-note{{instantiation}} + +// -- member function template of a class template +namespace N0 { + template<> + template<> + void X0::ft1(void*, const void*) { } + + template<> template<> + void X0::ft1(void *, int); + + template<> template<> + void X0::ft1(void *, unsigned); + + template<> template<> + void X0::ft1(void *, long); +} + +template<> template<> +void N0::X0::ft1(void *, unsigned) { } // okay + +template<> template<> +void N0::X0::ft1(void *, float) { } // expected-warning{{function template specialization}} + +namespace N1 { + template<> template<> + void N0::X0::ft1(void *, long) { } // expected-error{{does not enclose namespace}} +} + + +void test_func_template(N0::X0 xvp, void *vp, const void *cvp, + int i, unsigned u) { + xvp.ft1(vp, cvp); + xvp.ft1(vp, i); + xvp.ft1(vp, u); +} + +namespace PR8979 { + template + struct X0 { + template class Inner; + struct OtherInner; + template void f(Inner&); + + typedef Inner MyInner; + template<> void f(MyInner&); // expected-error{{cannot specialize a function 'f' within class scope}} + }; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp new file mode 100644 index 0000000..86cdcf8 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template +void f(T); + +template +struct A { }; + +struct X { + template<> friend void f(int); // expected-error{{in a friend}} + template<> friend class A; // expected-error{{cannot be a friend}} + + friend void f(float); // okay + friend class A; // okay +}; diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp new file mode 100644 index 0000000..ab26f40 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template +struct X { + void mf1(T); + template void mf2(T, U); // expected-note{{previous}} +}; + +template<> +void X::mf1(int i = 17) // expected-error{{default}} +{ +} + +template<> template<> +void X::mf2(int, int = 17) // expected-error{{default}} +{ } + +template<> template +void X::mf2(int, U = U()) // expected-error{{default}} +{ +} + +template<> +struct X { + void mf1(float); +}; + +void X::mf1(float = 3.14f) // okay +{ +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp new file mode 100644 index 0000000..84841cb --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace N { + template class X; +} + +template<> class X { /* ... */ }; // expected-error {{non-template class 'X'}} + +namespace N { + +template<> class X { /* ... */ }; // OK: X is a template + +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp new file mode 100644 index 0000000..772aef6 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct IntHolder { // expected-note{{here}} // expected-note 2{{candidate constructor (the implicit copy constructor)}} + IntHolder(int); // expected-note 2{{candidate constructor}} +}; + +template +struct X { // expected-note{{here}} + void f() { + T t; // expected-error{{no matching}} + } + + void g() { } + + struct Inner { // expected-error{{implicit default}} + T value; // expected-note {{member is declared here}} + }; + + static T value; +}; + +template +T X::value; // expected-error{{no matching constructor}} + +IntHolder &test_X_IntHolderInt(X xih) { + xih.g(); // okay + xih.f(); // expected-note{{instantiation}} + + X::Inner inner; // expected-note {{first required here}} + + return X::value; // expected-note{{instantiation}} +} + +// Explicitly specialize the members of X to not cause +// problems with instantiation. +template<> +void X::f() { } + +template<> +struct X::Inner { + Inner() : value(17) { } + IntHolder value; +}; + +template<> +IntHolder X::value = 17; + +IntHolder &test_X_IntHolderInt(X xih) { + xih.g(); // okay + xih.f(); // okay, uses specialization + + X::Inner inner; // okay, uses specialization + + return X::value; // okay, uses specialization +} + +template<> +X::X() { } // expected-error{{instantiated member}} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp new file mode 100644 index 0000000..f49190e --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +template struct A { + struct B { }; + template struct C { }; +}; + template<> struct A { + void f(int); +}; +void h() { + A a; + a.f(16); +} +// A::f must be defined somewhere +// template<> not used for a member of an // explicitly specialized class template +void A::f(int) { /* ... */ } + template<> struct A::B { + void f(); +}; +// template<> also not used when defining a member of // an explicitly specialized member class +void A::B::f() { /* ... */ } + template<> template struct A::C { + void f(); +}; + +template<> +template void A::C::f() { /* ... */ } + template<> struct A::B { + void f(); +}; +template<> void A::B::f() { /* ... */ } // expected-error{{no function template matches function template specialization 'f'}} + template<> template struct A::C { + void f(); +}; +template void A::C::f() { /* ... */ } // expected-error{{template parameter list matching the non-templated nested type 'A' should be empty ('template<>')}} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp new file mode 100644 index 0000000..512ea47 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp @@ -0,0 +1,61 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct IntHolder { + IntHolder(int); +}; + +template +struct X { + void f() { + T t; + } + + void g() { } + + struct Inner { + T value; + }; + + static T value; +}; + +template +T X::value; + +// Explicitly specialize the members of X to not cause +// problems with instantiation, but only provide declarations (not definitions). +template<> +void X::f(); + +template<> +struct X::Inner; // expected-note{{forward declaration}} + +template<> +IntHolder X::value; + +IntHolder &test_X_IntHolderInt(X xih) { + xih.g(); // okay + xih.f(); // okay, uses specialization + + X::Inner inner; // expected-error {{incomplete}} + + return X::value; // okay, uses specialization +} + + +template struct A { + void f(T) { /* ... */ } +}; + +template<> struct A { + void f(int); +}; + +void h() { + A a; + a.f(16); // A::f must be defined somewhere +} + +// explicit specialization syntax not used for a member of +// explicitly specialized class template specialization +void A::f(int) { /* ... */ } diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp new file mode 100644 index 0000000..f539471 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template +struct X0 { + void f(); + + template + void g(U); + + struct Nested { + }; + + static T member; +}; + +int &use_X0_int(X0 x0i, // expected-note{{implicit instantiation first required here}} + int i) { + x0i.f(); // expected-note{{implicit instantiation first required here}} + x0i.g(i); // expected-note{{implicit instantiation first required here}} + X0::Nested nested; // expected-note{{implicit instantiation first required here}} + return X0::member; // expected-note{{implicit instantiation first required here}} +} + +template<> +void X0::f() { // expected-error{{after instantiation}} +} + +template<> template<> +void X0::g(int) { // expected-error{{after instantiation}} +} + +template<> +struct X0::Nested { }; // expected-error{{after instantiation}} + +template<> +int X0::member = 17; // expected-error{{after instantiation}} + +template<> +struct X0 { }; // expected-error{{after instantiation}} + +// Example from the standard +template class Array { /* ... */ }; + +template void sort(Array& v) { /* ... */ } + +struct String {}; + +void f(Array& v) { + + sort(v); // expected-note{{required}} + // use primary template + // sort(Array&), T is String +} + +template<> void sort(Array& v); // // expected-error{{after instantiation}} +template<> void sort<>(Array& v); // OK: sort not yet used + +namespace PR6160 { + template void f(T); + template<> void f(int); + extern template void f(int); + template<> void f(int) { } +} diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp new file mode 100644 index 0000000..d4ce01f --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace N { + template class X { /* ... */ }; + template class Y { /* ... */ }; + template<> class X { /* ... */ }; + template<> class Y; + + const unsigned NumElements = 17; +} + +template<> class N::Y { + int array[NumElements]; +}; -- cgit v1.2.3