forked from OSchip/llvm-project
442 lines
15 KiB
C++
442 lines
15 KiB
C++
// 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>;
|
|
}
|
|
}
|
|
|
|
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}}
|
|
}
|