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 | // MSVC accepts this, but Clang doesn't. |
59 | namespace test_scope_spec { |
60 | template <typename T = ns::Bar> // expected-error {{use of undeclared identifier 'ns'}} |
61 | struct Foo { |
62 | static_assert(sizeof(T) == 4, "Bar should have gotten int"); |
63 | }; |
64 | namespace ns { typedef int Bar; } |
65 | } |
66 | |
67 | #ifdef __clang__ |
68 | // These are negative test cases that MSVC doesn't compile either. Try to use |
69 | // unique undeclared identifiers so typo correction doesn't find types declared |
70 | // above. |
71 | |
72 | namespace test_undeclared_nontype_parm_type { |
73 | template <Zargon N> // expected-error {{unknown type name 'Zargon'}} |
74 | struct Foo { int x[N]; }; |
75 | typedef int Zargon; |
76 | template struct Foo<4>; |
77 | } |
78 | |
79 | namespace test_undeclared_nontype_parm_type_no_name { |
80 | template <typename T, Asdf> // expected-error {{unknown type name 'Asdf'}} |
81 | struct Foo { T x; }; |
82 | template struct Foo<int, 0>; |
83 | } |
84 | |
85 | namespace test_undeclared_type_arg { |
86 | template <typename T> |
87 | struct Foo { T x; }; |
88 | template struct Foo<Yodel>; // expected-error {{use of undeclared identifier 'Yodel'}} |
89 | } |
90 | |
91 | namespace test_undeclared_nontype_parm_arg { |
92 | // Bury an undeclared type as a template argument to the type of a non-type |
93 | // template parameter. |
94 | template <typename T> struct Bar { T x; }; |
95 | |
96 | template <Bar<Xylophone> *P> // expected-error {{use of undeclared identifier 'Xylophone'}} |
97 | // expected-note@-1 {{template parameter is declared here}} |
98 | struct Foo { }; |
99 | |
100 | typedef int Xylophone; |
101 | Bar<Xylophone> g; |
102 | template struct Foo<&g>; // expected-error {{cannot be converted}} |
103 | } |
104 | |
105 | #endif |
106 | |