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