Index: lib/Parse/Parser.cpp =================================================================== --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -1798,6 +1798,13 @@ else if (Tok.is(tok::eof)) // Nothing to do here, bail out... return false; } + if (isa(Ty.get())) { + if (getLangOpts().CPlusPlus && Tok.is(tok::identifier) && + (NextToken().is(tok::semi) || NextToken().is(tok::comma))) { + AnnotateScopeToken(SS, IsNewScope); + return false; + } + } // This is a typename. Replace the current token in-place with an // annotation type token. Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -304,7 +304,11 @@ // // 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, 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 @@ -11,7 +11,7 @@ template class B : public A { public: - void z(T a) + void z(T a) { f(a); // expected-warning 2{{use of identifier 'f' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} g(); // expected-warning 2{{use of identifier 'g' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} @@ -116,9 +116,9 @@ void foo() { - B b; - b.g1(); // expected-note {{required here}} - b.g2(); // expected-note {{required here}} + B b; + b.g1(); // expected-note {{required here}} + b.g2(); // expected-note {{required here}} } } @@ -220,8 +220,8 @@ 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'}} + // 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 {{use of undeclared identifier 'U'}} }; 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,12 +4,12 @@ // 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 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); } +template int type_h() { return sizeof((T::type)); } //expected-error {{expected expression}} template int value_f() { return sizeof T::not_a_type; } 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; @@ -17,8 +17,8 @@ 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_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 7 {{template parameter is declared here}} +#else +// expected-note@+2 7 {{template parameter is declared here}} +#endif +template struct pair {}; template struct map { @@ -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(); }