| // 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; |
| } |
| |
| // MSVC accepts this, but Clang doesn't. |
| namespace test_scope_spec { |
| template <typename T = ns::Bar> // expected-error {{use of undeclared identifier 'ns'}} |
| struct Foo { |
| static_assert(sizeof(T) == 4, "Bar should have gotten int"); |
| }; |
| namespace ns { typedef int Bar; } |
| } |
| |
| #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 |