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