Files
clang-p2996/clang/test/SemaTemplate/nested-template.cpp
Matheus Izvekov e29c085812 [clang] disallow narrowing when matching template template parameters (#124313)
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).
2025-01-28 15:51:17 -03:00

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); }
}