r229817 - [MSVC] Improved lookup into dependent/non-dependent bases of dependent class
Alexey Bataev
a.bataev at hotmail.com
Wed Feb 18 20:28:23 PST 2015
Author: abataev
Date: Wed Feb 18 22:28:23 2015
New Revision: 229817
URL: http://llvm.org/viewvc/llvm-project?rev=229817&view=rev
Log:
[MSVC] Improved lookup into dependent/non-dependent bases of dependent class
Patch improves lookup into dependendt bases of dependent class and adds lookup
into non-dependent bases.
Differential Revision: http://reviews.llvm.org/D7173
Modified:
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=229817&r1=229816&r2=229817&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb 18 22:28:23 2015
@@ -128,45 +128,85 @@ bool Sema::isSimpleTypeSpecifier(tok::To
return false;
}
+namespace {
+enum class UnqualifiedTypeNameLookupResult {
+ NotFound,
+ FoundNonType,
+ 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
+lookupUnqualifiedTypeNameInBase(Sema &S, const IdentifierInfo &II,
+ SourceLocation NameLoc,
+ const CXXRecordDecl *RD) {
+ if (!RD->hasDefinition())
+ return UnqualifiedTypeNameLookupResult::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;
+ 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 = lookupUnqualifiedTypeNameInBase(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
Modified: cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp?rev=229817&r1=229816&r2=229817&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp (original)
+++ cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp Wed Feb 18 22:28:23 2015
@@ -303,12 +303,12 @@ static_assert(sizeof(B<int>) == sizeof(A
}
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,66 @@ namespace type_in_base_of_dependent_base
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 type_in_dependent_base_of_non_dependent_type {
+template<typename T> struct A { typedef int NameFromBase; };
+template<typename T> struct B : A<T> {
+ 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}}
+ };
+ 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}}
+ };
+};
+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}}
+};
+template<typename T> struct F : B<T>::C {
+ NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}}
+};
}
namespace lookup_in_function_contexts {
More information about the cfe-commits
mailing list