summaryrefslogtreecommitdiffstats
path: root/test/SemaTemplate/typename-specifier-4.cpp
blob: 2856c99b6ddf4e7dbd6b96ed3d288a8774457737 (plain)
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// 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
template<typename T, typename U> 
struct is_same {
  static const bool value = false;
};

template<typename T>
struct is_same<T, T> {
  static const bool value = true;
};

template<typename MetaFun, typename T1, typename T2>
struct metafun_apply2 {
  typedef typename MetaFun::template apply<T1, T2> inner;
  typedef typename inner::type type;
};

template<typename T, typename U> struct pair;

struct make_pair {
  template<typename T1, typename T2>
  struct apply {
    typedef pair<T1, T2> type;
  };
};

int a0[is_same<metafun_apply2<make_pair, int, float>::type, 
               pair<int, float> >::value? 1 : -1];
int a1[is_same<
         typename make_pair::template apply<int, float>, 
#if __cplusplus <= 199711L // C++03 and earlier modes
         // expected-warning@-2 {{'template' keyword outside of a template}}
         // expected-warning@-3 {{'typename' occurs outside of a template}}
#endif
         make_pair::apply<int, float>
       >::value? 1 : -1];

template<typename MetaFun>
struct swap_and_apply2 {
  template<typename T1, typename T2>
  struct apply {
    typedef typename MetaFun::template apply<T2, T1> new_metafun;
    typedef typename new_metafun::type type;
  };
};

int a2[is_same<swap_and_apply2<make_pair>::apply<int, float>::type, 
               pair<float, int> >::value? 1 : -1];

template<typename MetaFun>
struct swap_and_apply2b {
  template<typename T1, typename T2>
  struct apply {
    typedef typename MetaFun::template apply<T2, T1>::type type;
  };
};

int a3[is_same<swap_and_apply2b<make_pair>::apply<int, float>::type, 
               pair<float, int> >::value? 1 : -1];

template<typename T>
struct X0 {
  template<typename U, typename V>
  struct Inner;
  
  void f0(X0<T>::Inner<T*, T&>); // expected-note{{here}}
  void f0(typename X0<T>::Inner<T*, T&>); // expected-error{{redecl}}

  void f1(X0<T>::Inner<T*, T&>); // expected-note{{here}}
  void f1(typename X0<T>::template Inner<T*, T&>); // expected-error{{redecl}}

  void f2(typename X0<T>::Inner<T*, T&>::type); // expected-note{{here}}
  void f2(typename X0<T>::template Inner<T*, T&>::type); // expected-error{{redecl}}
};

namespace PR6236 {
  template<typename T, typename U> struct S { };
  
  template<typename T> struct S<T, T> {
    template<typename U> struct K { };
    
    void f() {
      typedef typename S<T, T>::template K<T> Foo;
    }
  };
}

namespace PR6268 {
  template <typename T>
  struct Outer {
    template <typename U>
    struct Inner {};

    template <typename U>
    typename Outer<T>::template Inner<U>
    foo(typename Outer<T>::template Inner<U>);
  };

  template <typename T>
  template <typename U>
  typename Outer<T>::template Inner<U>
  Outer<T>::foo(typename Outer<T>::template Inner<U>) {
    return Inner<U>();
  }
}

namespace PR6463 {
  struct B { typedef int type; }; // expected-note 2{{member found by ambiguous name lookup}}
  struct C { typedef int type; }; // expected-note 2{{member found by ambiguous name lookup}}

  template<typename T>
  struct A : B, C { 
    type& a(); // expected-error{{found in multiple base classes}}
    int x; 
  };

  // FIXME: Improve source location info here.
  template<typename T>
  typename A<T>::type& A<T>::a() { // expected-error{{found in multiple base classes}}
    return x;
  }
}

namespace PR7419 {
  template <typename T> struct S {
    typedef typename T::Y T2;
    typedef typename T2::Z T3;
    typedef typename T3::W T4;
    T4 *f();

    typedef typename T::template Y<int> TT2;
    typedef typename TT2::template Z<float> TT3;
    typedef typename TT3::template W<double> TT4;
    TT4 g();
  };

  template <typename T> typename T::Y::Z::W *S<T>::f() { }
  template <typename T> typename T::template Y<int>::template Z<float>::template W<double> S<T>::g() { }
}

namespace rdar8740998 {
  template<typename T>
  struct X : public T {
    using T::iterator; // expected-note{{add 'typename' to treat this using declaration as a type}} \
    // expected-error{{dependent using declaration resolved to type without 'typename'}}

    void f() {
      typename X<T>::iterator i; // expected-error{{typename specifier refers to a dependent using declaration for a value 'iterator' in 'X<T>'}}
    }
  };

  struct HasIterator {
    typedef int *iterator; // expected-note{{target of using declaration}}
  };

  void test_X(X<HasIterator> xi) { // expected-note{{in instantiation of template class}}
    xi.f();
  }
}

namespace rdar9068589 {
  // From GCC PR c++/13950
  template <class T> struct Base {};
  template <class T> struct Derived: public Base<T> {
    typename Derived::template Base<double>* p1;
  };
}