diff options
Diffstat (limited to 'test/SemaCXX/cxx1y-variable-templates_top_level.cpp')
-rw-r--r-- | test/SemaCXX/cxx1y-variable-templates_top_level.cpp | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp new file mode 100644 index 0000000..b6e8762 --- /dev/null +++ b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -0,0 +1,434 @@ +// RUN: %clang_cc1 -verify -fsyntax-only -Wno-c++11-extensions -Wno-c++1y-extensions %s -DPRECXX11 +// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s + +#ifdef PRECXX11 + #define CONST const +#else + #define CONST constexpr +#endif + +template<typename T> +T pi = T(3.1415926535897932385); // expected-note {{template is declared here}} + +template<typename T> +CONST T cpi = T(3.1415926535897932385); // expected-note {{template is declared here}} + +template<typename T> extern CONST T vc; +#ifndef PRECXX11 +// expected-error@-2 {{constexpr variable declaration must be a definition}} +#endif + +namespace use_in_top_level_funcs { + + void good() { + int ipi = pi<int>; + int icpi = cpi<int>; + double dpi = pi<double>; + double dcpi = cpi<double>; + } + + void no_deduce() { + // template arguments are not deduced for uses of variable templates. + int ipi = pi; // expected-error {{cannot refer to variable template 'pi' without a template argument list}} + int icpi = cpi; // expected-error {{cannot refer to variable template 'cpi' without a template argument list}} + } + + template<typename T> + T circular_area(T r) { + return pi<T> * r * r; + } + + template<typename T> + CONST T const_circular_area(T r) { + return cpi<T> * r * r; + } + + double use_circular_area(double r) { + CONST float t = const_circular_area(2.0) - 12; +#ifndef PRECXX11 + static_assert(const_circular_area(2) == 12, ""); + CONST int test = (t > 0) && (t < 1); + static_assert(test, ""); +#endif + return circular_area(r); + } +} + +namespace shadow { + void foo() { + int ipi0 = pi<int>; + int pi; + int a = pi; + int ipi = pi<int>; // expected-error {{expected '(' for function-style cast or type construction}} \ + // expected-error {{expected expression}} + } +} + +namespace odr_tmpl { + namespace pv_cvt { + int v; // expected-note {{previous definition is here}} + template<typename T> T v; // expected-error {{redefinition of 'v' as different kind of symbol}} + } + namespace pvt_cv { + template<typename T> T v; // expected-note {{previous definition is here}} + int v; // expected-error {{redefinition of 'v' as different kind of symbol}} + } + namespace pvt_cvt { + template<typename T> T v0; // expected-note {{previous definition is here}} + template<typename T> T v0; // expected-error {{redefinition of 'v0'}} + + template<typename T> T v; // expected-note {{previous definition is here}} + template<typename T> int v; // expected-error {{redefinition of 'v'}} + + template<typename T> int v1; // expected-note {{previous template declaration is here}} + template<int I> int v1; // expected-error {{template parameter has a different kind in template redeclaration}} + } + namespace pvt_use { + template<typename T> T v; + v = 10; // expected-error {{C++ requires a type specifier for all declarations}} + } + + namespace pvt_diff_params { + // FIXME: (?) Redefinitions should simply be not allowed, whether the + // template parameters match or not. However, this current behaviour also + // matches that of class templates... + template<typename T, typename> T v; // expected-note 2{{previous template declaration is here}} + template<typename T> T v; // expected-error {{too few template parameters in template redeclaration}} + template<typename T, typename, typename> T v; // expected-error {{too many template parameters in template redeclaration}} + } + + namespace pvt_extern { + template<typename T> T v = T(); + template<typename T> extern T v; // redeclaration is allowed \ + // expected-note {{previous definition is here}} + template<typename T> extern int v; // expected-error {{redefinition of 'v' with a different type: 'int' vs 'T'}} + +#ifndef PRECXX11 + template<typename T> extern auto v; // expected-error {{declaration of variable 'v' with type 'auto' requires an initializer}} +#endif + + template<typename T> T var = T(); // expected-note {{previous definition is here}} + extern int var; // expected-error {{redefinition of 'var' as different kind of symbol}} + } + +#ifndef PRECXX11 + namespace pvt_auto { + template<typename T> auto v0; // expected-error {{declaration of variable 'v0' with type 'auto' requires an initializer}} + template<typename T> auto v1 = T(); // expected-note {{previous definition is here}} + template<typename T> int v1; // expected-error {{redefinition of 'v1' with a different type: 'int' vs 'auto'}} + template<typename T> auto v2 = T(); // expected-note {{previous definition is here}} + template<typename T> T v2; // expected-error {{redefinition of 'v2'}} + template<typename T> auto v3 = T(); // expected-note {{previous definition is here}} + template<typename T> extern T v3; // expected-error {{redefinition of 'v3' with a different type: 'T' vs 'auto'}} + template<typename T> auto v4 = T(); + template<typename T> extern auto v4; // expected-error {{declaration of variable 'v4' with type 'auto' requires an initializer}} + } +#endif + +} + +namespace explicit_instantiation { + template<typename T> + T pi0a = T(3.1415926535897932385); // expected-note {{variable template 'pi0a' declared here}} + template float pi0a<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0a' does not match expected type 'int'}} + + template<typename T> + T pi0b = T(3.1415926535897932385); // expected-note {{variable template 'pi0b' declared here}} + template CONST int pi0b<int>; // expected-error {{type 'const int' of explicit instantiation of 'pi0b' does not match expected type 'int'}} + + template<typename T> + T pi0c = T(3.1415926535897932385); // expected-note {{variable template 'pi0c' declared here}} + template int pi0c<const int>; // expected-error {{type 'int' of explicit instantiation of 'pi0c' does not match expected type 'const int'}} + + template<typename T> + T pi0 = T(3.1415926535897932385); + template int pi0<int>; // expected-note {{previous explicit instantiation is here}} + template int pi0<int>; // expected-error {{duplicate explicit instantiation of 'pi0<int>'}} + + template<typename T> + CONST T pi1a = T(3.1415926535897932385); // expected-note {{variable template 'pi1a' declared here}} + template int pi1a<int>; // expected-error {{type 'int' of explicit instantiation of 'pi1a' does not match expected type 'const int'}} + + template<typename T> + CONST T pi1b = T(3.1415926535897932385); // expected-note {{variable template 'pi1b' declared here}} + template int pi1b<const int>; // expected-error {{type 'int' of explicit instantiation of 'pi1b' does not match expected type 'const const int'}} + + template<typename T> + CONST T pi1 = T(3.1415926535897932385); + template CONST int pi1<int>; // expected-note {{previous explicit instantiation is here}} + template CONST int pi1<int>; // expected-error {{duplicate explicit instantiation of 'pi1<int>'}} + +#ifndef PRECXX11 + namespace auto_var { + template<typename T> auto var0 = T(); + template auto var0<int>; // expected-error {{'auto' variable template instantiation is not allowed}} + + template<typename T> auto var = T(); + template int var<int>; + } +#endif + + template<typename=int> int missing_args; // expected-note {{here}} + template int missing_args; // expected-error {{must specify a template argument list}} + + namespace extern_var { + // TODO: + } +} + +namespace explicit_specialization { + + namespace good { + template<typename T1, typename T2> + CONST int pi2 = 1; + + template<typename T> + CONST int pi2<T,int> = 2; + + template<typename T> + CONST int pi2<int,T> = 3; + + template<> CONST int pi2<int,int> = 4; + +#ifndef PRECXX11 + void foo() { + static_assert(pi2<int,int> == 4, ""); + static_assert(pi2<float,int> == 2, ""); + static_assert(pi2<int,float> == 3, ""); + static_assert(pi2<int,float> == pi2<int,double>, ""); + static_assert(pi2<float,float> == 1, ""); + static_assert(pi2<float,float> == pi2<float,double>, ""); + } +#endif + } + + namespace ambiguous { + + template<typename T1, typename T2> + CONST int pi2 = 1; + + template<typename T> + CONST int pi2<T,int> = 2; // expected-note {{partial specialization matches [with T = int]}} + + template<typename T> + CONST int pi2<int,T> = 3; // expected-note {{partial specialization matches [with T = int]}} + + void foo() { + int a = pi2<int,int>; // expected-error {{ambiguous partial specializations of 'pi2<int, int>'}} + } + } + + namespace type_changes { + + template<typename T> + T pi0 = T(3.1415926535897932385); + + template<> float pi0<int> = 10; + template<> int pi0<const int> = 10; + + template<typename T> + T pi1 = T(3.1415926535897932385); + template<> CONST int pi1<int> = 10; + + template<typename T> + T pi2 = T(3.1415926535897932385); + template<> int pi2<const int> = 10; + + template<typename T> + CONST T pi4 = T(3.1415926535897932385); + template<> int pi4<int> = 10; + } + + namespace redefinition { + template<typename T> + T pi0 = T(3.1415926535897932385); + + template<> int pi0<int> = 10; // expected-note 3{{previous definition is here}} +#ifndef PRECXX11 +// expected-note@-2 {{previous definition is here}} +#endif + template<> int pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}} + template<> CONST int pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'const int' vs 'int'}} + template<> float pi0<int> = 10; // expected-error {{redefinition of 'pi0' with a different type: 'float' vs 'int'}} +#ifndef PRECXX11 + template<> auto pi0<int> = 10; // expected-error {{redefinition of 'pi0<int>'}} +#endif + + + template<typename T> + CONST T pi1 = T(3.1415926535897932385); + + template<> CONST int pi1<int> = 10; // expected-note {{previous definition is here}} + template<> CONST int pi1<int> = 10; // expected-error {{redefinition of 'pi1<int>'}} + } + + namespace before_instantiation { + template<typename T> + T pi0 = T(3.1415926535897932385); // expected-note {{variable template 'pi0' declared here}} + + template<> int pi0<int> = 10; + template int pi0<int>; + template float pi0<int>; // expected-error {{type 'float' of explicit instantiation of 'pi0' does not match expected type}} + + template<typename T1, typename T2> + CONST int pi2 = 1; + + template<typename T> CONST int pi2<T,int> = 2; + template CONST int pi2<int,int>; + } + namespace after_instantiation { + template<typename T> + T pi0 = T(3.1415926535897932385); + + template int pi0<int>; // expected-note 2{{explicit instantiation first required here}} + template<> int pi0<int> = 10; // expected-error {{explicit specialization of 'pi0' after instantiation}} + template<> float pi0<int>; // expected-error {{explicit specialization of 'pi0' after instantiation}} + + template<typename T1, typename T2> + CONST int pi2 = 1; + + template CONST int pi2<int,int>; + template<typename T> CONST int pi2<T,int> = 2; + } + +#ifndef PRECXX11 + namespace auto_var { + template<typename T, typename> auto var0 = T(); + template<typename T> auto var0<T,int> = T(); + template<> auto var0<int,int> = 7; + + template<typename T, typename> auto var = T(); + template<typename T> T var<T,int> = T(5); + template<> int var<int,int> = 7; + + void foo() { + int i0 = var0<int,int>; + int b = var<int,int>; + } + } +#endif + + namespace extern_var { + // TODO: + } + + namespace diff_type { + // TODO: + template<typename T> T* var = new T(); +#ifndef PRECXX11 + template<typename T> auto var<T*> = T(); // expected-note {{previous definition is here}} + template<typename T> T var<T*> = T(); // expected-error {{redefinition of 'var' with a different type: 'T' vs 'auto'}} +#endif + } +} + +namespace narrowing { + template<typename T> T v = {1234}; // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1234 to}} +#ifndef PRECXX11 + // expected-error@-2 {{constant expression evaluates to 1234 which cannot be narrowed to type 'char'}}\ + // expected-note@-2 {{override this message by inserting an explicit cast}} +#endif + int k = v<char>; // expected-note {{in instantiation of variable template specialization 'narrowing::v<char>' requested here}} +} + +namespace use_in_structs { + // TODO: +} + +namespace attributes { + // TODO: +} + +#ifndef PRECXX11 +namespace arrays { + template<typename T> + T* arr = new T[10]{T(10), T(23)}; + + float f = 10.5; + template<> float* arr<float> = &f; + + void bar() { + int *iarr = arr<int>; + iarr[0] = 1; + iarr[2] = 3; + iarr[6] = -2; + + float ff = *arr<float>; + float nof = arr<float>[3]; // No bounds-check in C++ + } +} +#endif + +namespace nested { + + namespace n0a { + template<typename T> + T pi0a = T(3.1415926535897932385); + } + + using namespace n0a; + int i0a = pi0a<int>; + + template float pi0a<float>; + float f0a = pi0a<float>; + + template<> double pi0a<double> = 5.2; + double d0a = pi0a<double>; + + namespace n0b { + template<typename T> + T pi0b = T(3.1415926535897932385); + } + + int i0b = n0b::pi0b<int>; + + template float n0b::pi0b<float>; + float f0b = n0b::pi0b<float>; + + template<> double n0b::pi0b<double> = 5.2; + double d0b = n0b::pi0b<double>; + + namespace n1 { + template<typename T> + T pi1a = T(3.1415926535897932385); +#ifndef PRECXX11 +// expected-note@-2 {{explicit instantiation refers here}} +#endif + + template<typename T> + T pi1b = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}} +#ifndef PRECXX11 +// expected-note@-2 {{explicit instantiation refers here}} +#endif + } + + namespace use_n1a { + using namespace n1; + int i1 = pi1a<int>; + + template float pi1a<float>; +#ifndef PRECXX11 +// expected-error@-2 {{explicit instantiation of 'pi1a<float>' not in a namespace enclosing 'n1'}} +#endif + float f1 = pi1a<float>; + + template<> double pi1a<double> = 5.2; // expected-error {{no variable template matches specialization}} + double d1 = pi1a<double>; + } + + namespace use_n1b { + int i1 = n1::pi1b<int>; + + template float n1::pi1b<float>; +#ifndef PRECXX11 +// expected-error@-2 {{explicit instantiation of 'pi1b<float>' not in a namespace enclosing 'n1'}} +#endif + float f1 = n1::pi1b<float>; + + template<> double n1::pi1b<double> = 5.2; // expected-error {{cannot define or redeclare 'pi1b' here because namespace 'use_n1b' does not enclose namespace 'n1'}} \ + // expected-error {{variable template specialization of 'pi1b' must originally be declared in namespace 'n1'}} + double d1 = n1::pi1b<double>; + } +} + |