diff options
author | Larisse Voufo <lvoufo@google.com> | 2013-08-06 01:03:05 +0000 |
---|---|---|
committer | Larisse Voufo <lvoufo@google.com> | 2013-08-06 01:03:05 +0000 |
commit | 39a1e507ff0bef4bd6b2fdbab4e38583d2679617 (patch) | |
tree | 93b6d63dcb7906152a4879eeaf765de5852aacd4 /clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp | |
parent | 6f7213cb93a3a6fe4e3dbbee0c1f0d2b34821523 (diff) | |
download | bcm5719-llvm-39a1e507ff0bef4bd6b2fdbab4e38583d2679617.tar.gz bcm5719-llvm-39a1e507ff0bef4bd6b2fdbab4e38583d2679617.zip |
Started implementing variable templates. Top level declarations should be fully supported, up to some limitations documented as FIXMEs or TODO. Static data member templates work very partially. Static data member templates of class templates need particular attention...
llvm-svn: 187762
Diffstat (limited to 'clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp')
-rw-r--r-- | clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp | 415 |
1 files changed, 415 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp new file mode 100644 index 00000000000..66ee4e1d4ab --- /dev/null +++ b/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -0,0 +1,415 @@ +// RUN: %clang_cc1 -verify -fsyntax-only -Wno-c++11-extensions -Wno-c++1y-extensions %s +// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -Wno-c++1y-extensions %s -DCXX11 +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s -DCXX11 + +#ifdef CXX11 + #define CONST constexpr +#else + #define CONST const +#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}} + +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; +#ifdef CXX11 + 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' with a different type: 'int' vs 'T'}} + } + 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'}} + +#ifdef CXX11 + template<typename T> extern auto v; // expected-error {{declaration of variable 'v' with type 'auto' requires an initializer}} +#endif + } + +#ifdef CXX11 + 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>'}} + +#ifdef CXX11 + 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 + + 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; + +#ifdef CXX11 + 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}} +#ifdef CXX11 +// 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'}} +#ifdef CXX11 + 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; + } + +#ifdef CXX11 + 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 = T(); + template<typename T> T* var<T> = new T(); +#ifdef CXX11 + 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 use_in_structs { + // TODO: +} + +namespace attributes { + // TODO: +} + +#ifdef CXX11 +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); +#ifdef CXX11 +// expected-note@-2 {{explicit instantiation refers here}} +#endif + + template<typename T> + T pi1b = T(3.1415926535897932385); // expected-note {{explicitly specialized declaration is here}} +#ifdef CXX11 +// expected-note@-2 {{explicit instantiation refers here}} +#endif + } + + namespace use_n1a { + using namespace n1; + int i1 = pi1a<int>; + + template float pi1a<float>; +#ifdef CXX11 +// 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>; +#ifdef CXX11 +// 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>; + } +} + |