| // RUN: %clang_cc1 -fms-compatibility -std=c++11 %s -verify | 
 |  | 
 | // MSVC should compile this file without errors. | 
 |  | 
 | namespace test_basic { | 
 | template <typename T = Baz> // expected-warning {{using the undeclared type 'Baz' as a default template argument is a Microsoft extension}} | 
 | struct Foo { T x; }; | 
 | typedef int Baz; | 
 | template struct Foo<>; | 
 | } | 
 |  | 
 | namespace test_namespace { | 
 | namespace nested { | 
 | template <typename T = Baz> // expected-warning {{using the undeclared type 'Baz' as a default template argument is a Microsoft extension}} | 
 | struct Foo { | 
 |   static_assert(sizeof(T) == 4, "should get int, not double"); | 
 | }; | 
 | typedef int Baz; | 
 | } | 
 | typedef double Baz; | 
 | template struct nested::Foo<>; | 
 | } | 
 |  | 
 | namespace test_inner_class_template { | 
 | struct Outer { | 
 |   template <typename T = Baz> // expected-warning {{using the undeclared type 'Baz' as a default template argument is a Microsoft extension}} | 
 |   struct Foo { | 
 |     static_assert(sizeof(T) == 4, "should get int, not double"); | 
 |   }; | 
 |   typedef int Baz; | 
 | }; | 
 | typedef double Baz; | 
 | template struct Outer::Foo<>; | 
 | } | 
 |  | 
 | namespace test_nontype_param { | 
 | template <typename T> struct Bar { T x; }; | 
 | typedef int Qux; | 
 | template <Bar<Qux> *P> | 
 | struct Foo { | 
 | }; | 
 | Bar<int> g; | 
 | template struct Foo<&g>; | 
 | } | 
 |  | 
 | // MSVC accepts this, but Clang doesn't. | 
 | namespace test_template_instantiation_arg { | 
 | template <typename T> struct Bar { T x; }; | 
 | template <typename T = Bar<Weber>>  // expected-error {{use of undeclared identifier 'Weber'}} | 
 | struct Foo { | 
 |   static_assert(sizeof(T) == 4, "Bar should have gotten int"); | 
 |   // FIXME: These diagnostics are bad. | 
 | }; // expected-error {{expected ',' or '>' in template-parameter-list}} | 
 | // expected-warning@-1 {{does not declare anything}} | 
 | typedef int Weber; | 
 | } | 
 |  | 
 | #ifdef __clang__ | 
 | // These are negative test cases that MSVC doesn't compile either.  Try to use | 
 | // unique undeclared identifiers so typo correction doesn't find types declared | 
 | // above. | 
 |  | 
 | namespace test_undeclared_nontype_parm_type { | 
 | template <Zargon N> // expected-error {{unknown type name 'Zargon'}} | 
 | struct Foo { int x[N]; }; | 
 | typedef int Zargon; | 
 | template struct Foo<4>; | 
 | } | 
 |  | 
 | namespace test_undeclared_nontype_parm_type_no_name { | 
 | template <typename T, Asdf> // expected-error {{unknown type name 'Asdf'}} | 
 | struct Foo { T x; }; | 
 | template struct Foo<int, 0>; | 
 | } | 
 |  | 
 | namespace test_undeclared_type_arg { | 
 | template <typename T> | 
 | struct Foo { T x; }; | 
 | template struct Foo<Yodel>; // expected-error {{use of undeclared identifier 'Yodel'}} | 
 | } | 
 |  | 
 | namespace test_undeclared_nontype_parm_arg { | 
 | // Bury an undeclared type as a template argument to the type of a non-type | 
 | // template parameter. | 
 | template <typename T> struct Bar { T x; }; | 
 |  | 
 | template <Bar<Xylophone> *P> // expected-error {{use of undeclared identifier 'Xylophone'}} | 
 | // expected-note@-1 {{template parameter is declared here}} | 
 | struct Foo { }; | 
 |  | 
 | typedef int Xylophone; | 
 | Bar<Xylophone> g; | 
 | template struct Foo<&g>; // expected-error {{cannot be converted}} | 
 | } | 
 |  | 
 | #endif |