cfe-commits try 2
http://reviews.llvm.org/D4237
Files:
lib/Sema/SemaDecl.cpp
test/SemaTemplate/ms-lookup-template-base-classes.cpp
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -128,6 +128,51 @@
return false;
}
+static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
+ CXXRecordDecl *RD,
+ const IdentifierInfo &II,
+ SourceLocation NameLoc) {
+ // 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)
+ continue;
+ auto *TD = TST->getTemplateName().getAsTemplateDecl();
+ if (!TD)
+ continue;
+ auto *BasePrimaryTemplate = cast<CXXRecordDecl>(TD->getTemplatedDecl());
+ for (NamedDecl *ND : BasePrimaryTemplate->lookup(&II)) {
+ if (FoundTypeDecl)
+ return ParsedType();
+ FoundTypeDecl = isa<TypeDecl>(ND);
+ if (!FoundTypeDecl)
+ return ParsedType();
+ }
+ }
+
+ // We found some types in dependent base classes. Recover as if the user
+ // wrote 'typename MyClass::II' instead of 'II'. We'll fully resolve the
+ // lookup during template instantiation.
+ S.Diag(NameLoc, diag::ext_found_via_dependent_bases_lookup) << &II;
+
+ ASTContext &Context = S.Context;
+ auto *NNS = NestedNameSpecifier::Create(Context, nullptr, false,
+ cast<Type>(Context.getRecordType(RD)));
+ QualType T = Context.getDependentNameType(ETK_Typename, NNS, &II);
+
+ CXXScopeSpec SS;
+ SS.MakeTrivial(Context, NNS, SourceRange(NameLoc));
+
+ TypeLocBuilder Builder;
+ DependentNameTypeLoc DepTL = Builder.push<DependentNameTypeLoc>(T);
+ DepTL.setNameLoc(NameLoc);
+ DepTL.setElaboratedKeywordLoc(SourceLocation());
+ DepTL.setQualifierLoc(SS.getWithLocInContext(Context));
+ return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
+}
+
/// \brief If the identifier refers to a type name within this scope,
/// return the declaration of that type.
///
@@ -209,6 +254,18 @@
} else {
// Perform unqualified name lookup.
LookupName(Result, S);
+
+ // For unqualified lookup in a class template in MSVC mode, look into
+ // dependent base classes where the primary class template is known.
+ if (Result.empty() && getLangOpts().MSVCCompat && (!SS || SS->isEmpty())) {
+ auto *RD = dyn_cast<CXXRecordDecl>(CurContext);
+ if (RD && RD->getDescribedClassTemplate()) {
+ ParsedType TypeInBase =
+ recoverFromTypeInKnownDependentBase(*this, RD, II, NameLoc);
+ if (TypeInBase)
+ return TypeInBase;
+ }
+ }
}
NamedDecl *IIDecl = nullptr;
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
@@ -275,3 +275,59 @@
};
template struct Derived<int>;
}
+
+namespace typedef_in_base {
+template <typename T> struct A { typedef T NameFromBase; };
+template <typename T> struct B : A<T> {
+ NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}}
+};
+static_assert(sizeof(B<int>) == 4, "");
+}
+
+namespace struct_in_base {
+template <typename T> struct A { struct NameFromBase {}; };
+template <typename T> struct B : A<T> {
+ NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}}
+};
+static_assert(sizeof(B<int>) == 1, "");
+}
+
+namespace enum_in_base {
+template <typename T> struct A { enum NameFromBase { X }; };
+template <typename T> struct B : A<T> {
+ NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}}
+};
+static_assert(sizeof(B<int>) == sizeof(A<int>::NameFromBase), "");
+}
+
+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 C : A<T>, B<T> {
+ NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}}
+};
+static_assert(sizeof(C<int>) == 4, "");
+}
+
+namespace type_and_decl_in_base {
+template <typename T> struct A { typedef T NameFromBase; };
+template <typename T> struct B { static const T NameFromBase = 42; };
+template <typename T> struct C : A<T>, B<T> {
+ NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}}
+};
+}
+
+namespace template_in_base {
+template <typename T> struct A {
+ template <typename U> struct NameFromBase { U x; };
+};
+template <typename T> struct B : A<T> {
+ // Correct form.
+ typename B::template NameFromBase<T> m;
+};
+template <typename T> struct C : A<T> {
+ // Incorrect form.
+ NameFromBase<T> m; // expected-error {{unknown type name 'NameFromBase'}}
+ //expected-error@-1 {{expected member name or ';' after declaration specifiers}}
+};
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits