Home | History | Annotate | Download | only in SemaTemplate
      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