[cfe-commits] r143725 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/class-template-decl.cpp
Devang Patel
dpatel at apple.com
Fri Nov 4 11:52:43 PDT 2011
Author: dpatel
Date: Fri Nov 4 13:52:43 2011
New Revision: 143725
URL: http://llvm.org/viewvc/llvm-project?rev=143725&view=rev
Log:
Revert r143551. It is causing g++.dg/template/crash52.C test failure.
Modified:
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaTemplate/class-template-decl.cpp
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=143725&r1=143724&r2=143725&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Nov 4 13:52:43 2011
@@ -3148,49 +3148,75 @@
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<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;
+
+ 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();
}
-
-
- // Move to the outer template scope.
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(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<ClassTemplateSpecializationDecl>(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<CXXRecordDecl>(DC);
}
// Fall through to deal with other dependent record types (e.g.,
Modified: cfe/trunk/test/SemaTemplate/class-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/class-template-decl.cpp?rev=143725&r1=143724&r2=143725&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/class-template-decl.cpp (original)
+++ cfe/trunk/test/SemaTemplate/class-template-decl.cpp Fri Nov 4 13:52:43 2011
@@ -75,23 +75,3 @@
}
}
-namespace rdar9676205 {
- template <unsigned, class _Tp> class tuple_element;
-
- template <class _T1, class _T2> class pair;
-
- template <class _T1, class _T2>
- class tuple_element<0, pair<_T1, _T2> >
- {
- template <class _Tp>
- struct X
- {
- template <class _Up, bool = X<_Up>::value>
- struct Y
- : public X<_Up>,
- public Y<_Up>
- { };
- };
- };
-}
-
More information about the cfe-commits
mailing list