From: Devang Patel Date: Fri, 4 Nov 2011 18:52:43 +0000 (+0000) Subject: Revert r143551. It is causing g++.dg/template/crash52.C test failure. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=03ea52f9f0f6fc796ecae5b568a7be489438269b;p=clang Revert r143551. It is causing g++.dg/template/crash52.C test failure. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143725 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 4cde69f087..bb6f2d347f 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3148,49 +3148,75 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, if (!Record->isDependentContext()) return D; - // Determine whether this record is the "templated" declaration describing - // a class template or class template partial specialization. + // 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; ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate(); - if (ClassTemplate) - ClassTemplate = ClassTemplate->getCanonicalDecl(); - else if (ClassTemplatePartialSpecializationDecl *PartialSpec - = dyn_cast(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(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(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; + + if (ClassTemplate) { + T = ClassTemplate->getInjectedClassNameSpecialization(); + } else if (ClassTemplatePartialSpecializationDecl *PartialSpec + = dyn_cast(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(T) && + "type of partial specialization is not an InjectedClassNameType"); + T = cast(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()->getDecl(); } - - - // Move to the outer template scope. - if (FunctionDecl *FD = dyn_cast(DC)) { - if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){ - DC = FD->getLexicalDeclContext(); - continue; - } + + // 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(DC)) + if (isInstantiationOf(ClassTemplate, + Spec->getSpecializedTemplate())) + return Spec; + + if (!DC->isDependentContext()) + SawNonDependentContext = true; } - - DC = DC->getParent(); + + // 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(DC); } // Fall through to deal with other dependent record types (e.g., diff --git a/test/SemaTemplate/class-template-decl.cpp b/test/SemaTemplate/class-template-decl.cpp index ec4e016385..38b1778abf 100644 --- a/test/SemaTemplate/class-template-decl.cpp +++ b/test/SemaTemplate/class-template-decl.cpp @@ -75,23 +75,3 @@ namespace PR8001 { } } -namespace rdar9676205 { - template class tuple_element; - - template class pair; - - template - class tuple_element<0, pair<_T1, _T2> > - { - template - struct X - { - template ::value> - struct Y - : public X<_Up>, - public Y<_Up> - { }; - }; - }; -} -