if (!Record->isDependentContext())
return D;
- // If the RecordDecl is actually the injected-class-name or a
- // "templated" declaration for a class template, class template
- // partial specialization, or a member class of a class template,
- // substitute into the injected-class-name of the class template
- // or partial specialization to find the new DeclContext.
- QualType T;
+ // Determine whether this record is the "templated" declaration describing
+ // a class template or class template partial specialization.
ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
-
- if (ClassTemplate) {
- T = ClassTemplate->getInjectedClassNameSpecialization();
- } else if (ClassTemplatePartialSpecializationDecl *PartialSpec
- = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
- ClassTemplate = PartialSpec->getSpecializedTemplate();
-
- // If we call SubstType with an InjectedClassNameType here we
- // can end up in an infinite loop.
- T = Context.getTypeDeclType(Record);
- assert(isa<InjectedClassNameType>(T) &&
- "type of partial specialization is not an InjectedClassNameType");
- T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType();
- }
-
- if (!T.isNull()) {
- // Substitute into the injected-class-name to get the type
- // corresponding to the instantiation we want, which may also be
- // the current instantiation (if we're in a template
- // definition). This substitution should never fail, since we
- // know we can instantiate the injected-class-name or we
- // wouldn't have gotten to the injected-class-name!
-
- // FIXME: Can we use the CurrentInstantiationScope to avoid this
- // extra instantiation in the common case?
- T = SubstType(T, TemplateArgs, Loc, DeclarationName());
- assert(!T.isNull() && "Instantiation of injected-class-name cannot fail.");
-
- if (!T->isDependentType()) {
- assert(T->isRecordType() && "Instantiation must produce a record type");
- return T->getAs<RecordType>()->getDecl();
+ if (ClassTemplate)
+ ClassTemplate = ClassTemplate->getCanonicalDecl();
+ else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record))
+ ClassTemplate = PartialSpec->getSpecializedTemplate()->getCanonicalDecl();
+
+ // Walk the current context to find either the record or an instantiation of
+ // it.
+ DeclContext *DC = CurContext;
+ while (!DC->isFileContext()) {
+ // If we're performing substitution while we're inside the template
+ // definition, we'll find our own context. We're done.
+ if (DC->Equals(Record))
+ return Record;
+
+ if (CXXRecordDecl *InstRecord = dyn_cast<CXXRecordDecl>(DC)) {
+ // Check whether we're in the process of instantiating a class template
+ // specialization of the template we're mapping.
+ if (ClassTemplateSpecializationDecl *InstSpec
+ = dyn_cast<ClassTemplateSpecializationDecl>(InstRecord)){
+ ClassTemplateDecl *SpecTemplate = InstSpec->getSpecializedTemplate();
+ if (ClassTemplate && isInstantiationOf(ClassTemplate, SpecTemplate))
+ return InstRecord;
+ }
+
+ // Check whether we're in the process of instantiating a member class.
+ if (isInstantiationOf(Record, InstRecord))
+ return InstRecord;
}
-
- // We are performing "partial" template instantiation to create
- // the member declarations for the members of a class template
- // specialization. Therefore, D is actually referring to something
- // in the current instantiation. Look through the current
- // context, which contains actual instantiations, to find the
- // instantiation of the "current instantiation" that D refers
- // to.
- bool SawNonDependentContext = false;
- for (DeclContext *DC = CurContext; !DC->isFileContext();
- DC = DC->getParent()) {
- if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(DC))
- if (isInstantiationOf(ClassTemplate,
- Spec->getSpecializedTemplate()))
- return Spec;
-
- if (!DC->isDependentContext())
- SawNonDependentContext = true;
+
+
+ // Move to the outer template scope.
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) {
+ if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){
+ DC = FD->getLexicalDeclContext();
+ continue;
+ }
}
-
- // We're performing "instantiation" of a member of the current
- // instantiation while we are type-checking the
- // definition. Compute the declaration context and return that.
- assert(!SawNonDependentContext &&
- "No dependent context while instantiating record");
- DeclContext *DC = computeDeclContext(T);
- assert(DC &&
- "Unable to find declaration for the current instantiation");
- return cast<CXXRecordDecl>(DC);
+
+ DC = DC->getParent();
}
// Fall through to deal with other dependent record types (e.g.,