Update after review
http://reviews.llvm.org/D7173
Files:
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,46 @@
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_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}}
+}
+
+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}}
+}
+
+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: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -128,45 +128,95 @@
return false;
}
+namespace {
+enum class UnqualifiedTypeNameLookupResult {
+ NotFound,
+ FoundNonTypeTemplateParam,
+ 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 UnqualifiedTypeNameLookupResult
+lookupUnqualifiedTypeNameInDependentBase(Sema &S, const IdentifierInfo &II,
+ SourceLocation NameLoc,
+ const CXXRecordDecl *RD) {
+ if (!RD || !RD->getDescribedClassTemplate())
+ return UnqualifiedTypeNameLookupResult::NotFound;
+
+ // Look for type decls in base classes.
+ UnqualifiedTypeNameLookupResult FoundTypeDecl =
+ UnqualifiedTypeNameLookupResult::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 UnqualifiedTypeNameLookupResult::FoundNonTypeTemplateParam;
+ FoundTypeDecl = UnqualifiedTypeNameLookupResult::FoundType;
+ }
+ continue;
+ }
+ 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;
+ for (NamedDecl *ND : BasePrimaryTemplate->lookup(&II)) {
+ if (!isa<TypeDecl>(ND))
+ return UnqualifiedTypeNameLookupResult::FoundNonTypeTemplateParam;
+ FoundTypeDecl = UnqualifiedTypeNameLookupResult::FoundType;
+ }
+ if (FoundTypeDecl == UnqualifiedTypeNameLookupResult::NotFound) {
+ switch (lookupUnqualifiedTypeNameInDependentBase(S, II, NameLoc,
+ BasePrimaryTemplate)) {
+ case UnqualifiedTypeNameLookupResult::FoundNonTypeTemplateParam:
+ return UnqualifiedTypeNameLookupResult::FoundNonTypeTemplateParam;
+ case UnqualifiedTypeNameLookupResult::FoundType:
+ FoundTypeDecl = UnqualifiedTypeNameLookupResult::FoundType;
+ break;
+ case UnqualifiedTypeNameLookupResult::NotFound:
+ break;
+ }
+ }
+ }
+ }
+
+ 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.
+ // Lookup in the parent class template context, if any.
const CXXRecordDecl *RD = nullptr;
- for (DeclContext *DC = S.CurContext; DC; DC = DC->getParent()) {
+ UnqualifiedTypeNameLookupResult FoundTypeDecl =
+ UnqualifiedTypeNameLookupResult::NotFound;
+ for (DeclContext *DC = S.CurContext;
+ DC && FoundTypeDecl == UnqualifiedTypeNameLookupResult::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())
- 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();
- }
+ FoundTypeDecl =
+ lookupUnqualifiedTypeNameInDependentBase(S, II, NameLoc, RD);
}
- if (!FoundTypeDecl)
+ if (FoundTypeDecl != UnqualifiedTypeNameLookupResult::FoundType)
return ParsedType();
// We found some types in dependent base classes. Recover as if the user
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits