auto *TD = TST->getTemplateName().getAsTemplateDecl();
if (!TD)
continue;
- auto *BasePrimaryTemplate =
- dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl());
- if (!BasePrimaryTemplate)
- continue;
- BaseRD = BasePrimaryTemplate;
+ if (auto *BasePrimaryTemplate =
+ dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl())) {
+ if (BasePrimaryTemplate->getCanonicalDecl() != RD->getCanonicalDecl())
+ BaseRD = BasePrimaryTemplate;
+ else if (auto *CTD = dyn_cast<ClassTemplateDecl>(TD)) {
+ if (const ClassTemplatePartialSpecializationDecl *PS =
+ CTD->findPartialSpecialization(Base.getType()))
+ if (PS->getCanonicalDecl() != RD->getCanonicalDecl())
+ BaseRD = PS;
+ }
+ }
}
if (BaseRD) {
for (NamedDecl *ND : BaseRD->lookup(&II)) {
template struct UseUnqualifiedTypeNames<Base>;
struct BadBase { };
template struct UseUnqualifiedTypeNames<BadBase>; // expected-note-re 2 {{in instantiation {{.*}} requested here}}
+
+namespace partial_template_lookup {
+
+class Bar;
+class Spare;
+
+template <class T, class X = Bar>
+class FooTemplated;
+
+class FooBase {
+public:
+ typedef int BaseTypedef;
+};
+
+// Partial template spec (unused)
+template <class T>
+class FooTemplated<T, Spare> {};
+
+// Partial template spec (used)
+template <class T>
+class FooTemplated<T, Bar> : public FooBase {};
+
+// Full template spec
+template <class T, class X>
+class FooTemplated : public FooTemplated<T, Bar> {
+public:
+ BaseTypedef Member; // expected-warning {{unqualified lookup}}
+};
+}