233 lines
11 KiB
C++
233 lines
11 KiB
C++
|
// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -verify %s
|
||
|
|
||
|
template <typename T> struct A { // expected-note 38{{declared here}}
|
||
|
constexpr A() {}
|
||
|
constexpr A(int) {}
|
||
|
constexpr operator int() { return 0; }
|
||
|
};
|
||
|
A() -> A<int>;
|
||
|
A(int) -> A<int>;
|
||
|
|
||
|
// Make sure we still correctly parse cases where a template can appear without arguments.
|
||
|
namespace template_template_arg {
|
||
|
template<template<typename> typename> struct X {};
|
||
|
template<typename> struct Y {};
|
||
|
|
||
|
X<A> xa;
|
||
|
Y<A> ya; // expected-error {{requires template arguments}}
|
||
|
X<::A> xcca;
|
||
|
Y<::A> ycca; // expected-error {{requires template arguments}}
|
||
|
X<A*> xap; // expected-error {{requires template arguments}}
|
||
|
X<const A> xca; // expected-error {{requires template arguments}}
|
||
|
X<A const> xac; // expected-error {{requires template arguments}}
|
||
|
// FIXME: This should not parse as a template template argument due to the
|
||
|
// trailing attributes.
|
||
|
X<A [[]]> xa_attr;
|
||
|
|
||
|
template<template<typename> typename = A> struct XD {};
|
||
|
template<typename = A> struct YD {}; // expected-error {{requires template arguments}}
|
||
|
template<template<typename> typename = ::A> struct XCCD {};
|
||
|
template<typename = ::A> struct YCCD {}; // expected-error {{requires template arguments}}
|
||
|
|
||
|
// FIXME: replacing the invalid type with 'int' here is horrible
|
||
|
template <A a = A<int>()> class C { }; // expected-error {{requires template arguments}}
|
||
|
template<typename T = A> struct G { }; // expected-error {{requires template arguments}}
|
||
|
}
|
||
|
|
||
|
namespace template_template_arg_pack {
|
||
|
template<template<typename> typename...> struct XP {};
|
||
|
template<typename...> struct YP {};
|
||
|
|
||
|
struct Z { template<typename T> struct Q {}; }; // expected-note 2{{here}}
|
||
|
|
||
|
template<typename T> using ZId = Z;
|
||
|
|
||
|
template<typename ...Ts> struct A {
|
||
|
XP<ZId<Ts>::Q...> xe;
|
||
|
YP<ZId<Ts>::Q...> ye; // expected-error {{requires template arguments}}
|
||
|
|
||
|
XP<ZId<Ts>::Q> xp; // expected-error {{unexpanded parameter pack}}
|
||
|
YP<ZId<Ts>::Q> yp; // expected-error {{requires template arguments}}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
namespace injected_class_name {
|
||
|
template<typename T> struct A {
|
||
|
A(T);
|
||
|
void f(int) { // expected-note {{previous}}
|
||
|
A a = 1;
|
||
|
injected_class_name::A b = 1; // expected-note {{in instantiation of template class 'injected_class_name::A<int>'}}
|
||
|
}
|
||
|
void f(T); // expected-error {{multiple overloads of 'f' instantiate to the same signature 'void (int)}}
|
||
|
};
|
||
|
A<short> ai = 1;
|
||
|
A<double>::A b(1); // expected-error {{constructor name}}
|
||
|
}
|
||
|
|
||
|
struct member {
|
||
|
A a; // expected-error {{requires template arguments}}
|
||
|
A *b; // expected-error {{requires template arguments}}
|
||
|
const A c; // expected-error {{requires template arguments}}
|
||
|
|
||
|
void f() throw (A); // expected-error {{requires template arguments}}
|
||
|
|
||
|
friend A; // expected-error {{requires template arguments; argument deduction not allowed in friend declaration}}
|
||
|
|
||
|
operator A(); // expected-error {{requires template arguments; argument deduction not allowed in conversion function type}}
|
||
|
|
||
|
static A x; // expected-error {{declaration of variable 'x' with deduced type 'A' requires an initializer}}
|
||
|
static constexpr A y = 0;
|
||
|
};
|
||
|
|
||
|
namespace in_typedef {
|
||
|
typedef A *AutoPtr; // expected-error {{requires template arguments; argument deduction not allowed in typedef}}
|
||
|
typedef A (*PFun)(int a); // expected-error{{requires template arguments; argument deduction not allowed in typedef}}
|
||
|
typedef A Fun(int a) -> decltype(a + a); // expected-error{{requires template arguments; argument deduction not allowed in function return type}}
|
||
|
}
|
||
|
|
||
|
namespace stmt {
|
||
|
void g(A a) { // expected-error{{requires template arguments; argument deduction not allowed in function prototype}}
|
||
|
try { }
|
||
|
catch (A &a) { } // expected-error{{requires template arguments; argument deduction not allowed in exception declaration}}
|
||
|
catch (const A a) { } // expected-error{{requires template arguments; argument deduction not allowed in exception declaration}}
|
||
|
try { } catch (A a) { } // expected-error{{requires template arguments; argument deduction not allowed in exception declaration}}
|
||
|
|
||
|
// FIXME: The standard only permits class template argument deduction in a
|
||
|
// simple-declaration or cast. We also permit it in conditions,
|
||
|
// for-range-declarations, member-declarations for static data members, and
|
||
|
// new-expressions, because not doing so would be bizarre.
|
||
|
A local = 0;
|
||
|
static A local_static = 0;
|
||
|
static thread_local A thread_local_static = 0;
|
||
|
if (A a = 0) {}
|
||
|
if (A a = 0; a) {}
|
||
|
switch (A a = 0) {} // expected-warning {{no case matching constant switch condition '0'}}
|
||
|
switch (A a = 0; a) {} // expected-warning {{no case matching constant switch condition '0'}}
|
||
|
for (A a = 0; a; /**/) {}
|
||
|
for (/**/; A a = 0; /**/) {}
|
||
|
while (A a = 0) {}
|
||
|
int arr[3];
|
||
|
for (A a : arr) {}
|
||
|
}
|
||
|
|
||
|
namespace std {
|
||
|
class type_info;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
namespace expr {
|
||
|
template<typename T> struct U {};
|
||
|
void j() {
|
||
|
(void)typeid(A); // expected-error{{requires template arguments; argument deduction not allowed here}}
|
||
|
(void)sizeof(A); // expected-error{{requires template arguments; argument deduction not allowed here}}
|
||
|
(void)__alignof(A); // expected-error{{requires template arguments; argument deduction not allowed here}}
|
||
|
|
||
|
U<A> v; // expected-error {{requires template arguments}}
|
||
|
|
||
|
int n;
|
||
|
(void)dynamic_cast<A&>(n); // expected-error{{requires template arguments; argument deduction not allowed here}}
|
||
|
(void)static_cast<A*>(&n); // expected-error{{requires template arguments; argument deduction not allowed here}}
|
||
|
(void)reinterpret_cast<A*>(&n); // expected-error{{requires template arguments; argument deduction not allowed here}}
|
||
|
(void)const_cast<A>(n); // expected-error{{requires template arguments; argument deduction not allowed here}}
|
||
|
(void)*(A*)(&n); // expected-error{{requires template arguments; argument deduction not allowed here}}
|
||
|
(void)(A)(n); // expected-error{{requires template arguments; argument deduction not allowed here}}
|
||
|
(void)(A){n}; // expected-error{{requires template arguments; argument deduction not allowed here}}
|
||
|
|
||
|
(void)A(n);
|
||
|
(void)A{n};
|
||
|
(void)new A(n);
|
||
|
(void)new A{n};
|
||
|
(void)new A;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
namespace decl {
|
||
|
enum E : A {}; // expected-error{{requires template arguments; argument deduction not allowed here}}
|
||
|
struct F : A {}; // expected-error{{expected class name}}
|
||
|
|
||
|
using B = A; // expected-error{{requires template arguments}}
|
||
|
|
||
|
auto k() -> A; // expected-error{{requires template arguments}}
|
||
|
|
||
|
A a;
|
||
|
A b = 0;
|
||
|
const A c = 0;
|
||
|
A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}}
|
||
|
A *p = 0; // expected-error {{cannot form pointer to deduced class template specialization type}}
|
||
|
A &r = *p; // expected-error {{cannot form reference to deduced class template specialization type}}
|
||
|
A arr[3] = 0; // expected-error {{cannot form array of deduced class template specialization type}}
|
||
|
A F::*pm = 0; // expected-error {{cannot form pointer to deduced class template specialization type}}
|
||
|
A (*fp)() = 0; // expected-error {{cannot form function returning deduced class template specialization type}}
|
||
|
A [x, y] = 0; // expected-error {{cannot be declared with type 'A'}} expected-error {{type 'A<int>' decomposes into 0 elements, but 2 names were provided}}
|
||
|
}
|
||
|
|
||
|
namespace typename_specifier {
|
||
|
struct F {};
|
||
|
|
||
|
void e() {
|
||
|
(void) typename ::A(0);
|
||
|
(void) typename ::A{0};
|
||
|
new typename ::A(0);
|
||
|
new typename ::A{0};
|
||
|
typename ::A a = 0;
|
||
|
const typename ::A b = 0;
|
||
|
if (typename ::A a = 0) {}
|
||
|
for (typename ::A a = 0; typename ::A b = 0; /**/) {}
|
||
|
|
||
|
(void)(typename ::A)(0); // expected-error{{requires template arguments; argument deduction not allowed here}}
|
||
|
(void)(typename ::A){0}; // expected-error{{requires template arguments; argument deduction not allowed here}}
|
||
|
}
|
||
|
typename ::A a = 0;
|
||
|
const typename ::A b = 0;
|
||
|
typename ::A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}}
|
||
|
typename ::A *p = 0; // expected-error {{cannot form pointer to deduced class template specialization type}}
|
||
|
typename ::A &r = *p; // expected-error {{cannot form reference to deduced class template specialization type}}
|
||
|
typename ::A arr[3] = 0; // expected-error {{cannot form array of deduced class template specialization type}}
|
||
|
typename ::A F::*pm = 0; // expected-error {{cannot form pointer to deduced class template specialization type}}
|
||
|
typename ::A (*fp)() = 0; // expected-error {{cannot form function returning deduced class template specialization type}}
|
||
|
typename ::A [x, y] = 0; // expected-error {{cannot be declared with type 'typename ::A'}} expected-error {{type 'typename ::A<int>' (aka 'A<int>') decomposes into 0}}
|
||
|
|
||
|
struct X { template<typename T> struct A { A(T); }; }; // expected-note 8{{declared here}}
|
||
|
|
||
|
template<typename T> void f() {
|
||
|
(void) typename T::A(0);
|
||
|
(void) typename T::A{0};
|
||
|
new typename T::A(0);
|
||
|
new typename T::A{0};
|
||
|
typename T::A a = 0;
|
||
|
const typename T::A b = 0;
|
||
|
if (typename T::A a = 0) {} // expected-error {{value of type 'typename X::A<int>' (aka 'typename_specifier::X::A<int>') is not contextually convertible to 'bool'}}
|
||
|
for (typename T::A a = 0; typename T::A b = 0; /**/) {} // expected-error {{value of type 'typename X::A<int>' (aka 'typename_specifier::X::A<int>') is not contextually convertible to 'bool'}}
|
||
|
|
||
|
{(void)(typename T::A)(0);} // expected-error{{refers to class template member}}
|
||
|
{(void)(typename T::A){0};} // expected-error{{refers to class template member}}
|
||
|
{typename T::A (parens) = 0;} // expected-error {{refers to class template member in 'typename_specifier::X'; argument deduction not allowed here}}
|
||
|
// expected-warning@-1 {{disambiguated as redundant parentheses around declaration of variable named 'parens'}} expected-note@-1 {{add a variable name}} expected-note@-1{{remove parentheses}} expected-note@-1 {{add enclosing parentheses}}
|
||
|
{typename T::A *p = 0;} // expected-error {{refers to class template member}}
|
||
|
{typename T::A &r = *p;} // expected-error {{refers to class template member}}
|
||
|
{typename T::A arr[3] = 0;} // expected-error {{refers to class template member}}
|
||
|
{typename T::A F::*pm = 0;} // expected-error {{refers to class template member}}
|
||
|
{typename T::A (*fp)() = 0;} // expected-error {{refers to class template member}}
|
||
|
{typename T::A [x, y] = 0;} // expected-error {{cannot be declared with type 'typename T::A'}} expected-error {{type 'typename X::A<int>' (aka 'typename_specifier::X::A<int>') decomposes into 0}}
|
||
|
}
|
||
|
template void f<X>(); // expected-note {{instantiation of}}
|
||
|
|
||
|
template<typename T> void g(typename T::A = 0); // expected-note {{refers to class template member}}
|
||
|
void h() { g<X>(); } // expected-error {{no matching function}}
|
||
|
}
|
||
|
|
||
|
namespace parenthesized {
|
||
|
template<typename T> struct X { X(T); };
|
||
|
auto n = (X([]{}));
|
||
|
}
|
||
|
|
||
|
namespace within_template_arg_list {
|
||
|
template<typename T> struct X { constexpr X(T v) : v(v) {} T v; };
|
||
|
template<int N = X(1).v> struct Y {};
|
||
|
using T = Y<>;
|
||
|
using T = Y<X(1).v>;
|
||
|
using T = Y<within_template_arg_list::X(1).v>;
|
||
|
|
||
|
template<int ...N> struct Z { Y<X(N)...> y; };
|
||
|
}
|