llvm-project/clang/test/SemaCXX/cxx1y-variable-templates_to...

461 lines
16 KiB
C++
Raw Normal View History

// 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> extern 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 {
template<typename T, typename> T v; // expected-note {{previous template declaration is here}}
template<typename T> T v; // expected-error {{too few template parameters in template redeclaration}} expected-note {{previous template declaration is here}}
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 declaration is here}}
template<typename T> extern int v; // expected-error {{redeclaration 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 {{redeclaration 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 {{insert an explicit cast to silence this issue}}
#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); // expected-note {{explicitly specialized declaration is here}}
#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 {{variable template specialization of 'pi1a' must originally be declared in namespace 'n1'}}
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>;
}
}
namespace nested_name {
template<typename T> int a; // expected-note {{variable template 'a' declared here}}
a<int>::b c; // expected-error {{qualified name refers into a specialization of variable template 'a'}}
class a<int> {}; // expected-error {{identifier followed by '<' indicates a class template specialization but 'a' refers to a variable template}}
enum a<int> {}; // expected-error {{expected identifier or '{'}} expected-warning {{does not declare anything}}
}
namespace PR18530 {
template<typename T> int a;
int a<int>; // expected-error {{requires 'template<>'}}
}
namespace PR19152 {
#ifndef PRECXX11
template<typename T> const auto x = 1;
static_assert(x<int> == 1, "");
#endif
}
namespace PR19169 {
template <typename T> int* f();
template <typename T> void f();
template<> int f<double>; // expected-error {{no variable template matches specialization; did you mean to use 'f' as function template instead?}}
template <typename T> void g();
template<> int g<double>; // expected-error {{no variable template matches specialization; did you mean to use 'g' as function template instead?}}
}