Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -304,9 +304,13 @@ // // We therefore do not perform any name lookup if the result would // refer to a member of an unknown specialization. - if (!isClassName && !IsCtorOrDtorName) + if (!isClassName && !IsCtorOrDtorName && + !((CurContext->getDeclKind() == Decl::Function || + CurContext->getDeclKind() == Decl::CXXMethod) && + getLangOpts().CPlusPlus && + getLangOpts().MSVCCompat && + getLangOpts().MicrosoftExt)) return nullptr; - // We know from the grammar that this name refers to a type, // so build a dependent node to describe the type. if (WantNontrivialTypeSourceInfo) Index: test/SemaCXX/MicrosoftCompatibility.cpp =================================================================== --- test/SemaCXX/MicrosoftCompatibility.cpp +++ test/SemaCXX/MicrosoftCompatibility.cpp @@ -217,7 +217,7 @@ template void function_missing_typename(const T::Type param)// expected-warning {{missing 'typename' prior to dependent type name}} { - const T::Type var = 2; // expected-warning {{missing 'typename' prior to dependent type name}} + const T::Type var = 2; } template void function_missing_typename(const D::Type param); Index: test/SemaTemplate/lookup-dependent-bases.cpp =================================================================== --- test/SemaTemplate/lookup-dependent-bases.cpp +++ test/SemaTemplate/lookup-dependent-bases.cpp @@ -12,11 +12,13 @@ template struct B : A { void foo() { - D::foo2(); // expected-warning {{use of undeclared identifier 'D'; unqualified lookup into dependent bases of class template 'B' is a Microsoft extension}} + // expected-warning@+2 {{use of undeclared identifier 'D'}} + // expected-error@+1 {{use of undeclared identifier 'D'}} + D::foo2(); } }; -template struct B; // Instantiation has no warnings. +template struct B; // expected-note {{in instantiation of member function 'basic::B::foo' requested here}} } namespace nested_nodep_base { @@ -46,10 +48,12 @@ struct B { struct C : T { void foo() { - D::foo2(); // expected-warning {{use of undeclared identifier 'D'; unqualified lookup into dependent bases of class template 'C' is a Microsoft extension}} + // expected-warning@+2 {{use of undeclared identifier 'D'; unqualified lookup into dependent bases of class template 'C' is a Microsoft extension}} + // expected-error@+1 {{use of undeclared identifier 'D'}} + D::foo2(); } }; }; -template struct B; // Instantiation has no warnings. +template struct B; //expected-note {{in instantiation of member function 'nested_dep_base::B::C::foo' requested here}} } Index: test/SemaTemplate/ms-lookup-template-base-classes.cpp =================================================================== --- test/SemaTemplate/ms-lookup-template-base-classes.cpp +++ test/SemaTemplate/ms-lookup-template-base-classes.cpp @@ -206,11 +206,11 @@ template struct B : T { int foo() { return a; } // expected-warning {{lookup into dependent bases}} int *bar() { return &a; } // expected-warning {{lookup into dependent bases}} - int baz() { return T::a; } - int T::*qux() { return &T::a; } - static int T::*stuff() { return &T::a; } - static int stuff1() { return T::sa; } - static int *stuff2() { return &T::sa; } + int baz() { return T::a; } //expected-error {{expected '(' for function-style cast or type construction}} + int T::*qux() { return &T::a; } //expected-error {{expected '(' for function-style cast or type construction}} + static int T::*stuff() { return &T::a; } //expected-error {{expected '(' for function-style cast or type construction}} + static int stuff1() { return T::sa; } //expected-error {{expected '(' for function-style cast or type construction}} + static int *stuff2() { return &T::sa; } //expected-error {{expected '(' for function-style cast or type construction}} static int stuff3() { return sa; } // expected-warning {{lookup into dependent bases}} static int *stuff4() { return &sa; } // expected-warning {{lookup into dependent bases}} }; @@ -218,10 +218,10 @@ template struct C : T { int foo() { return b; } // expected-error {{no member named 'b' in 'PR16014::C'}} expected-warning {{lookup into dependent bases}} int *bar() { return &b; } // expected-error {{no member named 'b' in 'PR16014::C'}} expected-warning {{lookup into dependent bases}} - int baz() { return T::b; } // expected-error {{no member named 'b' in 'PR16014::A'}} - int T::*qux() { return &T::b; } // expected-error {{no member named 'b' in 'PR16014::A'}} - int T::*fuz() { return &U::a; } // expected-error {{use of undeclared identifier 'U'}} \ - // expected-warning {{unqualified lookup into dependent bases of class template 'C'}} + int baz() { return T::b; } //expected-error {{expected '(' for function-style cast or type construction}} + int T::*qux() { return &T::b; } //expected-error {{expected '(' for function-style cast or type construction}} + // expected-warning@+1 {{use of undeclared identifier 'U'; unqualified lookup into dependent bases of class template 'C' is a Microsoft extension}} + int T::*fuz() { return &U::a; } //expected-error {{expected '(' for function-style cast or type construction}} }; template struct B; @@ -250,14 +250,14 @@ ::UndefClass::undef(); // expected-error {{no member named 'UndefClass' in the global namespace}} } void baz() { - B::qux(); // expected-error {{use of undeclared identifier 'B'}} \ - // expected-warning {{unqualified lookup into dependent bases of class template 'A'}} + // expected-error@+1 2 {{use of undeclared identifier 'B'}} + B::qux(); // expected-warning {{use of undeclared identifier 'B'; unqualified lookup into dependent bases of class template 'A' is a Microsoft extension}} } }; struct B { void qux(); }; struct C : B { }; -template struct A; // No error! B is a base of A, and qux is available. +template struct A; //expected-note {{in instantiation of member function 'PR19233::A::baz' requested here}} struct D { }; template struct A; // expected-note {{in instantiation of member function 'PR19233::A::baz' requested here}} Index: test/SemaTemplate/ms-sizeof-missing-typename.cpp =================================================================== --- test/SemaTemplate/ms-sizeof-missing-typename.cpp +++ test/SemaTemplate/ms-sizeof-missing-typename.cpp @@ -4,21 +4,21 @@ // get the size of this type, so they don't get errors after inserting typename. namespace basic { -template int type_f() { return sizeof T::type; } // expected-error {{missing 'typename' prior to dependent type name 'X::type'}} -template int type_g() { return sizeof(T::type); } // expected-warning {{missing 'typename' prior to dependent type name 'X::type'}} -template int type_h() { return sizeof((T::type)); } // expected-error {{missing 'typename' prior to dependent type name 'X::type'}} -template int value_f() { return sizeof T::not_a_type; } +template int type_f() { return sizeof T::type; } // expected-error {{expected parentheses around type name in sizeof expression}} +template int type_g() { return sizeof(T::type); } +template int type_h() { return sizeof((T::type)); } //expected-error {{expected expression}} +template int value_f() { return sizeof T::not_a_type; } //expected-error {{expected parentheses around type name in sizeof expression}} template int value_g() { return sizeof(T::not_a_type); } -template int value_h() { return sizeof((T::not_a_type)); } +template int value_h() { return sizeof((T::not_a_type)); } //expected-error {{expected expression}} struct X { typedef int type; static const int not_a_type; }; int bar() { return - type_f() + // expected-note-re {{in instantiation {{.*}} requested here}} - type_g() + // expected-note-re {{in instantiation {{.*}} requested here}} - type_h() + // expected-note-re {{in instantiation {{.*}} requested here}} + type_f() + + type_g() + + type_h() + value_f() + value_f() + value_f(); Index: test/SemaTemplate/typename-specifier.cpp =================================================================== --- test/SemaTemplate/typename-specifier.cpp +++ test/SemaTemplate/typename-specifier.cpp @@ -139,7 +139,12 @@ namespace missing_typename { -template struct pair {}; // expected-note 7 {{template parameter is declared here}} +#ifdef MSVC +// expected-note@+4 5 {{template parameter is declared here}} +#else +// expected-note@+2 7 {{template parameter is declared here}} +#endif +template struct pair {}; template struct map { @@ -158,7 +163,7 @@ void foo() { #ifdef MSVC - // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}} + // no error #else // expected-error@+2 {{template argument for template type parameter must be a type; did you forget 'typename'?}} #endif @@ -178,7 +183,7 @@ static void bar() { #ifdef MSVC - // expected-warning@+4 {{omitted 'typename' is a Microsoft extension}} + // no error #else // expected-error@+2 {{template argument for template type parameter must be a type; did you forget 'typename'?}} #endif @@ -231,31 +236,59 @@ template void f(); template void f(); -// expected-error@+1 {{missing 'typename' prior to dependent type name 'S::type'}} +#ifdef MSVC +// no error +#else +// expected-error@+2 {{missing 'typename' prior to dependent type name 'S::type'}} +#endif template void g() { f::type(int())>(); } // Adding typename does fix the diagnostic. template void h() { f::type(int())>(); } void j() { - g(); // expected-note-re {{in instantiation {{.*}} requested here}} +#ifdef MSVC + // no note. +#else + // expected-note-re@+2 {{in instantiation {{.*}} requested here}} +#endif + g(); h(); } } // namespace func_type_vs_construct_tmp namespace pointer_vs_multiply { int x; -// expected-error@+1 {{missing 'typename' prior to dependent type name 'B::type_or_int'}} +#ifdef MSVC +// expected-error@+4 {{typename specifier refers to non-type member 'type_or_int' in 'pointer_vs_multiply::A'}} +#else +// expected-error@+2 {{missing 'typename' prior to dependent type name 'B::type_or_int'}} +#endif template void g() { T::type_or_int * x; } // expected-error@+1 {{typename specifier refers to non-type member 'type_or_int' in 'pointer_vs_multiply::A'}} template void h() { typename T::type_or_int * x; } +#ifdef MSVC +// expected-note@+4 {{referenced member 'type_or_int' is declared here}} +#else +// no note +#endif struct A { static const int type_or_int = 5; }; // expected-note {{referenced member 'type_or_int' is declared here}} struct B { typedef int type_or_int; }; void j() { +#ifdef MSVC + //expected-note@+4 {{in instantiation of function template specialization 'pointer_vs_multiply::g' requested here}} +#else + // no note +#endif g(); - g(); // expected-note-re {{in instantiation {{.*}} requested here}} +#ifdef MSVC + // no note +#else + // expected-note-re@+2 {{in instantiation {{.*}} requested here}} +#endif + g(); h(); // expected-note-re {{in instantiation {{.*}} requested here}} h(); }