Teach Sema::ActOnDependentTemplateName that a dependent template name
in a member access expression referring into the current instantiation
need not be resolved at template definition *if* the current
instantiation has any dependent base classes. Fixes PR6081.

llvm-svn: 93877
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 3e9deda..948949b 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -2053,7 +2053,6 @@
   bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
   CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
   bool isUnknownSpecialization(const CXXScopeSpec &SS);
-  bool isCurrentInstantiationWithDependentBases(const CXXScopeSpec &SS);
 
   /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
   /// global scope ('::').
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 6006bca..7a0b625 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -210,28 +210,6 @@
   return getCurrentInstantiationOf(NNS) == 0;
 }
 
-/// \brief Determine whether the given scope specifier refers to a
-/// current instantiation that has any dependent base clases.
-///
-/// This check is typically used when we've performed lookup into the
-/// current instantiation of a template, but that lookup failed. When
-/// there are dependent bases present, however, the lookup needs to be
-/// delayed until template instantiation time.
-bool Sema::isCurrentInstantiationWithDependentBases(const CXXScopeSpec &SS) {
-  if (!SS.isSet())
-    return false;
-
-  NestedNameSpecifier *NNS = (NestedNameSpecifier*)SS.getScopeRep();
-  if (!NNS->isDependent())
-    return false;
-
-  CXXRecordDecl *CurrentInstantiation = getCurrentInstantiationOf(NNS);
-  if (!CurrentInstantiation)
-    return false;
-
-  return CurrentInstantiation->hasAnyDependentBases();
-}
-
 /// \brief If the given nested name specifier refers to the current
 /// instantiation, return the declaration that corresponds to that
 /// current instantiation (C++0x [temp.dep.type]p1).
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 2fad832..0773a0f 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1586,9 +1586,12 @@
                                  UnqualifiedId &Name,
                                  TypeTy *ObjectType,
                                  bool EnteringContext) {
-  if ((ObjectType &&
-       computeDeclContext(QualType::getFromOpaquePtr(ObjectType))) ||
-      (SS.isSet() && computeDeclContext(SS, EnteringContext))) {
+  DeclContext *LookupCtx = 0;
+  if (SS.isSet())
+    LookupCtx = computeDeclContext(SS, EnteringContext);
+  if (!LookupCtx && ObjectType)
+    LookupCtx = computeDeclContext(QualType::getFromOpaquePtr(ObjectType));
+  if (LookupCtx) {
     // C++0x [temp.names]p5:
     //   If a name prefixed by the keyword template is not the name of
     //   a template, the program is ill-formed. [Note: the keyword
@@ -1608,8 +1611,9 @@
     TemplateTy Template;
     TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType,
                                           EnteringContext, Template);
-    if (TNK == TNK_Non_template && 
-        isCurrentInstantiationWithDependentBases(SS)) {
+    if (TNK == TNK_Non_template && LookupCtx->isDependentContext() &&
+        isa<CXXRecordDecl>(LookupCtx) &&
+        cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()) {
       // This is a dependent template.
     } else if (TNK == TNK_Non_template) {
       Diag(Name.getSourceRange().getBegin(), 
diff --git a/clang/test/SemaTemplate/dependent-base-classes.cpp b/clang/test/SemaTemplate/dependent-base-classes.cpp
index 79b28c2..80d20b0 100644
--- a/clang/test/SemaTemplate/dependent-base-classes.cpp
+++ b/clang/test/SemaTemplate/dependent-base-classes.cpp
@@ -82,3 +82,31 @@
 
   Derived<int> di; // expected-note{{instantiation of}}
 }
+
+namespace PR6081 {
+  template<typename T>
+  struct A { };
+
+  template<typename T>
+  class B : public A<T> 
+  {
+  public:
+    template< class X >
+    void f0(const X & k)
+    {
+      this->template f1<int>()(k);
+    }
+  };
+
+  template<typename T>
+  class C
+  {
+  public:
+    template< class X >
+    void f0(const X & k)
+    {
+      this->template f1<int>()(k); // expected-error{{'f1' following the 'template' keyword does not refer to a template}} \
+      // FIXME: expected-error{{unqualified-id}}
+    }
+  };
+}