| 12
 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 type 'int' found by ambiguous name lookup}}
  struct C { typedef const int type; }; // expected-note 2{{member type 'const int' 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;
  };
}
 |