Hi rsmith, rnk, thakis,

Provides better qualified/unqualified lookup into dependent bases for MSVC code 
+ improves diagnostics.

http://reviews.llvm.org/D8100

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaTemplate.cpp
  test/SemaCXX/MicrosoftCompatibility.cpp
  test/SemaTemplate/ms-lookup-template-base-classes.cpp
  test/SemaTemplate/typename-specifier.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: test/SemaTemplate/typename-specifier.cpp
===================================================================
--- test/SemaTemplate/typename-specifier.cpp
+++ test/SemaTemplate/typename-specifier.cpp
@@ -211,14 +211,21 @@
 template <typename T> void f();
 template <int N> void f();
 
-// expected-error@+1 {{missing 'typename' prior to dependent type name 'S<int>::type'}}
+#ifdef MSVC
+// expected-warning@+4 {{missing 'typename' prior to dependent type name 'S<T>::type'}}
+#else
+// expected-error@+2 {{missing 'typename' prior to dependent type name 'S<int>::type'}}
+#endif
 template <typename T> void g() { f</*typename*/ S<T>::type(int())>(); }
 
 // Adding typename does fix the diagnostic.
 template <typename T> void h() { f<typename S<T>::type(int())>(); }
 
 void j() {
-  g<int>(); // expected-note-re {{in instantiation {{.*}} requested here}}
+#ifndef MSVC
+  // expected-note-re@+2 {{in instantiation {{.*}} requested here}}
+#endif
+  g<int>();
   h<int>();
 }
 } // namespace func_type_vs_construct_tmp
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
@@ -64,7 +64,7 @@
 class B : public A<T> {
 public:
   void f() {
-    var = 3; // expected-warning {{use of undeclared identifier 'var'; unqualified lookup into dependent bases of class template 'B' is a Microsoft extension}}
+    var = 3; // expected-warning {{use of identifier 'var' found via unqualified lookup into dependent bases of class template 'B<T>' is a Microsoft extension}}
   }
 };
 
@@ -160,7 +160,7 @@
 class A : public T {
 public:
   void f(int hWnd) {
-    m_hWnd = 1; // expected-warning {{use of undeclared identifier 'm_hWnd'; unqualified lookup into dependent bases of class template 'A' is a Microsoft extension}}
+    m_hWnd = 1; // expected-warning {{use of identifier 'm_hWnd' found via unqualified lookup into dependent bases of class template 'A<T>' is a Microsoft extension}}
   }
 };
 
@@ -281,32 +281,32 @@
 namespace typedef_in_base {
 template <typename T> struct A { typedef T NameFromBase; };
 template <typename T> struct B : A<T> {
-  NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}}
+  NameFromBase m; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'B<T>' is a Microsoft extension}} expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
 };
 static_assert(sizeof(B<int>) == 4, "");
 }
 
 namespace struct_in_base {
 template <typename T> struct A { struct NameFromBase {}; };
 template <typename T> struct B : A<T> {
-  NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}}
+  NameFromBase m; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'B<T>' is a Microsoft extension}} expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
 };
 static_assert(sizeof(B<int>) == 1, "");
 }
 
 namespace enum_in_base {
 template <typename T> struct A { enum NameFromBase { X }; };
 template <typename T> struct B : A<T> {
-  NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}}
+  NameFromBase m; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'B<T>' is a Microsoft extension}} expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
 };
 static_assert(sizeof(B<int>) == sizeof(A<int>::NameFromBase), "");
 }
 
 namespace two_types_in_base {
 template <typename T> struct A { typedef T NameFromBase; }; // expected-note {{member found by ambiguous name lookup}}
 template <typename T> struct B { struct NameFromBase { T m; }; }; // expected-note {{member found by ambiguous name lookup}}
 template <typename T> struct C : A<T>, B<T> {
-  NameFromBase m; // expected-error {{member 'NameFromBase' found in multiple base classes of different types}} expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+  NameFromBase m; // expected-error {{member 'NameFromBase' found in multiple base classes of different types}} expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'C<T>' is a Microsoft extension}} expected-warning {{missing 'typename' prior to dependent type name 'C<T>::NameFromBase'}}
 };
 static_assert(sizeof(C<int>) == 4, ""); // expected-note {{in instantiation of template class 'two_types_in_base::C<int>' requested here}}
 }
@@ -322,7 +322,7 @@
 namespace classify_type_from_base {
 template <typename T> struct A { struct NameFromBase {}; };
 template <typename T> struct B : A<T> {
-  A<NameFromBase> m; // expected-warning {{found via unqualified lookup into dependent bases}}
+  A<NameFromBase> m; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'B<T>' is a Microsoft extension}} expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
 };
 }
 
@@ -387,34 +387,34 @@
 template <typename T>
 struct B : A {};
 template <typename T>
-struct C : B<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+struct C : B<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'C<T>' is a Microsoft extension}} expected-warning {{missing 'typename' prior to dependent type name 'C<T>::NameFromBase'}}
 }
 
 namespace type_in_second_dependent_base {
 template <typename T>
 struct A {};
 template<typename T>
 struct B { typedef T NameFromBase; };
 template <typename T>
-struct D : A<T>, B<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+struct D : A<T>, B<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'D<T>' is a Microsoft extension}} expected-warning {{missing 'typename' prior to dependent type name 'D<T>::NameFromBase'}}
 }
 
 namespace type_in_second_non_dependent_base {
 struct A {};
 struct B { typedef int NameFromBase; };
 template<typename T>
 struct C : A, B {};
 template <typename T>
-struct D : C<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+struct D : C<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'D<T>' is a Microsoft extension}} expected-warning {{missing 'typename' prior to dependent type name 'D<T>::NameFromBase'}}
 }
 
 namespace type_in_virtual_base_of_dependent_base {
 template <typename T>
 struct A { typedef T NameFromBase; };
 template <typename T>
 struct B : virtual A<T> {};
 template <typename T>
-struct C : B<T>, virtual A<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+struct C : B<T>, virtual A<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'C<T>' is a Microsoft extension}} expected-warning {{missing 'typename' prior to dependent type name 'C<T>::NameFromBase'}}
 C<int> c;
 }
 
@@ -424,7 +424,7 @@
 template <typename T>
 struct B : public A<T> {};
 template <typename T>
-struct C : B<T>, public A<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} expected-warning {{direct base 'A<int>' is inaccessible due to ambiguity:}}
+struct C : B<T>, public A<T> { NameFromBase m; }; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'C<T>' is a Microsoft extension}} expected-warning {{missing 'typename' prior to dependent type name 'C<T>::NameFromBase'}} expected-warning {{direct base 'A<int>' is inaccessible due to ambiguity:}}
 C<int> c; // expected-note {{in instantiation of template class 'type_in_base_of_multiple_dependent_bases::C<int>' requested here}}
 }
 
@@ -434,14 +434,14 @@
   struct C;
   template<typename TT>
   struct D : C {
-    NameFromBase m; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+    NameFromBase m; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'B<T>' is a Microsoft extension}} expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
   };
   struct E : C {
-    NameFromBase m; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+    NameFromBase m; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'B<T>' is a Microsoft extension}} expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
   };
 };
 template<typename T> struct B<T>::C : B {
-  NameFromBase m; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+  NameFromBase m; // expected-warning {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'B<T>' is a Microsoft extension}} expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
 };
 template<typename T> struct F : B<T>::C {
   NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}}
@@ -453,43 +453,43 @@
 template <typename T>
 struct B : A<T> {
   // expected-warning@+1 {{lookup into dependent bases}}
-  static auto lateSpecifiedFunc() -> decltype(NameFromBase()) {
+  static auto lateSpecifiedFunc() -> decltype(NameFromBase()) { // expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
     return {};
   }
 
   static void memberFunc() {
-    NameFromBase x; // expected-warning {{lookup into dependent bases}}
+    NameFromBase x; // expected-warning {{lookup into dependent bases}} expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
   }
 
   static void funcLocalClass() {
     struct X {
-      NameFromBase x; // expected-warning {{lookup into dependent bases}}
+      NameFromBase x; // expected-warning {{lookup into dependent bases}} expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
     } y;
   }
 
   void localClassMethod() {
     struct X {
       void bar() {
-        NameFromBase m; // expected-warning {{lookup into dependent bases}}
+        NameFromBase m; // expected-warning {{lookup into dependent bases}} expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
       }
     } x;
     x.bar();
   }
 
   static void funcLambda() {
     auto l = []() {
-      NameFromBase x; // expected-warning {{lookup into dependent bases}}
+      NameFromBase x; // expected-warning {{lookup into dependent bases}} expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
     };
     l();
   }
 
   static constexpr int constexprFunc() {
-    NameFromBase x = {}; // expected-warning {{lookup into dependent bases}}
+    NameFromBase x = {}; // expected-warning {{lookup into dependent bases}} expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
     return sizeof(x);
   }
 
   static auto autoFunc() {
-    NameFromBase x; // expected-warning {{lookup into dependent bases}}
+    NameFromBase x; // expected-warning {{lookup into dependent bases}} expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
     return x;
   }
 };
@@ -508,14 +508,14 @@
 struct A { typedef T NameFromBase; };
 template <typename T>
 struct B : A<T> {
-  // expected-warning@+1 {{found via unqualified lookup into dependent bases}}
-  int x = f<NameFromBase>();
+  // expected-warning@+1 {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases of class template 'B<T>' is a Microsoft extension}}
+  int x = f<NameFromBase>(); // expected-warning {{missing 'typename' prior to dependent type name 'B<T>::NameFromBase'}}
 };
 
 // Dependent base class with enum.
 template <typename T> struct C { enum { NameFromBase = 4 }; };
 template <typename T> struct D : C<T> {
-  // expected-warning@+1 {{use of undeclared identifier 'NameFromBase'; unqualified lookup into dependent bases}}
+  // expected-warning@+1 {{use of identifier 'NameFromBase' found via unqualified lookup into dependent bases}}
   int x = f<NameFromBase>();
 };
 }
@@ -547,3 +547,139 @@
   XXX x; // expected-error {{unknown type name}}
 };
 }
+
+namespace complex_qualified_and_unqualified_lookup {
+template <class T> struct Base {
+  T a;
+  // expected-note@+2 4 {{template is declared here}}
+  // expected-note@+1 2 {{must qualify identifier to find this declaration in dependent base class}}
+  template <class U> struct InnerBase {};
+  typedef InnerBase<T> TDInnerBase;
+  // expected-note@+1 {{must qualify identifier to find this declaration in dependent base class}}
+  template <class G> void f(G t) {}
+  // expected-note@+1 {{must qualify identifier to find this declaration in dependent base class}}
+  template <class G> static void fs(G t) {}
+};
+
+template <class T> struct Sub : Base<T> {
+  // expected-note@+2 4 {{template is declared here}}
+  // expected-note@+1 2 {{must qualify identifier to find this declaration in dependent base class}}
+  template <class U> struct InnerSub {};
+  typedef InnerSub<T> TDInnerSub;
+  void g() {}
+};
+
+template <class T> struct SubSub : Sub<T> {
+  // expected-warning@+2 {{use of identifier 'TDInnerBase' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+  // expected-warning@+1 {{missing 'typename' prior to dependent type name 'SubSub<T>::TDInnerBase'}}
+  TDInnerBase b;
+  void g() {
+    typedef Base<T> BaseTD;
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'BaseTD::TDInnerBase'}}
+    BaseTD::TDInnerBase();
+    typename Sub<T>::template InnerBase<T>();
+    // expected-warning@+1 {{use of identifier 'a' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    a = T();
+    // expected-warning@+2 {{use of identifier 'TDInnerBase' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'SubSub<T>::TDInnerBase'}}
+    b = TDInnerBase();
+    // expected-warning@+1 {{use of identifier 'f' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+    f(4);
+    // expected-warning@+2 {{use of identifier 'f' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    // expected-warning@+1 {{use 'template' keyword to treat 'f' as a dependent template name}}
+    f<int>(4);
+    // expected-warning@+2 {{use of identifier 'f' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    // expected-warning@+1 {{use 'template' keyword to treat 'f' as a dependent template name}}
+    f<T>(4);
+    this->f(4);
+    // expected-warning@+1 {{use 'template' keyword to treat 'f' as a dependent template name}}
+    this->f<int>(4);
+    // expected-warning@+1 {{use 'template' keyword to treat 'f' as a dependent template name}}
+    this->f<T>(4);
+    Sub<T>::template f<int>(4);
+    this->template f<int>(4);
+    Sub<T>::template f<T>(4);
+    this->template f<T>(4);
+    // expected-warning@+1 {{use of identifier 'InnerBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+    InnerBase(); // expected-error {{cannot refer to class template 'InnerBase' without a template argument list}}
+    // expected-warning@+2 {{use of identifier 'InnerBase' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'SubSub<T>::InnerBase'}}
+    InnerBase<T>();
+    // expected-warning@+2 {{use of identifier 'TDInnerBase' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'SubSub<T>::TDInnerBase'}}
+    TDInnerBase();
+    // expected-warning@+1 {{use of identifier 'InnerSub' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+    InnerSub(); // expected-error {{cannot refer to class template 'InnerSub' without a template argument list}}
+    // expected-warning@+2 {{use of identifier 'InnerSub' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'SubSub<T>::InnerSub'}}
+    InnerSub<T>();
+    // expected-warning@+2 {{use of identifier 'TDInnerSub' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'SubSub<T>::TDInnerSub'}}
+    TDInnerSub();
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'Sub<T>::InnerBase'}}
+    Sub<T>::InnerBase<T>();
+    Sub<T>::InnerBase(); // expected-error {{cannot refer to class template 'InnerBase' without a template argument list}}
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'Sub<T>::TDInnerBase'}}
+    Sub<T>::TDInnerBase();
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'Sub<T>::InnerSub'}}
+    Sub<T>::InnerSub<T>();
+    Sub<T>::InnerSub(); // expected-error {{cannot refer to class template 'InnerSub' without a template argument list}}
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'Sub<T>::TDInnerSub'}}
+    Sub<T>::TDInnerSub();
+  }
+  static void gs() {
+    typedef Base<T> BaseTD;
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'BaseTD::TDInnerBase'}}
+    BaseTD::TDInnerBase();
+    // expected-warning@+1 {{use of identifier 'fs' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+    fs(4);
+    // expected-warning@+2 {{use of identifier 'fs' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    // expected-warning@+1 {{use 'template' keyword to treat 'fs' as a dependent template name}}
+    fs<int>(4);
+    // expected-warning@+2 {{use of identifier 'fs' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    // expected-warning@+1 {{use 'template' keyword to treat 'fs' as a dependent template name}}
+    fs<T>(4);
+    // expected-warning@+1 {{use of identifier 'InnerBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+    InnerBase(); // expected-error {{cannot refer to class template 'InnerBase' without a template argument list}}
+    // expected-warning@+2 {{use of identifier 'InnerBase' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'SubSub<T>::InnerBase'}}
+    InnerBase<T>();
+    // expected-warning@+2 {{use of identifier 'TDInnerBase' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'SubSub<T>::TDInnerBase'}}
+    TDInnerBase();
+    // expected-warning@+2 {{use of identifier 'InnerSub' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'SubSub<T>::InnerSub'}}
+    InnerSub<T>();
+     // expected-warning@+1 {{use of identifier 'InnerSub' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
+   InnerSub(); // expected-error {{cannot refer to class template 'InnerSub' without a template argument list}}
+    // expected-warning@+2 {{use of identifier 'TDInnerSub' found via unqualified lookup into dependent bases of class template 'SubSub<T>' is a Microsoft extension}}
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'SubSub<T>::TDInnerSub'}}
+    TDInnerSub();
+    Sub<T>::fs(4);
+    // expected-warning@+1 {{use 'template' keyword to treat 'fs' as a dependent template name}}
+    Sub<T>::fs<int>(4);
+    // expected-warning@+1 {{use 'template' keyword to treat 'fs' as a dependent template name}}
+    Sub<T>::fs<T>(4);
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'Sub<T>::InnerBase'}}
+    Sub<T>::InnerBase<T>();
+    Sub<T>::InnerBase(); // expected-error {{cannot refer to class template 'InnerBase' without a template argument list}}
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'Sub<T>::TDInnerBase'}}
+    Sub<T>::TDInnerBase();
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'Sub<T>::InnerSub'}}
+    Sub<T>::InnerSub<T>();
+    Sub<T>::InnerSub(); // expected-error {{cannot refer to class template 'InnerSub' without a template argument list}}
+    // expected-warning@+1 {{missing 'typename' prior to dependent type name 'Sub<T>::TDInnerSub'}}
+    Sub<T>::TDInnerSub();
+  }
+};
+
+void foo() {
+  Sub<int> i;
+  SubSub<int> ii;
+  i.g();
+  // expected-note@+1 {{in instantiation of member function 'complex_qualified_and_unqualified_lookup::SubSub<int>::g' requested here}}
+  ii.g();
+  // expected-note@+1 {{in instantiation of member function 'complex_qualified_and_unqualified_lookup::SubSub<int>::gs' requested here}}
+  SubSub<int>::gs();
+}
+}
Index: test/SemaCXX/MicrosoftCompatibility.cpp
===================================================================
--- test/SemaCXX/MicrosoftCompatibility.cpp
+++ test/SemaCXX/MicrosoftCompatibility.cpp
@@ -172,8 +172,8 @@
    B<U>::TYPE a3; // expected-warning {{missing 'typename' prior to dependent type name}}
    Base2::TYPE a4; // expected-warning {{missing 'typename' prior to dependent type name}}
 
-   A<U>::TYPE a5; // expected-error {{missing 'typename' prior to dependent type name}}
-   Base3::TYPE a6; // expected-error {{missing 'typename' prior to dependent type name}}
+   A<U>::TYPE a5; // expected-warning {{missing 'typename' prior to dependent type name}}
+   Base3::TYPE a6; // expected-warning {{missing 'typename' prior to dependent type name}}
  };
 
 class D {
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -3864,6 +3864,9 @@
 def ext_found_via_dependent_bases_lookup : ExtWarn<"use of identifier %0 "
   "found via unqualified lookup into dependent bases of class templates is a "
   "Microsoft extension">, InGroup<Microsoft>;
+def ext_found_via_dependent_base_lookup : ExtWarn<"use of identifier %0 "
+  "found via unqualified lookup into dependent bases of class template %1 is a "
+  "Microsoft extension">, InGroup<Microsoft>;
 def note_dependent_var_use : Note<"must qualify identifier to find this "
     "declaration in dependent base class">;
 def err_not_found_by_two_phase_lookup : Error<"call to function %0 that is neither "
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -3497,6 +3497,41 @@
   // Primary Expressions.
   SourceRange getExprRange(Expr *E) const;
 
+  /// \brief Checks if currently looking for symbols in a class with dependent
+  /// bases. Used in Microsoft Compatibility mode for better compatibility
+  /// during lookup into classes with dependent bases.
+  /// \param LastChanceToRecover true if no need to check for decl existence in
+  /// base dependent classes, false if still need to check.
+  /// \param SS If not nullptr and not empty the base class is calculated from
+  /// this scope. If not nullptr and empty and \a ObjectType is empty then it is
+  /// calculated in this method from the current context.
+  /// \param ObjectType If specified the base class is calculated from this
+  /// type.
+  /// \param II Used for diagnostic only. If \a SS is not nullptr and empty and
+  /// \a ObjectType is empty and \a is not nullptr \a SS is calculated and a
+  /// diagnostic is emitted.
+  /// \return true if currently trying to lookup in class with the dependent
+  /// base, false otherwise.
+  bool isInClassWithAnyDependentBase(SourceLocation Loc,
+                                     bool IsLastChanceToRecover,
+                                     CXXScopeSpec *SS = nullptr,
+                                     ParsedType ObjectType = ParsedType(),
+                                     const IdentifierInfo *II = nullptr);
+
+  /// \brief Checks if the specified identifier \a II is a class template
+  /// declaration declared in a class with dependent bases (specified in \a SS
+  /// scope).
+  bool isClassTemplateInClassWithAnyDependentBase(CXXScopeSpec &SS,
+                                                  SourceLocation Loc,
+                                                  const IdentifierInfo &II);
+
+  /// \brief Checks if the specified identifier \a II is any member declared in
+  /// a class with dependent bases (specified in \a SS scope).
+  bool isMemberInClassWithAnyDependentBase(CXXScopeSpec &SS, SourceLocation Loc,
+                                           const IdentifierInfo &II,
+                                           bool NonInstanceMemberOnly,
+                                           bool SupposeExistInBaseParm);
+
   ExprResult ActOnIdExpression(
       Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
       UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand,
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -129,98 +129,157 @@
 }
 
 namespace {
-enum class UnqualifiedTypeNameLookupResult {
+enum class IdNameLookupResult {
   NotFound,
-  FoundNonType,
-  FoundType
+  FoundNotSpecifiedKind,
+  SupposeFoundSpecifiedKind,
+  FoundSpecifiedKind
 };
 } // namespace
 
 /// \brief Tries to perform unqualified lookup of the type decls in bases for
 /// dependent class.
-/// \return \a NotFound if no any decls is found, \a FoundNotType if found not a
-/// type decl, \a FoundType if only type decls are found.
-static UnqualifiedTypeNameLookupResult
-lookupUnqualifiedTypeNameInBase(Sema &S, const IdentifierInfo &II,
-                                SourceLocation NameLoc,
-                                const CXXRecordDecl *RD) {
+/// \return \a NotFound if no any decls is found, \a FoundNotSpecifiedKind if
+/// found not a type decl, \a FoundSpecifiedKind if only type decls are found.
+static IdNameLookupResult lookupIdNameInDependentClass(
+    Sema &S, const IdentifierInfo &II, SourceLocation NameLoc,
+    const CXXRecordDecl *RD, bool SupposeExistInBaseParm,
+    const std::function<bool(NamedDecl *)> &CheckKind) {
   if (!RD->hasDefinition())
-    return UnqualifiedTypeNameLookupResult::NotFound;
+    return IdNameLookupResult::NotFound;
   // Look for type decls in base classes.
-  UnqualifiedTypeNameLookupResult FoundTypeDecl =
-      UnqualifiedTypeNameLookupResult::NotFound;
-  for (const auto &Base : RD->bases()) {
-    const CXXRecordDecl *BaseRD = nullptr;
-    if (auto *BaseTT = Base.getType()->getAs<TagType>())
-      BaseRD = BaseTT->getAsCXXRecordDecl();
-    else if (auto *TST = Base.getType()->getAs<TemplateSpecializationType>()) {
-      // Look for type decls in dependent base classes that have known primary
-      // templates.
-      if (!TST || !TST->isDependentType())
-        continue;
-      auto *TD = TST->getTemplateName().getAsTemplateDecl();
-      if (!TD)
-        continue;
-      auto *BasePrimaryTemplate =
-          dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl());
-      if (!BasePrimaryTemplate)
-        continue;
-      BaseRD = BasePrimaryTemplate;
-    }
-    if (BaseRD) {
-      for (NamedDecl *ND : BaseRD->lookup(&II)) {
-        if (!isa<TypeDecl>(ND))
-          return UnqualifiedTypeNameLookupResult::FoundNonType;
-        FoundTypeDecl = UnqualifiedTypeNameLookupResult::FoundType;
-      }
-      if (FoundTypeDecl == UnqualifiedTypeNameLookupResult::NotFound) {
-        switch (lookupUnqualifiedTypeNameInBase(S, II, NameLoc, BaseRD)) {
-        case UnqualifiedTypeNameLookupResult::FoundNonType:
-          return UnqualifiedTypeNameLookupResult::FoundNonType;
-        case UnqualifiedTypeNameLookupResult::FoundType:
-          FoundTypeDecl = UnqualifiedTypeNameLookupResult::FoundType;
+  IdNameLookupResult FoundDecl = IdNameLookupResult::NotFound;
+  for (NamedDecl *ND : RD->lookup(&II)) {
+    if (!CheckKind(ND))
+      return IdNameLookupResult::FoundNotSpecifiedKind;
+    FoundDecl = IdNameLookupResult::FoundSpecifiedKind;
+  }
+  if (FoundDecl == IdNameLookupResult::NotFound) {
+    for (const auto &Base : RD->bases()) {
+      const CXXRecordDecl *BaseRD = nullptr;
+      auto BaseTy = S.getASTContext().getCanonicalType(Base.getType());
+      if (const TagType *BaseTT = BaseTy->getAs<TagType>())
+        BaseRD = BaseTT->getAsCXXRecordDecl();
+      else if (const TemplateSpecializationType *TST =
+                   BaseTy->getAs<TemplateSpecializationType>()) {
+        // Look for type decls in dependent base classes that have known primary
+        // templates.
+        if (!TST || !TST->isDependentType())
+          continue;
+        auto *TD = TST->getTemplateName().getAsTemplateDecl();
+        if (!TD)
+          continue;
+        auto *BasePrimaryTemplate =
+            dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl());
+        if (!BasePrimaryTemplate)
+          continue;
+        BaseRD = BasePrimaryTemplate;
+      } else if (SupposeExistInBaseParm &&
+                 BaseTy->getAs<TemplateTypeParmType>() &&
+                 FoundDecl == IdNameLookupResult::NotFound) {
+        FoundDecl = IdNameLookupResult::SupposeFoundSpecifiedKind;
+      }
+      if (BaseRD) {
+        switch (lookupIdNameInDependentClass(
+            S, II, NameLoc, BaseRD, SupposeExistInBaseParm, CheckKind)) {
+        case IdNameLookupResult::FoundNotSpecifiedKind:
+          return IdNameLookupResult::FoundNotSpecifiedKind;
+        case IdNameLookupResult::FoundSpecifiedKind:
+          FoundDecl = IdNameLookupResult::FoundSpecifiedKind;
+          break;
+        case IdNameLookupResult::SupposeFoundSpecifiedKind:
+          if (FoundDecl == IdNameLookupResult::NotFound)
+            FoundDecl = IdNameLookupResult::SupposeFoundSpecifiedKind;
           break;
-        case UnqualifiedTypeNameLookupResult::NotFound:
+        case IdNameLookupResult::NotFound:
           break;
         }
       }
     }
   }
 
-  return FoundTypeDecl;
+  return FoundDecl;
 }
 
-static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
-                                                      const IdentifierInfo &II,
-                                                      SourceLocation NameLoc) {
+static bool
+isDeclInDependentClass(Sema &S, CXXScopeSpec &SS, SourceLocation Loc,
+                       const IdentifierInfo &II, bool SupposeExistInBaseParm,
+                       const std::function<bool(NamedDecl *)> &CheckKind) {
   // Lookup in the parent class template context, if any.
   const CXXRecordDecl *RD = nullptr;
-  UnqualifiedTypeNameLookupResult FoundTypeDecl =
-      UnqualifiedTypeNameLookupResult::NotFound;
-  for (DeclContext *DC = S.CurContext;
-       DC && FoundTypeDecl == UnqualifiedTypeNameLookupResult::NotFound;
+  IdNameLookupResult FoundDecl = IdNameLookupResult::NotFound;
+  auto *DC = S.computeDeclContext(SS, /*EnteringContext=*/true);
+  if (!DC)
+    DC = S.CurContext;
+  for (; DC && FoundDecl == IdNameLookupResult::NotFound;
        DC = DC->getParent()) {
     // Look for type decls in dependent base classes that have known primary
     // templates.
     RD = dyn_cast<CXXRecordDecl>(DC);
     if (RD && RD->getDescribedClassTemplate())
-      FoundTypeDecl = lookupUnqualifiedTypeNameInBase(S, II, NameLoc, RD);
+      FoundDecl = lookupIdNameInDependentClass(
+          S, II, Loc, RD, SupposeExistInBaseParm, CheckKind);
   }
-  if (FoundTypeDecl != UnqualifiedTypeNameLookupResult::FoundType)
+  if (FoundDecl == IdNameLookupResult::FoundSpecifiedKind ||
+      FoundDecl == IdNameLookupResult::SupposeFoundSpecifiedKind) {
+    if (SS.isEmpty()) {
+      auto *NNS =
+          NestedNameSpecifier::Create(S.getASTContext(),
+                                      /*Prefix=*/nullptr,
+                                      /*Template=*/false, RD->getTypeForDecl());
+      SS.MakeTrivial(S.getASTContext(), NNS, SourceRange(Loc, Loc));
+    }
+    return true;
+  }
+
+  return false;
+}
+
+bool Sema::isClassTemplateInClassWithAnyDependentBase(
+    CXXScopeSpec &SS, SourceLocation Loc, const IdentifierInfo &II) {
+  return isDeclInDependentClass(
+      *this, SS, Loc, II, /*SupposeExistInBaseParm=*/false,
+      [](NamedDecl *ND) -> bool { return isa<ClassTemplateDecl>(ND); });
+}
+
+bool Sema::isMemberInClassWithAnyDependentBase(CXXScopeSpec &SS,
+                                               SourceLocation Loc,
+                                               const IdentifierInfo &II,
+                                               bool NonInstanceMemberOnly,
+                                               bool SupposeExistInBaseParm) {
+  return isDeclInDependentClass(*this, SS, Loc, II, SupposeExistInBaseParm,
+                                [NonInstanceMemberOnly](NamedDecl *ND) -> bool {
+                                  if (ND->isCXXClassMember())
+                                    return NonInstanceMemberOnly
+                                               ? !ND->isCXXInstanceMember()
+                                               : true;
+                                  return false;
+                                });
+}
+
+static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
+                                                      CXXScopeSpec &SS,
+                                                      const IdentifierInfo &II,
+                                                      SourceLocation NameLoc) {
+  bool IsUnqualifiedLookup = SS.isEmpty();
+  if (!isDeclInDependentClass(
+          S, SS, NameLoc, II, /*SupposeExistInBaseParm=*/false,
+          [](NamedDecl *ND) -> bool { return isa<TypeDecl>(ND); }))
     return ParsedType();
 
   // We found some types in dependent base classes.  Recover as if the user
   // wrote 'typename MyClass::II' instead of 'II'.  We'll fully resolve the
   // lookup during template instantiation.
-  S.Diag(NameLoc, diag::ext_found_via_dependent_bases_lookup) << &II;
-
   ASTContext &Context = S.Context;
-  auto *NNS = NestedNameSpecifier::Create(Context, nullptr, false,
-                                          cast<Type>(Context.getRecordType(RD)));
-  QualType T = Context.getDependentNameType(ETK_Typename, NNS, &II);
-
-  CXXScopeSpec SS;
-  SS.MakeTrivial(Context, NNS, SourceRange(NameLoc));
+  if (IsUnqualifiedLookup)
+    S.Diag(NameLoc, diag::ext_found_via_dependent_base_lookup)
+        << &II << S.computeDeclContext(SS, /*EnteringContext=*/true);
+  S.Diag(SS.getBeginLoc(), diag::ext_typename_missing)
+      << SS.getScopeRep() << II.getName()
+      << SourceRange(SS.getBeginLoc(), NameLoc)
+      << FixItHint::CreateInsertion(SS.getBeginLoc(), "typename ");
+  QualType T =
+      Context.getDependentNameType(ETK_Typename, SS.getScopeRep(), &II);
 
   TypeLocBuilder Builder;
   DependentNameTypeLoc DepTL = Builder.push<DependentNameTypeLoc>(T);
@@ -265,8 +324,16 @@
         //
         // 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) {
+          // For qualified lookup in a class template in MSVC mode, look into
+          // dependent base classes where the primary class template is known.
+          if (getLangOpts().MSVCCompat) {
+            if (ParsedType TypeInBase = recoverFromTypeInKnownDependentBase(
+                    *this, *SS, II, NameLoc))
+              return TypeInBase;
+          }
           return ParsedType();
+        }
         
         // We know from the grammar that this name refers to a type,
         // so build a dependent node to describe the type.
@@ -312,13 +379,17 @@
     // Perform unqualified name lookup.
     LookupName(Result, S);
 
-    // For unqualified lookup in a class template in MSVC mode, look into
-    // dependent base classes where the primary class template is known.
-    if (Result.empty() && getLangOpts().MSVCCompat && (!SS || SS->isEmpty())) {
-      if (ParsedType TypeInBase =
-              recoverFromTypeInKnownDependentBase(*this, II, NameLoc))
-        return TypeInBase;
-    }
+  }
+
+  // For unqualified lookup in a class template in MSVC mode, look into
+  // dependent base classes where the primary class template is known.
+  CXXScopeSpec NewSS;
+  if (SS && SS->isValid())
+    NewSS = *SS;
+  if (Result.empty() && getLangOpts().MSVCCompat) {
+    if (ParsedType TypeInBase =
+            recoverFromTypeInKnownDependentBase(*this, NewSS, II, NameLoc))
+      return TypeInBase;
   }
 
   NamedDecl *IIDecl = nullptr;
@@ -745,9 +816,10 @@
 
   // For unqualified lookup in a class template in MSVC mode, look into
   // dependent base classes where the primary class template is known.
-  if (Result.empty() && SS.isEmpty() && getLangOpts().MSVCCompat) {
+  CXXScopeSpec NewSS = SS;
+  if (Result.empty() && getLangOpts().MSVCCompat) {
     if (ParsedType TypeInBase =
-            recoverFromTypeInKnownDependentBase(*this, *Name, NameLoc))
+            recoverFromTypeInKnownDependentBase(*this, NewSS, *Name, NameLoc))
       return TypeInBase;
   }
 
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -168,7 +168,38 @@
   LookupResult R(*this, TName, Name.getLocStart(), LookupOrdinaryName);
   LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
                      MemberOfUnknownSpecialization);
-  if (R.empty()) return TNK_Non_template;
+  if (R.empty()) {
+    // In MSVC mode resolve symbol in a class with dependent bases on
+    // instantiation.
+    if (getLangOpts().MSVCCompat && !hasTemplateKeyword &&
+        Name.getKind() == UnqualifiedId::IK_Identifier) {
+      if (S && S->getFnParent() &&
+          isInClassWithAnyDependentBase(Name.getLocStart(),
+                                        /*IsLastChanceToRecover=*/false, &SS,
+                                        ObjectTypePtr, Name.Identifier)) {
+        R.suppressDiagnostics();
+        // Mark class template declaration as a TNK_Type_template for proper AST
+        // node generation if it used in expression in constructs like
+        // typecasts/constructor calls:
+        // if (Templ<T>(a))
+        //     ^~~~~
+        //     typename
+        // use of undeclared identifier 'Templ'
+        if (isClassTemplateInClassWithAnyDependentBase(SS, Name.getLocStart(),
+                                                       *Name.Identifier)) {
+          Diag(SS.getBeginLoc(), diag::ext_typename_missing)
+              << SS.getScopeRep() << Name.Identifier->getName()
+              << SourceRange(SS.getBeginLoc(), Name.getLocStart())
+              << FixItHint::CreateInsertion(SS.getBeginLoc(), "typename ");
+          TemplateResult = TemplateTy::make(Context.getDependentTemplateName(
+              SS.getScopeRep(), Name.Identifier));
+          return TNK_Type_template;
+        }
+        MemberOfUnknownSpecialization = true;
+      }
+    }
+    return TNK_Non_template;
+  }
   if (R.isAmbiguous()) {
     // Suppress diagnostics;  we'll redo this lookup later.
     R.suppressDiagnostics();
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -1950,51 +1950,52 @@
   return true;
 }
 
-/// In Microsoft mode, if we are inside a template class whose parent class has
-/// dependent base classes, and we can't resolve an unqualified identifier, then
-/// assume the identifier is a member of a dependent base class.  We can only
-/// recover successfully in static methods, instance methods, and other contexts
-/// where 'this' is available.  This doesn't precisely match MSVC's
-/// instantiation model, but it's close enough.
-static Expr *
-recoverFromMSUnqualifiedLookup(Sema &S, ASTContext &Context,
-                               DeclarationNameInfo &NameInfo,
-                               SourceLocation TemplateKWLoc,
-                               const TemplateArgumentListInfo *TemplateArgs) {
-  // Only try to recover from lookup into dependent bases in static methods or
-  // contexts where 'this' is available.
-  QualType ThisType = S.getCurrentThisType();
-  const CXXRecordDecl *RD = nullptr;
-  if (!ThisType.isNull())
-    RD = ThisType->getPointeeType()->getAsCXXRecordDecl();
-  else if (auto *MD = dyn_cast<CXXMethodDecl>(S.CurContext))
-    RD = MD->getParent();
+bool Sema::isInClassWithAnyDependentBase(SourceLocation Loc,
+                                         bool IsLastChanceToRecover,
+                                         CXXScopeSpec *SS,
+                                         ParsedType ObjectType,
+                                         const IdentifierInfo *II) {
+  CXXRecordDecl *RD = nullptr;
+  if (ObjectType && !ObjectType.get().isNull()) {
+    // If ObjectType is defined - get cxx scope from this type.
+    RD = dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(ObjectType.get()));
+  } else if (!SS || SS->isEmpty()) {
+    // Only try to recover from lookup into dependent bases in static methods
+    // or contexts where 'this' is available.
+    QualType ThisType = getCurrentThisType();
+    if (!ThisType.isNull())
+      RD = ThisType->getPointeeType()->getAsCXXRecordDecl();
+    else if (auto *MD = dyn_cast<CXXMethodDecl>(CurContext))
+      RD = MD->getParent();
+  } else {
+    // Cxx scope is set - get class from this scope.
+    RD = dyn_cast_or_null<CXXRecordDecl>(
+        computeDeclContext(*SS, /*EnteringContext=*/true));
+  }
   if (!RD || !RD->hasAnyDependentBases())
-    return nullptr;
-
-  // Diagnose this as unqualified lookup into a dependent base class.  If 'this'
-  // is available, suggest inserting 'this->' as a fixit.
-  SourceLocation Loc = NameInfo.getLoc();
-  auto DB = S.Diag(Loc, diag::ext_undeclared_unqual_id_with_dependent_base);
-  DB << NameInfo.getName() << RD;
-
-  if (!ThisType.isNull()) {
-    DB << FixItHint::CreateInsertion(Loc, "this->");
-    return CXXDependentScopeMemberExpr::Create(
-        Context, /*This=*/nullptr, ThisType, /*IsArrow=*/true,
-        /*Op=*/SourceLocation(), NestedNameSpecifierLoc(), TemplateKWLoc,
-        /*FirstQualifierInScope=*/nullptr, NameInfo, TemplateArgs);
-  }
-
-  // Synthesize a fake NNS that points to the derived class.  This will
-  // perform name lookup during template instantiation.
-  CXXScopeSpec SS;
-  auto *NNS =
-      NestedNameSpecifier::Create(Context, nullptr, true, RD->getTypeForDecl());
-  SS.MakeTrivial(Context, NNS, SourceRange(Loc, Loc));
-  return DependentScopeDeclRefExpr::Create(
-      Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
-      TemplateArgs);
+    return false;
+  // Compute temp cxx scope to check that II member decl exists in this scope.
+  CXXScopeSpec TempSS;
+  if (!SS || SS->isEmpty()) {
+    auto *NNS = NestedNameSpecifier::Create(
+        Context, /*Prefix=*/nullptr, /*Template=*/false, RD->getTypeForDecl());
+    TempSS.MakeTrivial(Context, NNS, SourceRange(Loc, Loc));
+  } else {
+    TempSS = *SS;
+  }
+  if (isMemberInClassWithAnyDependentBase(TempSS, Loc, *II,
+                                          getCurrentThisType().isNull(),
+                                          IsLastChanceToRecover)) {
+    // Found specified member decl in dependent class.
+    if ((!ObjectType || ObjectType.get().isNull()) && SS && SS->isEmpty()) {
+      *SS = TempSS;
+      if (II)
+        Diag(Loc, diag::ext_found_via_dependent_base_lookup)
+            << II << computeDeclContext(*SS, /*EnteringContext=*/true);
+    }
+    return true;
+  }
+  return false;
 }
 
 ExprResult
@@ -2102,10 +2103,24 @@
   bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen);
 
   if (R.empty() && !ADL) {
-    if (SS.isEmpty() && getLangOpts().MSVCCompat) {
-      if (Expr *E = recoverFromMSUnqualifiedLookup(*this, Context, NameInfo,
-                                                   TemplateKWLoc, TemplateArgs))
-        return E;
+    /// In Microsoft mode, if we are inside a template class whose parent class
+    /// has dependent base classes, and we can't resolve an unqualified
+    /// identifier, then assume the identifier is a member of a dependent base
+    /// class. We can only recover successfully in static methods, instance
+    /// methods, and other contexts where 'this' is available.  This doesn't
+    /// precisely match MSVC's instantiation model, but it's close enough.
+    if (SS.isEmpty() && getLangOpts().MSVCCompat &&
+        isInClassWithAnyDependentBase(NameLoc, /*IsLastChanceToRecover=*/true,
+                                      &SS, ParsedType(), II)) {
+      if (getCurrentThisType().isNull())
+        return DependentScopeDeclRefExpr::Create(
+            Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
+            TemplateArgs);
+      return CXXDependentScopeMemberExpr::Create(
+          Context, /*This=*/nullptr, getCurrentThisType(),
+          /*IsArrow=*/true,
+          /*Op=*/SourceLocation(), NestedNameSpecifierLoc(), TemplateKWLoc,
+          /*FirstQualifierInScope=*/nullptr, NameInfo, TemplateArgs);
     }
 
     // Don't diagnose an empty lookup for inline assembly.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to