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). --- clang/test/CXX/temp/temp.spec/p5.cpp | 47 +++ .../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 + .../CXX/temp/temp.spec/temp.explicit/p1-0x.cpp | 24 ++ .../CXX/temp/temp.spec/temp.explicit/p1-emit.cpp | 29 ++ clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp | 89 ++++++ .../test/CXX/temp/temp.spec/temp.explicit/p10.cpp | 33 ++ .../test/CXX/temp/temp.spec/temp.explicit/p11.cpp | 18 ++ .../test/CXX/temp/temp.spec/temp.explicit/p12.cpp | 6 + clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp | 43 +++ .../CXX/temp/temp.spec/temp.explicit/p3-0x.cpp | 65 ++++ clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp | 81 +++++ clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp | 48 +++ clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp | 17 ++ clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp | 35 +++ clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp | 36 +++ clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp | 40 +++ .../temp/temp.spec/temp.explicit/p9-linkage.cpp | 66 ++++ clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp | 59 ++++ clang/test/CXX/temp/temp.spec/temp.inst/p1.cpp | 104 +++++++ clang/test/CXX/temp/temp.spec/temp.inst/p11.cpp | 15 + 40 files changed, 2347 insertions(+) create mode 100644 clang/test/CXX/temp/temp.spec/p5.cpp 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 create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.inst/p1.cpp create mode 100644 clang/test/CXX/temp/temp.spec/temp.inst/p11.cpp (limited to 'clang/test/CXX/temp/temp.spec') diff --git a/clang/test/CXX/temp/temp.spec/p5.cpp b/clang/test/CXX/temp/temp.spec/p5.cpp new file mode 100644 index 0000000..0e69a26 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/p5.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template inline void f(T) { } +template void f(int); // expected-note{{previous explicit instantiation}} +template void f(int); // expected-error{{duplicate explicit instantiation}} + +template +struct X0 { + union Inner { }; + + void f(T) { } + + static T value; +}; + +template +T X0::value = 3.14; // expected-warning{{implicit conversion turns literal floating-point number into integer}} + +template struct X0; // expected-note{{previous explicit instantiation}} \ + expected-note{{requested here}} +template struct X0; // expected-error{{duplicate explicit instantiation}} + +template void X0::f(float); // expected-note{{previous explicit instantiation}} +template void X0::f(float); // expected-error{{duplicate explicit instantiation}} + +template union X0::Inner; // expected-note{{previous explicit instantiation}} +template union X0::Inner; // expected-error{{duplicate explicit instantiation}} + +template float X0::value; // expected-note{{previous explicit instantiation}} +template float X0::value; // expected-error{{duplicate explicit instantiation}} + +// Make sure that we don't get tricked by redeclarations of nested classes. +namespace NestedClassRedecls { + template + struct X { + struct Nested; + friend struct Nested; + + struct Nested { + Nested() {} + } nested; + }; + + X xi; + + template struct X; +} 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]; +}; diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp new file mode 100644 index 0000000..80f0598 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +template +struct X { + void f() {} +}; + +template inline void X::f(); // expected-error{{explicit instantiation cannot be 'inline'}} + +template +struct Y { + constexpr int f() { return 0; } +}; + +template constexpr int Y::f(); // expected-error{{explicit instantiation cannot be 'constexpr'}} + +template +struct Z { + enum E : T { e1, e2 }; + T t; // expected-note {{refers here}} +}; + +template enum Z::E; // expected-error {{enumerations cannot be explicitly instantiated}} +template int Z::t; // expected-error {{explicit instantiation of 't' does not refer to}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp new file mode 100644 index 0000000..d0df305 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 -o - %s | FileCheck %s +template +struct X { + static T member1; + static T member2; + static T member3; +}; + +template +T X::member1; + +template +T X::member2 = 17; + +// CHECK: @_ZN1XIiE7member1E = weak_odr global i32 0 +template int X::member1; + +// CHECK: @_ZN1XIiE7member2E = weak_odr global i32 17 +template int X::member2; + +// For implicit instantiation of +long& get(bool Cond1, bool Cond2) { + // CHECK: @_ZN1XIlE7member1E = weak_odr global i64 0 + // CHECK: @_ZN1XIlE7member2E = weak_odr global i64 17 + // CHECK: @_ZN1XIlE7member3E = external global i64 + return Cond1? X::member1 + : Cond2? X::member2 + : X::member3; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp new file mode 100644 index 0000000..b426339 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct C { }; + +template +struct X0 { + T value; // expected-error{{incomplete}} +}; + +// Explicitly instantiate a class template specialization +template struct X0; +template struct X0; // expected-note{{instantiation}} + +// Explicitly instantiate a function template specialization +template +void f0(T t) { + ++t; // expected-error{{cannot increment}} +} + +template void f0(int); +template void f0(long); +template void f0<>(unsigned); +template void f0(int C::*); // expected-note{{instantiation}} + +// Explicitly instantiate a member template specialization +template +struct X1 { + template + struct Inner { + T member1; + U member2; // expected-error{{incomplete}} + }; + + template + void f(T& t, U u) { + t = u; // expected-error{{incompatible}} + } +}; + +template struct X1::Inner; +template struct X1::Inner; +template struct X1::Inner; // expected-note{{instantiation}} + +template void X1::f(int&, float); +template void X1::f(int&, long); +template void X1::f<>(int&, double); +template void X1::f<>(int&, int*); // expected-note{{instantiation}} + +// Explicitly instantiate members of a class template +struct Incomplete; // expected-note{{forward declaration}} +struct NonDefaultConstructible { // expected-note{{candidate constructor (the implicit copy constructor) not viable}} + NonDefaultConstructible(int); // expected-note{{candidate constructor}} +}; + +template +struct X2 { + void f(T &t, U u) { + t = u; // expected-error{{incompatible}} + } + + struct Inner { + T member1; + U member2; // expected-error{{incomplete}} + }; + + static T static_member1; + static U static_member2; +}; + +template +T X2::static_member1 = 17; // expected-error{{cannot initialize}} + +template +U X2::static_member2; // expected-error{{no matching}} + +template void X2::f(int &, float); +template void X2::f(int &, double); // expected-error{{does not refer}} +template void X2::f(int&, int*); // expected-note{{instantiation}} + +template struct X2::Inner; +template struct X2::Inner; // expected-note{{instantiation}} + +template int X2::static_member1; +template int* X2::static_member1; // expected-note{{instantiation}} +template + NonDefaultConstructible X2::static_member1; + +template + NonDefaultConstructible X2::static_member2; // expected-note{{instantiation}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp new file mode 100644 index 0000000..290a874 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template +struct X0 { + void f(T&); + + struct Inner; + + static T static_var; +}; + +template +void X0::f(T& t) { + t = 1; // expected-error{{incompatible type}} +} + +template +struct X0::Inner { + T member; +}; + +template +T X0::static_var = 1; // expected-error{{cannot initialize}} + +extern template struct X0; +template struct X0; // expected-note 2{{instantiation}} + +template struct X0; // expected-note 4{{explicit instantiation definition is here}} + +extern template void X0::f(int&); // expected-error{{follows explicit instantiation definition}} +extern template struct X0::Inner; // expected-error{{follows explicit instantiation definition}} +extern template int X0::static_var; // expected-error{{follows explicit instantiation definition}} +extern template struct X0; // expected-error{{follows explicit instantiation definition}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp new file mode 100644 index 0000000..4ca5428 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class X { + template class Y {}; +}; + +class A { + class B {}; + class C {}; +}; + +// C++0x [temp.explicit] 14.7.2/11: +// The usual access checking rules do not apply to names used to specify +// explicit instantiations. +template class X::Y; + +// As an extension, this rule is applied to explicit specializations as well. +template <> class X::Y {}; diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp new file mode 100644 index 0000000..c756486 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +char* p = 0; +template T g(T x = &p) { return x; } +template int g(int); // OK even though &p isn't an int. + diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp new file mode 100644 index 0000000..1dfcf0c --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -Wc++11-compat %s + +// Example from the standard +template class Array { void mf() { } }; + +template class Array; +template void Array::mf(); +template void sort(Array& v) { /* ... */ } +template void sort(Array&); +namespace N { + template void f(T&) { } +} +template void N::f(int&); + + +template +struct X0 { + struct Inner {}; + void f() { } + static T value; +}; + +template +T X0::value = 17; + +typedef X0 XInt; + +template struct XInt::Inner; // expected-warning{{template-id}} +template void XInt::f(); // expected-warning{{template-id}} +template int XInt::value; // expected-warning{{template-id}} + +namespace N { + template + struct X1 { // expected-note{{explicit instantiation refers here}} + }; + + template + void f1(T) {} // expected-note{{explicit instantiation refers here}} +} +using namespace N; + +template struct X1; // expected-warning{{must occur in}} +template void f1(int); // expected-warning{{must occur in}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp new file mode 100644 index 0000000..1028830 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// If the name declared in the explicit instantiation is an +// unqualified name, the explicit instantiation shall appear in the +// namespace where its template is declared or, if that namespace is +// inline (7.3.1), any namespace from its enclosing namespace set. + +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; + }; + } + + template int X0::value = 17; + + struct X1 {}; + struct X2 {}; + + template void f(X1&); + template void f(X2&); + + template struct X0; + + template struct X0::MemberClass; + + template void X0::mem_func(); + + template struct X0::MemberClassTemplate; + + template void X0::mem_func_template(X1&); + + template int X0::value; +} + +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 +struct has_inline_namespaces::X0::MemberClassTemplate; + +template +void has_inline_namespaces::X0::mem_func_template(X3&); diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp new file mode 100644 index 0000000..38ae768 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s + +// A declaration of a function template shall be in scope at the point of the +// explicit instantiation of the function template. +template void f0(T); +template void f0(int); // okay +template void f0(T) { } + +// A definition of the class or class template containing a member function +// template shall be in scope at the point of the explicit instantiation of +// the member function template. +struct X0; // expected-note {{forward declaration}} +template struct X1; // expected-note 5{{declared here}} + +template void X0::f0(int); // expected-error {{incomplete type}} +template void X1::f0(int); // expected-error {{implicit instantiation of undefined template}} + +// A definition of a class template or class member template shall be in scope +// at the point of the explicit instantiation of the class template or class +// member template. +template struct X1; // expected-error{{explicit instantiation of undefined template}} + +template +struct X2 { // expected-note 4{{refers here}} + template + struct Inner; // expected-note{{declared here}} + + struct InnerClass; // expected-note{{forward declaration}} +}; + +template struct X2::Inner; // expected-error{{explicit instantiation of undefined template}} + +// A definition of a class template shall be in scope at the point of an +// explicit instantiation of a member function or a static data member of the +// class template. +template void X1::f1(int); // expected-error {{undefined template}} +template void X1::f1(int); // expected-error {{undefined template}} + +template int X1::member; // expected-error {{undefined template}} + +// A definition of a member class of a class template shall be in scope at the +// point of an explicit instantiation of the member class. +template struct X2::InnerClass; // expected-error{{undefined member}} + +// If the declaration of the explicit instantiation names an implicitly-declared +// special member function (Clause 12), the program is ill-formed. +template X2::X2(); // expected-error{{not an instantiation}} +template X2::X2(const X2&); // expected-error{{not an instantiation}} +template X2::~X2(); // expected-error{{not an instantiation}} +template X2 &X2::operator=(const X2&); // expected-error{{not an instantiation}} + + +// A definition of a class template is sufficient to explicitly +// instantiate a member of the class template which itself is not yet defined. +namespace PR7979 { + template struct S { + void f(); + static void g(); + static int i; + struct S2 { + void h(); + }; + }; + + template void S::f(); + template void S::g(); + template int S::i; + template void S::S2::h(); + + template void S::f() {} + template void S::g() {} + template int S::i; + template void S::S2::h() {} +} + +namespace PR11599 { + template class BasicStringPiece; // expected-note {{template is declared here}} + + extern template class BasicStringPiece; // expected-error{{explicit instantiation of undefined template 'PR11599::BasicStringPiece}} + template class BasicStringPiece; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp new file mode 100644 index 0000000..09c428e --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s + +template void f0(T); // expected-note{{here}} +template void f0(int); // expected-error{{explicit instantiation of undefined function template}} + +template +struct X0 { + struct Inner; + + void f1(); // expected-note{{here}} + + static T value; // expected-note{{here}} +}; + +template void X0::f1(); // expected-error{{explicit instantiation of undefined member function}} + +template int X0::value; // expected-error{{explicit instantiation of undefined static data member}} + +template<> void f0(long); // expected-note{{previous template specialization is here}} +template void f0(long); // expected-warning{{explicit instantiation of 'f0' that occurs after an explicit specialization will be ignored}} + +template<> void X0::f1(); // expected-note{{previous template specialization is here}} +template void X0::f1(); // expected-warning{{explicit instantiation of 'f1' that occurs after an explicit specialization will be ignored}} + +template<> struct X0::Inner; // expected-note{{previous template specialization is here}} +template struct X0::Inner; // expected-warning{{explicit instantiation of 'Inner' that occurs after an explicit specialization will be ignored}} + +template<> long X0::value; // expected-note{{previous template specialization is here}} +template long X0::value; // expected-warning{{explicit instantiation of 'value' that occurs after an explicit specialization will be ignored}} + +template<> struct X0; // expected-note{{previous template specialization is here}} +template struct X0; // expected-warning{{explicit instantiation of 'X0' that occurs after an explicit specialization will be ignored}} + +// PR 6458 +namespace test0 { + template class foo { + int compare(T x, T y); + }; + + template <> int foo::compare(char x, char y); + template int foo::compare(T x, T y) { + // invalid at T=char; if we get a diagnostic here, we're + // inappropriately instantiating this template. + void *ptr = x; + } + extern template class foo; // expected-warning {{extern templates are a C++11 extension}} + template class foo; +} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp new file mode 100644 index 0000000..8422c51 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s + +namespace N { + template class Y { // expected-note{{explicit instantiation refers here}} + void mf() { } + }; +} + +template class Z; // expected-error{{explicit instantiation of non-template class 'Z'}} + +// FIXME: This example from the standard is wrong; note posted to CWG reflector +// on 10/27/2009 +using N::Y; +template class Y; // expected-warning{{must occur in}} + +template class N::Y; +template void N::Y::mf(); diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp new file mode 100644 index 0000000..1382272 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template class Array { /* ... */ }; +template void sort(Array& v) { } + +// instantiate sort(Array&) - template-argument deduced +template void sort<>(Array&); + +template void sort(Array&); + +template void f0(T, U*) { } + +template void f0(int, float*); +template void f0<>(double, float*); + +template struct hash { }; +struct S { + bool operator==(const S&) const { return false; } +}; + +template struct Hash_map { + void Method(const T& x) { h(x); } + hash h; +}; + +Hash_map *x; +const Hash_map *foo() { + return x; +} + +template<> struct hash { + int operator()(const S& k) const { + return 0; + } +}; diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp new file mode 100644 index 0000000..7398dca --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template +struct X0 { + struct MemberClass { + T member; // expected-error{{with function type}} + }; + + T* f0(T* ptr) { + return ptr + 1; // expected-error{{pointer to the function}} + } + + static T* static_member; +}; + +template +T* X0::static_member = ((T*)0) + 1; // expected-error{{pointer to the function}} + +template class X0; // okay + +template class X0; // expected-note 3{{requested here}} + +// Specialize everything, so that the explicit instantiation does not trigger +// any diagnostics. +template<> +struct X0::MemberClass { }; + +typedef int int_long_func(long); +template<> +int_long_func *X0::f0(int_long_func *) { return 0; } + +template<> +int_long_func *X0::static_member; + +template class X0; + diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp new file mode 100644 index 0000000..550078a --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +template +struct X0 { + struct MemberClass; + + T* f0(T* ptr); + + static T* static_member; +}; + +template class X0; // ok; nothing gets instantiated. + +template +struct X0::MemberClass { + T member; +}; + +template +T* X0::f0(T* ptr) { + return ptr + 1; +} + +template +T* X0::static_member = 0; + +template class X0; // ok + + +template +struct X1 { + enum class E { + e = T::error // expected-error 2{{no members}} + }; +}; +template struct X1; // expected-note {{here}} + +extern template struct X1; // ok + +template struct X1; // expected-note {{here}} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp new file mode 100644 index 0000000..04e7df5 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp @@ -0,0 +1,66 @@ +// RUN: %clang_cc1 -O1 -emit-llvm -std=c++11 -o - %s | FileCheck %s + +template +struct X0 { + void f(T &t) { + t = 0; + } + + void g(T &t); + + void h(T &t); + + static T static_var; +}; + +template +inline void X0::g(T & t) { + t = 0; +} + +template +void X0::h(T & t) { + t = 0; +} + +template +T X0::static_var = 0; + +extern template struct X0; + +int *&test(X0 xi, int *ip) { + // CHECK: define available_externally void @_ZN2X0IPiE1fERS0_ + xi.f(ip); + // CHECK: define available_externally void @_ZN2X0IPiE1gERS0_ + xi.g(ip); + // CHECK: declare void @_ZN2X0IPiE1hERS0_ + xi.h(ip); + return X0::static_var; +} + +template +void f0(T& t) { + t = 0; +} + +template +inline void f1(T& t) { + t = 0; +} + +extern template void f0<>(int *&); +extern template void f1<>(int *&); + +void test_f0(int *ip, float *fp) { + // CHECK: declare void @_Z2f0IPiEvRT_ + f0(ip); + // CHECK: define linkonce_odr void @_Z2f0IPfEvRT_ + f0(fp); +} + +void test_f1(int *ip, float *fp) { + // CHECK: define available_externally void @_Z2f1IPiEvRT_ + f1(ip); + // CHECK: define linkonce_odr void @_Z2f1IPfEvRT_ + f1(fp); +} diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp new file mode 100644 index 0000000..8649017 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s + +template +struct X0 { + void f(T &t) { + t = 1; // expected-error{{incompatible type}} + } + + void g(T &t); + + void h(T &t); + + static T static_var; +}; + +template +inline void X0::g(T & t) { + t = 1; // expected-error{{incompatible type}} +} + +template +void X0::h(T & t) { + t = 1; +} + +template +T X0::static_var = 1; + +extern template struct X0; + +int *&test(X0 xi, int *ip) { + xi.f(ip); // expected-note{{instantiation}} + xi.g(ip); // expected-note{{instantiation}} + xi.h(ip); + return X0::static_var; +} + +template +void f0(T& t) { + t = 1; // expected-error{{incompatible type}} +} + +template +inline void f1(T& t) { + t = 1; // expected-error 2{{incompatible type}} +} + +extern template void f0<>(int *&); +extern template void f1<>(int *&); + +void test_f0(int *ip, float *fp) { + f0(ip); + f0(fp); // expected-note{{instantiation}} +} + +void test_f1(int *ip, float *fp) { + f1(ip); // expected-note{{instantiation}} + f1(fp); // expected-note{{instantiation}} +} diff --git a/clang/test/CXX/temp/temp.spec/temp.inst/p1.cpp b/clang/test/CXX/temp/temp.spec/temp.inst/p1.cpp new file mode 100644 index 0000000..8684fc4 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.inst/p1.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +// The implicit specialization of a class template specialuzation causes the +// implicit instantiation of the declarations, but not the definitions or +// default arguments, of: + +// FIXME: Many omitted cases + +// - scoped member enumerations +namespace ScopedEnum { + template struct ScopedEnum1 { + enum class E { + e = T::error // expected-error {{'double' cannot be used prior to '::'}} + }; + }; + ScopedEnum1 se1; // ok + + template struct ScopedEnum2 { + enum class E : T { // expected-error {{non-integral type 'void *' is an invalid underlying type}} + e = 0 + }; + }; + ScopedEnum2 se2; // expected-note {{here}} + + template struct UnscopedEnum3 { + enum class E : T { + e = 4 + }; + int arr[(int)E::e]; + }; + UnscopedEnum3 ue3; // ok + + ScopedEnum1::E e1; // ok + ScopedEnum1::E e2 = decltype(e2)::e; // expected-note {{in instantiation of enumeration 'ScopedEnum::ScopedEnum1::E' requested here}} + + // The behavior for enums defined within function templates is not clearly + // specified by the standard. We follow the rules for enums defined within + // class templates. + template + int f() { + enum class E { + e = T::error + }; + return (int)E(); + } + int test1 = f(); + + template + int g() { + enum class E { + e = T::error // expected-error {{has no members}} + }; + return E::e; // expected-note {{here}} + } + int test2 = g(); // expected-note {{here}} +} + +// And it cases the implicit instantiations of the definitions of: + +// - unscoped member enumerations +namespace UnscopedEnum { + template struct UnscopedEnum1 { + enum E { + e = T::error // expected-error {{'int' cannot be used prior to '::'}} + }; + }; + UnscopedEnum1 ue1; // expected-note {{here}} + + template struct UnscopedEnum2 { + enum E : T { // expected-error {{non-integral type 'void *' is an invalid underlying type}} + e = 0 + }; + }; + UnscopedEnum2 ue2; // expected-note {{here}} + + template struct UnscopedEnum3 { + enum E : T { + e = 4 + }; + int arr[E::e]; + }; + UnscopedEnum3 ue3; // ok + + template + int f() { + enum E { + e = T::error // expected-error {{has no members}} + }; + return (int)E(); + } + int test1 = f(); // expected-note {{here}} + + template + int g() { + enum E { + e = T::error // expected-error {{has no members}} + }; + return E::e; + } + int test2 = g(); // expected-note {{here}} +} + +// FIXME: +//- - member anonymous unions diff --git a/clang/test/CXX/temp/temp.spec/temp.inst/p11.cpp b/clang/test/CXX/temp/temp.spec/temp.inst/p11.cpp new file mode 100644 index 0000000..8184071 --- /dev/null +++ b/clang/test/CXX/temp/temp.spec/temp.inst/p11.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify -emit-llvm-only %s + +// rdar://problem/7838962 +namespace test0 { + template unsigned f0() { + return T::MaxSize; // expected-error {{'int' cannot be used prior to '::'}} + }; + template struct A { + void Allocate(unsigned Alignment + = f0()) // expected-note {{in instantiation}} + {} + }; + void f1(A x) { x.Allocate(); } + +} -- cgit v1.2.3