Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -2639,6 +2639,15 @@ ParsedType T; IdentifierInfo *II = Tok.getIdentifierInfo(); bool IsTemplateName = getLangOpts().CPlusPlus && NextToken().is(tok::less); + if (getLangOpts().MSVCCompat) { + // Patterns of the form type1::type2& A, or type1::type2* A, or type1::type2&& A + // where A is not an identifier, are valid types. + IsTemplateName |= (SS && SS->isSet() && !SS->isEmpty() && + ((NextToken().is(tok::amp) || + NextToken().is(tok::ampamp) || + NextToken().is(tok::star)) && + GetLookAheadToken(2).isNot(tok::identifier))); + } Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T, IsTemplateName); if (T) { Index: lib/Parse/ParseTentative.cpp =================================================================== --- lib/Parse/ParseTentative.cpp +++ lib/Parse/ParseTentative.cpp @@ -1435,6 +1435,10 @@ *HasMissingTypename = true; return TPResult::Ambiguous; } + if (((Tok.is(tok::amp) || Tok.is(tok::star)) && + NextToken().isNot(tok::identifier)) || + (Tok.is(tok::ampamp) && NextToken().is(tok::greater))) + return TPResult::True; } else { // Try to resolve the name. If it doesn't exist, assume it was // intended to name a type and keep disambiguating. Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -751,10 +751,11 @@ if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S)) DiagID = diag::ext_typename_missing; - Diag(SS->getRange().getBegin(), DiagID) - << SS->getScopeRep() << II->getName() - << SourceRange(SS->getRange().getBegin(), IILoc) - << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename "); + if (!IsTemplateName) + Diag(SS->getRange().getBegin(), DiagID) + << SS->getScopeRep() << II->getName() + << SourceRange(SS->getRange().getBegin(), IILoc) + << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename "); SuggestedType = ActOnTypenameType(S, SourceLocation(), *SS, *II, IILoc).get(); } else { Index: test/SemaTemplate/missing-typename.cpp =================================================================== --- /dev/null +++ test/SemaTemplate/missing-typename.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -Wno-unused +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -Wno-unused -fms-compatibility -DMSVC + +struct A { + typedef int BASE_VALUE; +}; + +void g(int &y) {} + +template +void f(int &rValue) { +#ifdef MSVC + // expected-no-diagnostics +#else + // expected-error@+2 {{missing 'typename' prior to dependent type name 'BASE_CLASS::BASE_VALUE'}} +#endif + return g((BASE_CLASS::BASE_VALUE &)rValue); +} + +int main() { + int x; + f(x); +} + +struct site_symmetry_ops {}; + +template +struct class_ { + template + void def(A1 const &a1) {} +}; + +template +struct init { + init() {} +}; + +struct special_position_site_parameter { + typedef char scatterer_type; +}; + +template +struct valued_asu_parameter_heir_wrapper { + static class_ wrap(char const *name) { + return class_(); + } +}; + +template +struct special_position_wrapper { + static void wrap(char const *name) { + valued_asu_parameter_heir_wrapper::wrap(name) +#ifdef MSVC + // expected-no-diagnostics +#else + // expected-error@+2 {{missing 'typename' prior to dependent type name 'wt::scatterer_type'}} +#endif + .def(init()); + } +}; + +void wrap_special_position() { + special_position_wrapper::wrap("special_position_site_parameter"); +}