1 // RUN: %clang_cc1 -fsyntax-only -verify %s -Wno-unused 2 // RUN: %clang_cc1 -fsyntax-only -verify %s -Wno-unused -fms-compatibility -DMSVC 3 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s -Wno-unused 4 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s -Wno-unused -fms-compatibility -DMSVC 5 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -Wno-unused 6 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -Wno-unused -fms-compatibility -DMSVC 7 namespace N { 8 struct A { 9 typedef int type; 10 }; 11 12 struct B { 13 }; 14 15 struct C { 16 struct type { }; 17 int type; // expected-note 2{{referenced member 'type' is declared here}} 18 }; 19 } 20 21 int i; 22 23 typename N::A::type *ip1 = &i; 24 #if __cplusplus <= 199711L // C++03 or earlier modes 25 // expected-warning@-2 {{'typename' occurs outside of a template}} 26 #endif 27 typename N::B::type *ip2 = &i; // expected-error{{no type named 'type' in 'N::B'}} 28 #if __cplusplus <= 199711L 29 // expected-warning@-2 {{'typename' occurs outside of a template}} 30 #endif 31 typename N::C::type *ip3 = &i; // expected-error{{typename specifier refers to non-type member 'type'}} 32 #if __cplusplus <= 199711L 33 // expected-warning@-2 {{'typename' occurs outside of a template}} 34 #endif 35 36 void test(double d) { 37 typename N::A::type f(typename N::A::type(a)); // expected-warning{{disambiguated as a function declaration}} 38 // expected-note@-1 {{add a pair of parentheses}} 39 #if __cplusplus <= 199711L 40 // expected-warning@-3 2{{'typename' occurs outside of a template}} 41 #endif 42 int five = f(5); 43 44 using namespace N; 45 for (typename A::type i = 0; i < 10; ++i) 46 #if __cplusplus <= 199711L 47 // expected-warning@-2 {{'typename' occurs outside of a template}} 48 #endif 49 five += 1; 50 51 const typename N::A::type f2(d); 52 #if __cplusplus <= 199711L 53 // expected-warning@-2 {{'typename' occurs outside of a template}} 54 #endif 55 } 56 57 namespace N { 58 template<typename T> 59 struct X { 60 typedef typename T::type type; // expected-error {{no type named 'type' in 'N::B'}} \ 61 // expected-error {{no type named 'type' in 'B'}} \ 62 // FIXME: location info for error above isn't very good \ 63 // expected-error 2{{typename specifier refers to non-type member 'type'}} \ 64 // expected-error{{type 'int' cannot be used prior to '::' because it has no members}} 65 }; 66 } 67 68 N::X<N::A>::type *ip4 = &i; 69 N::X<N::B>::type *ip5 = &i; // expected-note{{in instantiation of template class 'N::X<N::B>' requested here}} 70 N::X<N::C>::type *ip6 = &i; // expected-note{{in instantiation of template class 'N::X<N::C>' requested here}} 71 72 N::X<int>::type fail1; // expected-note{{in instantiation of template class 'N::X<int>' requested here}} 73 74 template<typename T> 75 struct Y { 76 typedef typename N::X<T>::type *type; // expected-note{{in instantiation of template class 'N::X<B>' requested here}} \ 77 // expected-note{{in instantiation of template class 'N::X<C>' requested here}} 78 }; 79 80 struct A { 81 typedef int type; 82 }; 83 84 struct B { 85 }; 86 87 struct C { 88 struct type { }; 89 int type; // expected-note{{referenced member 'type' is declared here}} 90 }; 91 92 ::Y<A>::type ip7 = &i; 93 ::Y<B>::type ip8 = &i; // expected-note{{in instantiation of template class 'Y<B>' requested here}} 94 ::Y<C>::type ip9 = &i; // expected-note{{in instantiation of template class 'Y<C>' requested here}} 95 96 template<typename T> struct D { 97 typedef typename T::foo foo; // expected-error {{type 'long' cannot be used prior to '::' because it has no members}} 98 typedef typename foo::bar bar; 99 }; 100 101 D<long> struct_D; // expected-note {{in instantiation of template class 'D<long>' requested here}} 102 103 template<typename T> struct E { 104 typedef typename T::foo foo; 105 typedef typename foo::bar bar; // expected-error {{type 'foo' (aka 'double') cannot be used prior to '::' because it has no members}} 106 }; 107 108 struct F { 109 typedef double foo; 110 }; 111 112 E<F> struct_E; // expected-note {{in instantiation of template class 'E<F>' requested here}} 113 114 template<typename T> struct G { 115 typedef typename T::foo foo; 116 typedef typename foo::bar bar; 117 }; 118 119 struct H { 120 struct foo { 121 typedef double bar; 122 }; 123 }; 124 125 G<H> struct_G; 126 127 namespace PR10925 { 128 template< int mydim, typename Traits > 129 class BasicGeometry 130 { 131 typedef int some_type_t; 132 }; 133 134 template<class ctype, int mydim, int coorddim> 135 class MockGeometry : BasicGeometry<mydim, int>{ 136 using typename BasicGeometry<mydim, int>::operator[]; // expected-error {{typename is allowed for identifiers only}} 137 }; 138 } 139 140 141 namespace missing_typename { 142 template <class T1, class T2> struct pair {}; // expected-note 7 {{template parameter is declared here}} 143 144 template <class T1, class T2> 145 struct map { 146 typedef T1* iterator; 147 }; 148 149 template <class T> 150 class ExampleClass1 { 151 struct ExampleItem; 152 153 154 struct ExampleItemSet { 155 typedef ExampleItem* iterator; 156 ExampleItem* operator[](unsigned); 157 }; 158 159 void foo() { 160 #ifdef MSVC 161 // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}} 162 #else 163 // expected-error@+2 {{template argument for template type parameter must be a type; did you forget 'typename'?}} 164 #endif 165 pair<ExampleItemSet::iterator, int> i; 166 pair<this->ExampleItemSet::iterator, int> i; // expected-error-re {{template argument for template type parameter must be a type{{$}}}} 167 pair<ExampleItemSet::operator[], int> i; // expected-error-re {{template argument for template type parameter must be a type{{$}}}} 168 } 169 #ifdef MSVC 170 // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}} 171 #else 172 // expected-error@+2 {{template argument for template type parameter must be a type; did you forget 'typename'?}} 173 #endif 174 pair<ExampleItemSet::iterator, int> elt; 175 176 177 typedef map<int, ExampleItem*> ExampleItemMap; 178 179 static void bar() { 180 #ifdef MSVC 181 // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}} 182 #else 183 // expected-error@+2 {{template argument for template type parameter must be a type; did you forget 'typename'?}} 184 #endif 185 pair<ExampleItemMap::iterator, int> i; 186 } 187 #ifdef MSVC 188 // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}} 189 #else 190 // expected-error@+2 {{template argument for template type parameter must be a type; did you forget 'typename'?}} 191 #endif 192 pair<ExampleItemMap::iterator, int> entry; 193 pair<bar, int> foobar; // expected-error {{template argument for template type parameter must be a type}} 194 }; 195 } // namespace missing_typename 196 197 namespace missing_typename_and_base { 198 template <class T> struct Bar {}; // expected-note 1+ {{template parameter is declared here}} 199 template <typename T> 200 struct Foo : T { 201 202 // FIXME: MSVC accepts this code. 203 Bar<TypeInBase> x; // expected-error {{use of undeclared identifier 'TypeInBase'}} 204 205 #ifdef MSVC 206 // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}} 207 #else 208 // expected-error@+2 {{must be a type; did you forget 'typename'?}} 209 #endif 210 Bar<T::TypeInBase> y; 211 212 #ifdef MSVC 213 // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}} 214 #else 215 // expected-error@+2 {{must be a type; did you forget 'typename'?}} 216 #endif 217 Bar<T::NestedRD::TypeInNestedRD> z; 218 219 }; 220 struct Base { 221 typedef int TypeInBase; 222 struct NestedRD { 223 typedef int TypeInNestedRD; 224 }; 225 }; 226 Foo<Base> x; 227 } // namespace missing_typename_and_base 228 229 namespace func_type_vs_construct_tmp { 230 template <typename> struct S { typedef int type; }; 231 template <typename T> void f(); 232 template <int N> void f(); 233 234 // expected-error@+1 {{missing 'typename' prior to dependent type name 'S<int>::type'}} 235 template <typename T> void g() { f</*typename*/ S<T>::type(int())>(); } 236 237 // Adding typename does fix the diagnostic. 238 template <typename T> void h() { f<typename S<T>::type(int())>(); } 239 240 void j() { 241 g<int>(); // expected-note-re {{in instantiation {{.*}} requested here}} 242 h<int>(); 243 } 244 } // namespace func_type_vs_construct_tmp 245 246 namespace pointer_vs_multiply { 247 int x; 248 // expected-error@+1 {{missing 'typename' prior to dependent type name 'B::type_or_int'}} 249 template <typename T> void g() { T::type_or_int * x; } 250 // expected-error@+1 {{typename specifier refers to non-type member 'type_or_int' in 'pointer_vs_multiply::A'}} 251 template <typename T> void h() { typename T::type_or_int * x; } 252 253 struct A { static const int type_or_int = 5; }; // expected-note {{referenced member 'type_or_int' is declared here}} 254 struct B { typedef int type_or_int; }; 255 256 void j() { 257 g<A>(); 258 g<B>(); // expected-note-re {{in instantiation {{.*}} requested here}} 259 h<A>(); // expected-note-re {{in instantiation {{.*}} requested here}} 260 h<B>(); 261 } 262 } // namespace pointer_vs_multiply 263