1// RUN: %clang_cc1 -fsyntax-only -verify %s
2
3// Template argument deduction with template template parameters.
4template<typename T, template<T> class A>
5struct X0 {
6  static const unsigned value = 0;
7};
8
9template<template<int> class A>
10struct X0<int, A> {
11  static const unsigned value = 1;
12};
13
14template<int> struct X0i;
15template<long> struct X0l;
16int array_x0a[X0<long, X0l>::value == 0? 1 : -1];
17int array_x0b[X0<int, X0i>::value == 1? 1 : -1];
18
19template<typename T, typename U>
20struct is_same {
21  static const bool value = false;
22};
23
24template<typename T>
25struct is_same<T, T> {
26  static const bool value = true;
27};
28
29template<typename T> struct allocator { };
30template<typename T, typename Alloc = allocator<T> > struct vector {};
31
32// Fun with meta-lambdas!
33struct _1 {};
34struct _2 {};
35
36// Replaces all occurrences of _1 with Arg1 and _2 with Arg2 in T.
37template<typename T, typename Arg1, typename Arg2>
38struct Replace {
39  typedef T type;
40};
41
42// Replacement of the whole type.
43template<typename Arg1, typename Arg2>
44struct Replace<_1, Arg1, Arg2> {
45  typedef Arg1 type;
46};
47
48template<typename Arg1, typename Arg2>
49struct Replace<_2, Arg1, Arg2> {
50  typedef Arg2 type;
51};
52
53// Replacement through cv-qualifiers
54template<typename T, typename Arg1, typename Arg2>
55struct Replace<const T, Arg1, Arg2> {
56  typedef typename Replace<T, Arg1, Arg2>::type const type;
57};
58
59// Replacement of templates
60template<template<typename> class TT, typename T1, typename Arg1, typename Arg2>
61struct Replace<TT<T1>, Arg1, Arg2> {
62  typedef TT<typename Replace<T1, Arg1, Arg2>::type> type;
63};
64
65template<template<typename, typename> class TT, typename T1, typename T2,
66         typename Arg1, typename Arg2>
67struct Replace<TT<T1, T2>, Arg1, Arg2> {
68  typedef TT<typename Replace<T1, Arg1, Arg2>::type,
69             typename Replace<T2, Arg1, Arg2>::type> type;
70};
71
72// Just for kicks...
73template<template<typename, typename> class TT, typename T1,
74         typename Arg1, typename Arg2>
75struct Replace<TT<T1, _2>, Arg1, Arg2> {
76  typedef TT<typename Replace<T1, Arg1, Arg2>::type, Arg2> type;
77};
78
79int array0[is_same<Replace<_1, int, float>::type, int>::value? 1 : -1];
80int array1[is_same<Replace<const _1, int, float>::type, const int>::value? 1 : -1];
81int array2[is_same<Replace<vector<_1>, int, float>::type, vector<int> >::value? 1 : -1];
82int array3[is_same<Replace<vector<const _1>, int, float>::type, vector<const int> >::value? 1 : -1];
83int array4[is_same<Replace<vector<int, _2>, double, float>::type, vector<int, float> >::value? 1 : -1];
84
85// PR5911
86template <typename T, int N> void f(const T (&a)[N]);
87int iarr[] = { 1 };
88void test_PR5911() { f(iarr); }
89
90// Must not examine base classes of incomplete type during template argument
91// deduction.
92namespace PR6257 {
93  template <typename T> struct X {
94    template <typename U> X(const X<U>& u);
95  };
96  struct A;
97  void f(A& a);
98  void f(const X<A>& a);
99  void test(A& a) { (void)f(a); }
100}
101
102// PR7463
103namespace PR7463 {
104  const int f ();
105  template <typename T_> void g (T_&); // expected-note{{T_ = int}}
106  void h (void) { g(f()); } // expected-error{{no matching function for call}}
107}
108
109namespace test0 {
110  template <class T> void make(const T *(*fn)()); // expected-note {{candidate template ignored: can't deduce a type for 'T' which would make 'const T' equal 'char'}}
111  char *char_maker();
112  void test() {
113    make(char_maker); // expected-error {{no matching function for call to 'make'}}
114  }
115}
116
117namespace test1 {
118  template<typename T> void foo(const T a[3][3]);
119  void test() {
120    int a[3][3];
121    foo(a);
122  }
123}
124
125// PR7708
126namespace test2 {
127  template<typename T> struct Const { typedef void const type; };
128
129  template<typename T> void f(T, typename Const<T>::type*);
130  template<typename T> void f(T, void const *);
131
132  void test() {
133    void *p = 0;
134    f(0, p);
135  }
136}
137
138// rdar://problem/8537391
139namespace test3 {
140  struct Foo {
141    template <void F(char)> static inline void foo();
142  };
143
144  class Bar {
145    template<typename T> static inline void wobble(T ch);
146
147  public:
148    static void madness() {
149      Foo::foo<wobble<char> >();
150    }
151  };
152}
153
154// Verify that we can deduce enum-typed arguments correctly.
155namespace test14 {
156  enum E { E0, E1 };
157  template <E> struct A {};
158  template <E e> void foo(const A<e> &a) {}
159
160  void test() {
161    A<E0> a;
162    foo(a);
163  }
164}
165