[cfe-commits] r95442 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/instantiate-member-template.cpp
Douglas Gregor
dgregor at apple.com
Fri Feb 5 14:40:04 PST 2010
Author: dgregor
Date: Fri Feb 5 16:40:03 2010
New Revision: 95442
URL: http://llvm.org/viewvc/llvm-project?rev=95442&view=rev
Log:
Cope with finding the "instantiated" declaration when we are
type-checking within a template definition. In this case, the
"instantiated" declaration is just the declaration itself, found
within the current instantiation. Fixes PR6239.
Modified:
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=95442&r1=95441&r2=95442&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Feb 5 16:40:03 2010
@@ -2170,10 +2170,11 @@
if (!Record->isDependentContext())
return D;
- // If the RecordDecl is actually the injected-class-name or a "templated"
- // declaration for a class template or class template partial
- // specialization, substitute into the injected-class-name of the
- // class template or partial specialization to find the new DeclContext.
+ // 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();
@@ -2183,15 +2184,18 @@
= dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
T = Context.getTypeDeclType(Record);
ClassTemplate = PartialSpec->getSpecializedTemplate();
- }
+ }
if (!T.isNull()) {
- // Substitute into the injected-class-name to get the type corresponding
- // to the instantiation we want. 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?
+ // 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, SourceLocation(), DeclarationName());
assert(!T.isNull() && "Instantiation of injected-class-name cannot fail.");
@@ -2200,26 +2204,37 @@
return T->getAs<RecordType>()->getDecl();
}
- // 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.
+ // 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))
+ = dyn_cast<ClassTemplateSpecializationDecl>(DC))
if (isInstantiationOf(ClassTemplate,
Spec->getSpecializedTemplate()))
return Spec;
+
+ if (!DC->isDependentContext())
+ SawNonDependentContext = true;
}
- assert(false &&
+ // 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 Record;
+ return cast<CXXRecordDecl>(DC);
}
-
+
// Fall through to deal with other dependent record types (e.g.,
// anonymous unions in class templates).
}
Modified: cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp?rev=95442&r1=95441&r2=95442&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp Fri Feb 5 16:40:03 2010
@@ -131,3 +131,28 @@
x1.f(x0l);
}
}
+
+namespace PR6239 {
+ template <typename T>
+ struct X0 {
+ class type {
+ typedef T E;
+ template <E e> // subsitute T for E and bug goes away
+ struct sfinae { };
+
+ template <class U>
+ typename sfinae<&U::operator=>::type test(int);
+ };
+ };
+
+ template <typename T>
+ struct X1 {
+ typedef T E;
+ template <E e> // subsitute T for E and bug goes away
+ struct sfinae { };
+
+ template <class U>
+ typename sfinae<&U::operator=>::type test(int);
+ };
+
+}
More information about the cfe-commits
mailing list