This fixes the core issue described in P3579, following the design intent of P0522 to not introduce any new cases where a template template parameter match is allowed for a template which is not valid for all possible uses. With this patch, narrowing conversions are disallowed for TTP matching. This reuses the existing machinery for diagnosing narrowing in a converted constant expression. Since P0522 is a DR and we apply it all the way back to C++98, this brings that machinery to use in older standards, in this very narrow scope of TTP matching. This still doesn't solve the ambiguity when partial ordering NTTPs of different integral types, this is blocked by a different bug which will be fixed in a subsequent patch (but the test cases are added).
171 lines
3.6 KiB
C++
171 lines
3.6 KiB
C++
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
|
class A;
|
|
|
|
class S {
|
|
public:
|
|
template<typename T> struct A {
|
|
struct Nested {
|
|
typedef T type;
|
|
};
|
|
};
|
|
};
|
|
|
|
int i;
|
|
S::A<int>::Nested::type *ip = &i;
|
|
|
|
template<typename T>
|
|
struct Outer {
|
|
template<typename U>
|
|
class Inner0;
|
|
|
|
template<typename U>
|
|
class Inner1 {
|
|
struct ReallyInner;
|
|
|
|
T foo(U);
|
|
template<typename V> T bar(V);
|
|
template<typename V> T* bar(V);
|
|
|
|
static T value1;
|
|
static U value2;
|
|
};
|
|
};
|
|
|
|
template<typename X>
|
|
template<typename Y>
|
|
class Outer<X>::Inner0 {
|
|
public:
|
|
void f(X, Y);
|
|
};
|
|
|
|
template<typename X>
|
|
template<typename Y>
|
|
void Outer<X>::Inner0<Y>::f(X, Y) {
|
|
}
|
|
|
|
template<typename X>
|
|
template<typename Y>
|
|
struct Outer<X>::Inner1<Y>::ReallyInner {
|
|
static Y value3;
|
|
|
|
void g(X, Y);
|
|
};
|
|
|
|
template<typename X>
|
|
template<typename Y>
|
|
void Outer<X>::Inner1<Y>::ReallyInner::g(X, Y) {
|
|
}
|
|
|
|
template<typename X>
|
|
template<typename Y>
|
|
X Outer<X>::Inner1<Y>::foo(Y) {
|
|
return X();
|
|
}
|
|
|
|
template<typename X>
|
|
template<typename Y>
|
|
template<typename Z>
|
|
X Outer<X>::Inner1<Y>::bar(Z) {
|
|
return X();
|
|
}
|
|
|
|
template<typename X>
|
|
template<typename Y>
|
|
template<typename Z>
|
|
X* Outer<X>::Inner1<Y>::bar(Z) {
|
|
return 0;
|
|
}
|
|
|
|
template<typename X>
|
|
template<typename Y>
|
|
X Outer<X>::Inner1<Y>::value1 = 0;
|
|
|
|
template<typename X>
|
|
template<typename Y>
|
|
Y Outer<X>::Inner1<Y>::value2 = Y();
|
|
|
|
template<typename X>
|
|
template<typename Y>
|
|
Y Outer<X>::Inner1<Y>::ReallyInner::value3 = Y();
|
|
|
|
template<typename X>
|
|
template<typename Y>
|
|
Y Outer<X>::Inner1<Y*>::ReallyInner::value4; // expected-error{{Outer<X>::Inner1<Y *>::ReallyInner::}}
|
|
|
|
|
|
template<typename T>
|
|
struct X0 { };
|
|
|
|
template<typename T>
|
|
struct X0<T*> {
|
|
template<typename U>
|
|
void f(U u = T()) { }
|
|
};
|
|
|
|
// PR5103
|
|
template<typename>
|
|
struct X1 {
|
|
template<typename, bool = false> struct B { };
|
|
};
|
|
template struct X1<int>::B<bool>;
|
|
|
|
// Template template parameters
|
|
template<typename T>
|
|
struct X2 {
|
|
template<template<class U, T Value> class> // expected-error {{cannot have type 'float'}}
|
|
// expected-error@-1 {{cannot be narrowed from type 'long long' to 'int'}}
|
|
// expected-note@-2 {{previous template template parameter is here}}
|
|
struct Inner { };
|
|
};
|
|
|
|
template<typename T, int Value>
|
|
struct X2_arg;
|
|
|
|
X2<int>::Inner<X2_arg> x2i1;
|
|
X2<float> x2a; // expected-note{{instantiation}}
|
|
X2<long long>::Inner<X2_arg> x2i3; // expected-note {{has different template parameters}}
|
|
|
|
namespace PR10896 {
|
|
template<typename TN>
|
|
class Foo {
|
|
|
|
public:
|
|
void foo() {}
|
|
private:
|
|
|
|
template<typename T>
|
|
T SomeField; // expected-error {{non-static data member 'SomeField' cannot be declared as a template}}
|
|
template<> int SomeField2; // expected-error {{extraneous 'template<>' in declaration of variable 'SomeField2'}}
|
|
};
|
|
|
|
void g() {
|
|
Foo<int> f;
|
|
f.foo();
|
|
}
|
|
}
|
|
|
|
namespace PR10924 {
|
|
template< class Topology, class ctype >
|
|
struct ReferenceElement
|
|
{
|
|
};
|
|
|
|
template< class Topology, class ctype >
|
|
template< int codim >
|
|
class ReferenceElement< Topology, ctype > :: BaryCenterArray // expected-error{{out-of-line definition of 'BaryCenterArray' does not match any declaration in 'ReferenceElement<Topology, ctype>'}}
|
|
{
|
|
};
|
|
}
|
|
|
|
class Outer1 {
|
|
template <typename T> struct X;
|
|
template <typename T> int X<T>::func() {} // expected-error{{out-of-line definition of 'func' from class 'X<T>' without definition}}
|
|
};
|
|
|
|
namespace RefPack {
|
|
template<const int &...N> struct A { template<typename ...T> void f(T (&...t)[N]); };
|
|
constexpr int k = 10;
|
|
int arr[10];
|
|
void g() { A<k>().f(arr); }
|
|
}
|