static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
const IdentifierInfo &II,
SourceLocation NameLoc) {
- auto *RD = dyn_cast<CXXRecordDecl>(S.CurContext);
- if (!RD || !RD->getDescribedClassTemplate())
+ // 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
if (!TD)
continue;
auto *BasePrimaryTemplate = cast<CXXRecordDecl>(TD->getTemplatedDecl());
+ // 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();
-// RUN: %clang_cc1 -std=c++1y -fms-compatibility -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++1y -fms-compatibility -fno-spell-checking -fsyntax-only -verify %s
template <class T>
struct C : A<int> { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}}
}
+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'}}
+}
+
namespace lookup_in_function_contexts {
template <typename T> struct A { typedef T NameFromBase; };
template <typename T>
return {};
}
- // FIXME: MSVC accepts all of the code below that isn't C++14 only. Downgrade
- // these errors to warnings.
-
static void memberFunc() {
- NameFromBase x; // expected-error {{unknown type name 'NameFromBase'}}
+ NameFromBase x; // expected-warning {{lookup into dependent bases}}
}
static void funcLocalClass() {
struct X {
- NameFromBase x; // expected-error {{unknown type name 'NameFromBase'}}
+ NameFromBase x; // expected-warning {{lookup into dependent bases}}
} y;
}
void localClassMethod() {
struct X {
void bar() {
- NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}}
+ NameFromBase m; // expected-warning {{lookup into dependent bases}}
}
} x;
x.bar();
static void funcLambda() {
auto l = []() {
- NameFromBase x; // expected-error {{unknown type name 'NameFromBase'}}
+ NameFromBase x; // expected-warning {{lookup into dependent bases}}
};
l();
}
static constexpr int constexprFunc() {
- NameFromBase x = {}; // expected-error {{unknown type name 'NameFromBase'}}
- // FIXME: Suppress this diagnostic, we have an initializer.
- // expected-error@-2 {{variables defined in a constexpr function must be initialized}}
+ NameFromBase x = {}; // expected-warning {{lookup into dependent bases}}
return sizeof(x);
}
static auto autoFunc() {
- NameFromBase x; // expected-error {{unknown type name 'NameFromBase'}}
+ NameFromBase x; // expected-warning {{lookup into dependent bases}}
return x;
}
};