1// RUN: %clang_cc1 -std=c++11 -fms-compatibility -fsyntax-only -verify %s
2
3// If we were even more clever, we'd tell the user to use one set of parens to
4// get the size of this type, so they don't get errors after inserting typename.
5
6namespace basic {
7template <typename T> int type_f() { return sizeof T::type; }  // expected-error {{missing 'typename' prior to dependent type name 'X::type'}}
8template <typename T> int type_g() { return sizeof(T::type); }  // expected-warning {{missing 'typename' prior to dependent type name 'X::type'}}
9template <typename T> int type_h() { return sizeof((T::type)); }  // expected-error {{missing 'typename' prior to dependent type name 'X::type'}}
10template <typename T> int value_f() { return sizeof T::not_a_type; }
11template <typename T> int value_g() { return sizeof(T::not_a_type); }
12template <typename T> int value_h() { return sizeof((T::not_a_type)); }
13struct X {
14  typedef int type;
15  static const int not_a_type;
16};
17int bar() {
18  return
19      type_f<X>() + // expected-note-re {{in instantiation {{.*}} requested here}}
20      type_g<X>() + // expected-note-re {{in instantiation {{.*}} requested here}}
21      type_h<X>() + // expected-note-re {{in instantiation {{.*}} requested here}}
22      value_f<X>() +
23      value_f<X>() +
24      value_f<X>();
25}
26}
27
28namespace nested_sizeof {
29template <typename T>
30struct Foo {
31  enum {
32    // expected-warning@+2 {{use 'template' keyword to treat 'InnerTemplate' as a dependent template name}}
33    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'Bar::InnerType'}}
34    x1 = sizeof(typename T::/*template*/ InnerTemplate<sizeof(/*typename*/ T::InnerType)>),
35    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'Bar::InnerType'}}
36    x2 = sizeof(typename T::template InnerTemplate<sizeof(/*typename*/ T::InnerType)>),
37    // expected-warning@+1 {{use 'template' keyword to treat 'InnerTemplate' as a dependent template name}}
38    y1 = sizeof(typename T::/*template*/ InnerTemplate<sizeof(T::InnerVar)>),
39    y2 = sizeof(typename T::template InnerTemplate<sizeof(T::InnerVar)>),
40    z = sizeof(T::template InnerTemplate<sizeof(T::InnerVar)>::x),
41  };
42};
43struct Bar {
44  template <int N>
45  struct InnerTemplate { int x[N]; };
46  typedef double InnerType;
47  static const int InnerVar = 42;
48};
49template struct Foo<Bar>; // expected-note-re {{in instantiation {{.*}} requested here}}
50}
51
52namespace ambiguous_missing_parens {
53// expected-error@+1 {{'Q::U' instantiated to a class template, not a function template}}
54template <typename T> void f() { int a = sizeof T::template U<0> + 4; }
55struct Q {
56  // expected-error@+1 {{class template declared here}}
57  template <int> struct U {};
58};
59// expected-note-re@+1 {{in instantiation {{.*}} requested here}}
60template void f<Q>();
61}
62