1df6e4a06SReid Kleckner // RUN: %clang_cc1 -fms-compatibility -std=c++11 %s -verify
2df6e4a06SReid Kleckner 
3df6e4a06SReid Kleckner // MSVC should compile this file without errors.
4df6e4a06SReid Kleckner 
5df6e4a06SReid Kleckner namespace test_basic {
6df6e4a06SReid Kleckner template <typename T = Baz> // expected-warning {{using the undeclared type 'Baz' as a default template argument is a Microsoft extension}}
7df6e4a06SReid Kleckner struct Foo { T x; };
8df6e4a06SReid Kleckner typedef int Baz;
9df6e4a06SReid Kleckner template struct Foo<>;
10df6e4a06SReid Kleckner }
11df6e4a06SReid Kleckner 
12df6e4a06SReid Kleckner namespace test_namespace {
13df6e4a06SReid Kleckner namespace nested {
14df6e4a06SReid Kleckner template <typename T = Baz> // expected-warning {{using the undeclared type 'Baz' as a default template argument is a Microsoft extension}}
15df6e4a06SReid Kleckner struct Foo {
16df6e4a06SReid Kleckner   static_assert(sizeof(T) == 4, "should get int, not double");
17df6e4a06SReid Kleckner };
18df6e4a06SReid Kleckner typedef int Baz;
19df6e4a06SReid Kleckner }
20df6e4a06SReid Kleckner typedef double Baz;
21df6e4a06SReid Kleckner template struct nested::Foo<>;
22df6e4a06SReid Kleckner }
23df6e4a06SReid Kleckner 
24df6e4a06SReid Kleckner namespace test_inner_class_template {
25df6e4a06SReid Kleckner struct Outer {
26df6e4a06SReid Kleckner   template <typename T = Baz> // expected-warning {{using the undeclared type 'Baz' as a default template argument is a Microsoft extension}}
27df6e4a06SReid Kleckner   struct Foo {
28df6e4a06SReid Kleckner     static_assert(sizeof(T) == 4, "should get int, not double");
29df6e4a06SReid Kleckner   };
30df6e4a06SReid Kleckner   typedef int Baz;
31df6e4a06SReid Kleckner };
32df6e4a06SReid Kleckner typedef double Baz;
33df6e4a06SReid Kleckner template struct Outer::Foo<>;
34df6e4a06SReid Kleckner }
35df6e4a06SReid Kleckner 
36df6e4a06SReid Kleckner namespace test_nontype_param {
37df6e4a06SReid Kleckner template <typename T> struct Bar { T x; };
38df6e4a06SReid Kleckner typedef int Qux;
39df6e4a06SReid Kleckner template <Bar<Qux> *P>
40df6e4a06SReid Kleckner struct Foo {
41df6e4a06SReid Kleckner };
42df6e4a06SReid Kleckner Bar<int> g;
43df6e4a06SReid Kleckner template struct Foo<&g>;
44df6e4a06SReid Kleckner }
45df6e4a06SReid Kleckner 
46df6e4a06SReid Kleckner // MSVC accepts this, but Clang doesn't.
47df6e4a06SReid Kleckner namespace test_template_instantiation_arg {
48df6e4a06SReid Kleckner template <typename T> struct Bar { T x; };
49df6e4a06SReid Kleckner template <typename T = Bar<Weber>>  // expected-error {{use of undeclared identifier 'Weber'}}
50df6e4a06SReid Kleckner struct Foo {
51df6e4a06SReid Kleckner   static_assert(sizeof(T) == 4, "Bar should have gotten int");
52*0c42539dSRichard Smith };
53df6e4a06SReid Kleckner typedef int Weber;
54df6e4a06SReid Kleckner }
55df6e4a06SReid Kleckner 
569a96e420SReid Kleckner // MSVC accepts this, but Clang doesn't.
579a96e420SReid Kleckner namespace test_scope_spec {
589a96e420SReid Kleckner template <typename T = ns::Bar>  // expected-error {{use of undeclared identifier 'ns'}}
599a96e420SReid Kleckner struct Foo {
609a96e420SReid Kleckner   static_assert(sizeof(T) == 4, "Bar should have gotten int");
619a96e420SReid Kleckner };
629a96e420SReid Kleckner namespace ns { typedef int Bar; }
639a96e420SReid Kleckner }
649a96e420SReid Kleckner 
65df6e4a06SReid Kleckner #ifdef __clang__
66df6e4a06SReid Kleckner // These are negative test cases that MSVC doesn't compile either.  Try to use
67df6e4a06SReid Kleckner // unique undeclared identifiers so typo correction doesn't find types declared
68df6e4a06SReid Kleckner // above.
69df6e4a06SReid Kleckner 
70df6e4a06SReid Kleckner namespace test_undeclared_nontype_parm_type {
71df6e4a06SReid Kleckner template <Zargon N> // expected-error {{unknown type name 'Zargon'}}
72df6e4a06SReid Kleckner struct Foo { int x[N]; };
73df6e4a06SReid Kleckner typedef int Zargon;
74df6e4a06SReid Kleckner template struct Foo<4>;
75df6e4a06SReid Kleckner }
76df6e4a06SReid Kleckner 
77df6e4a06SReid Kleckner namespace test_undeclared_nontype_parm_type_no_name {
78df6e4a06SReid Kleckner template <typename T, Asdf> // expected-error {{unknown type name 'Asdf'}}
79df6e4a06SReid Kleckner struct Foo { T x; };
80df6e4a06SReid Kleckner template struct Foo<int, 0>;
81df6e4a06SReid Kleckner }
82df6e4a06SReid Kleckner 
83df6e4a06SReid Kleckner namespace test_undeclared_type_arg {
84df6e4a06SReid Kleckner template <typename T>
85df6e4a06SReid Kleckner struct Foo { T x; };
86df6e4a06SReid Kleckner template struct Foo<Yodel>; // expected-error {{use of undeclared identifier 'Yodel'}}
87df6e4a06SReid Kleckner }
88df6e4a06SReid Kleckner 
89df6e4a06SReid Kleckner namespace test_undeclared_nontype_parm_arg {
90df6e4a06SReid Kleckner // Bury an undeclared type as a template argument to the type of a non-type
91df6e4a06SReid Kleckner // template parameter.
92df6e4a06SReid Kleckner template <typename T> struct Bar { T x; };
93df6e4a06SReid Kleckner 
94b481f028SSaar Raz template <Bar<Xylophone> *P> // expected-error {{use of undeclared identifier 'Xylophone'}}
95b481f028SSaar Raz // expected-note@-1{{template parameter is declared here}}
96df6e4a06SReid Kleckner struct Foo { };
97df6e4a06SReid Kleckner 
98df6e4a06SReid Kleckner typedef int Xylophone;
99df6e4a06SReid Kleckner Bar<Xylophone> g;
100ff1e0fceSSaar Raz template struct Foo<&g>; // expected-error {{value of type}}
101df6e4a06SReid Kleckner }
102df6e4a06SReid Kleckner 
103df6e4a06SReid Kleckner #endif
104