Hi rsmith,

Patch improves lookup into dependendt bases of dependent class and adds lookup 
into non-dependent bases.

http://reviews.llvm.org/D7173

Files:
  include/clang/AST/Type.h
  lib/AST/Type.cpp
  lib/Sema/SemaDecl.cpp
  test/SemaTemplate/ms-lookup-template-base-classes.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
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
@@ -303,12 +303,12 @@
 }
 
 namespace two_types_in_base {
-template <typename T> struct A { typedef T NameFromBase; };
-template <typename T> struct B { struct NameFromBase { T m; }; };
+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 {{unknown type name 'NameFromBase'}}
+  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}}
 };
-static_assert(sizeof(C<int>) == 4, "");
+static_assert(sizeof(C<int>) == 4, ""); // expected-note {{in instantiation of template class 'two_types_in_base::C<int>' requested here}}
 }
 
 namespace type_and_decl_in_base {
@@ -386,9 +386,28 @@
 struct A { typedef int NameFromBase; };
 template <typename T>
 struct B : A {};
-// FIXME: MSVC accepts this.
 template <typename T>
-struct C : B<T> { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}}
+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}}
+}
+
+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}}
+C<int> c;
+}
+
+namespace type_in_base_of_multiple_dependent_bases {
+template <typename T>
+struct A { typedef T NameFromBase; };
+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:}}
+C<int> c; // expected-note {{in instantiation of template class 'type_in_base_of_multiple_dependent_bases::C<int>' requested here}}
 }
 
 namespace lookup_in_function_contexts {
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h
+++ include/clang/AST/Type.h
@@ -3374,6 +3374,7 @@
 
 public:
   TagDecl *getDecl() const;
+  TagDecl *getDecl();
 
   /// @brief Determines whether this type is in the process of being
   /// defined.
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -128,45 +128,82 @@
   return false;
 }
 
+namespace {
+enum BasesLookupResult { NotFound, FoundNotType, FoundType };
+} // 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 BasesLookupResult lookupInBases(Sema &S, const IdentifierInfo &II,
+                                       SourceLocation NameLoc,
+                                       const CXXRecordDecl *RD) {
+  if (!RD || !RD->getDescribedClassTemplate())
+    return NotFound;
+
+  // Look for type decls in base classes.
+  BasesLookupResult FoundTypeDecl = NotFound;
+  for (const auto &Base : RD->bases()) {
+    if (auto *TT = Base.getType()->getAs<TagType>()) {
+      // Look for type decls in non-dependent base classes.
+      if (auto *DC = dyn_cast<DeclContext>(TT->getDecl())) {
+        LookupResult LR(S, DeclarationName(&II), NameLoc,
+                        /*LookupKind=*/Sema::LookupAnyName);
+        if (!S.LookupQualifiedName(LR, DC) &&
+            LR.getResultKind() == LookupResult::NotFound)
+          continue;
+        if (!LR.getAsSingle<TypeDecl>())
+          return FoundNotType;
+        FoundTypeDecl = FoundType;
+      }
+    } 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;
+      switch (lookupInBases(S, II, NameLoc, BasePrimaryTemplate)) {
+      case FoundNotType:
+        return FoundNotType;
+      case FoundType:
+        FoundTypeDecl = FoundType;
+        break;
+      case NotFound:
+        break;
+      }
+      for (NamedDecl *ND : BasePrimaryTemplate->lookup(&II)) {
+        if (!isa<TypeDecl>(ND))
+          return FoundNotType;
+        FoundTypeDecl = FoundType;
+      }
+    }
+  }
+
+  return FoundTypeDecl;
+}
+
 static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
                                                       const IdentifierInfo &II,
                                                       SourceLocation NameLoc) {
   // Find the first parent class template context, if any.
-  // FIXME: Perform the lookup in all enclosing class templates.
   const CXXRecordDecl *RD = nullptr;
   for (DeclContext *DC = S.CurContext; DC; DC = DC->getParent()) {
     RD = dyn_cast<CXXRecordDecl>(DC);
     if (RD && RD->getDescribedClassTemplate())
       break;
   }
-  if (!RD)
-    return ParsedType();
-
   // Look for type decls in dependent base classes that have known primary
   // templates.
-  bool FoundTypeDecl = false;
-  for (const auto &Base : RD->bases()) {
-    auto *TST = Base.getType()->getAs<TemplateSpecializationType>();
-    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;
-    // FIXME: Allow lookup into non-dependent bases of dependent bases, possibly
-    // by calling or integrating with the main LookupQualifiedName mechanism.
-    for (NamedDecl *ND : BasePrimaryTemplate->lookup(&II)) {
-      if (FoundTypeDecl)
-        return ParsedType();
-      FoundTypeDecl = isa<TypeDecl>(ND);
-      if (!FoundTypeDecl)
-        return ParsedType();
-    }
-  }
-  if (!FoundTypeDecl)
+  BasesLookupResult FoundTypeDecl = lookupInBases(S, II, NameLoc, RD);
+  if (FoundTypeDecl != FoundType)
     return ParsedType();
 
   // We found some types in dependent base classes.  Recover as if the user
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp
+++ lib/AST/Type.cpp
@@ -1895,6 +1895,10 @@
   return getInterestingTagDecl(decl);
 }
 
+TagDecl *TagType::getDecl() {
+  return getInterestingTagDecl(decl);
+}
+
 bool TagType::isBeingDefined() const {
   return getDecl()->isBeingDefined();
 }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to