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