1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
// PR4607
template <class T> struct X {};
template <> struct X<char>
{
static char* g();
};
template <class T> struct X2 {};
template <class U>
struct X2<U*> {
static void f() {
X<U>::g();
}
};
void a(char *a, char *b) {X2<char*>::f();}
namespace WonkyAccess {
template<typename T>
struct X {
int m;
};
template<typename U>
class Y;
template<typename U>
struct Y<U*> : X<U> { };
template<>
struct Y<float*> : X<float> { };
int f(Y<int*> y, Y<float*> y2) {
return y.m + y2.m;
}
}
namespace rdar9169404 {
template<typename T, T N> struct X { };
template<bool C> struct X<bool, C> {
typedef int type;
};
X<bool, -1>::type value;
#if __cplusplus >= 201103L
// expected-error@-2 {{non-type template argument evaluates to -1, which cannot be narrowed to type 'bool'}}
#endif
}
namespace rdar39524996 {
template <typename T, typename U>
struct enable_if_not_same
{
typedef void type;
};
template <typename T>
struct enable_if_not_same<T, T>;
template <typename T>
struct Wrapper {
// Assertion triggered on trying to set twice the same partial specialization
// enable_if_not_same<int, int>
template <class U>
Wrapper(const Wrapper<U>& other,
typename enable_if_not_same<U, T>::type* = 0) {}
explicit Wrapper(int i) {}
};
template <class T>
struct Container {
// It is important that the struct has implicit copy and move constructors.
Container() : x() {}
template <class U>
Container(const Container<U>& other) : x(static_cast<T>(other.x)) {}
// Implicit constructors are member-wise, so the field triggers instantiation
// of T constructors and we instantiate all of them for overloading purposes.
T x;
};
void takesWrapperInContainer(const Container< Wrapper<int> >& c);
void test() {
// Type mismatch triggers initialization with conversion which requires
// implicit constructors to be instantiated.
Container<int> c;
takesWrapperInContainer(c);
}
}
namespace InstantiationDependent {
template<typename> using ignore = void; // expected-warning 0-1{{extension}}
template<typename T, typename = void> struct A {
static const bool specialized = false;
};
template<typename T> struct Hide { typedef void type; };
template<typename T> struct A<T, Hide<ignore<typename T::type> >::type> {
static const bool specialized = true;
};
struct X {};
struct Y { typedef int type; };
_Static_assert(!A<X>::specialized, "");
_Static_assert(A<Y>::specialized, "");
}
namespace IgnorePartialSubstitution {
template <typename... T> struct tuple {}; // expected-warning 0-1{{extension}}
template <typename> struct IsTuple {
enum { value = false };
};
template <typename... Us> struct IsTuple<tuple<Us...> > { // expected-warning 0-1{{extension}}
enum { value = true };
};
template <bool...> using ignore = void; // expected-warning 0-2{{extension}}
template <class... Pred> ignore<Pred::value...> helper(); // expected-warning 0-1{{extension}}
using S = IsTuple<tuple<int> >; // expected-warning 0-1{{extension}}
// This used to pick the primary template, because we got confused and
// thought that template parameter 0 was the current partially-substituted
// pack (from `helper`) during the deduction for the partial specialization.
void f() { helper<S>(); }
_Static_assert(S::value, "");
}
namespace GH60778 {
template <bool B = false> class ClassTemplate {
public:
template <typename T, typename = void> class Nested {};
};
template <typename DerivedType> class Base {};
template <>
template <typename T>
class ClassTemplate<>::Nested<T> : public Base<ClassTemplate<>::Nested<T> > {};
void use() {
// This should instantiate the body of Nested with the template arguments
// from the Partial Specialization. This would previously get confused and
// get the template arguments from the primary template instead.
ClassTemplate<>::Nested<int> instantiation;
}
}
|