forked from OSchip/llvm-project
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. llvm-svn: 95442
This commit is contained in:
parent
175629608e
commit
d225fa05bd
|
@ -2170,10 +2170,11 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
|
||||||
if (!Record->isDependentContext())
|
if (!Record->isDependentContext())
|
||||||
return D;
|
return D;
|
||||||
|
|
||||||
// If the RecordDecl is actually the injected-class-name or a "templated"
|
// If the RecordDecl is actually the injected-class-name or a
|
||||||
// declaration for a class template or class template partial
|
// "templated" declaration for a class template, class template
|
||||||
// specialization, substitute into the injected-class-name of the
|
// partial specialization, or a member class of a class template,
|
||||||
// class template or partial specialization to find the new DeclContext.
|
// substitute into the injected-class-name of the class template
|
||||||
|
// or partial specialization to find the new DeclContext.
|
||||||
QualType T;
|
QualType T;
|
||||||
ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
|
ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
|
||||||
|
|
||||||
|
@ -2183,15 +2184,18 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
|
||||||
= dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
|
= dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
|
||||||
T = Context.getTypeDeclType(Record);
|
T = Context.getTypeDeclType(Record);
|
||||||
ClassTemplate = PartialSpec->getSpecializedTemplate();
|
ClassTemplate = PartialSpec->getSpecializedTemplate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!T.isNull()) {
|
if (!T.isNull()) {
|
||||||
// Substitute into the injected-class-name to get the type corresponding
|
// Substitute into the injected-class-name to get the type
|
||||||
// to the instantiation we want. This substitution should never fail,
|
// corresponding to the instantiation we want, which may also be
|
||||||
// since we know we can instantiate the injected-class-name or we wouldn't
|
// the current instantiation (if we're in a template
|
||||||
// have gotten to the injected-class-name!
|
// definition). This substitution should never fail, since we
|
||||||
// FIXME: Can we use the CurrentInstantiationScope to avoid this extra
|
// know we can instantiate the injected-class-name or we
|
||||||
// instantiation in the common case?
|
// 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());
|
T = SubstType(T, TemplateArgs, SourceLocation(), DeclarationName());
|
||||||
assert(!T.isNull() && "Instantiation of injected-class-name cannot fail.");
|
assert(!T.isNull() && "Instantiation of injected-class-name cannot fail.");
|
||||||
|
|
||||||
|
@ -2200,26 +2204,37 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D,
|
||||||
return T->getAs<RecordType>()->getDecl();
|
return T->getAs<RecordType>()->getDecl();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We are performing "partial" template instantiation to create the
|
// We are performing "partial" template instantiation to create
|
||||||
// member declarations for the members of a class template
|
// the member declarations for the members of a class template
|
||||||
// specialization. Therefore, D is actually referring to something in
|
// specialization. Therefore, D is actually referring to something
|
||||||
// the current instantiation. Look through the current context,
|
// in the current instantiation. Look through the current
|
||||||
// which contains actual instantiations, to find the instantiation of
|
// context, which contains actual instantiations, to find the
|
||||||
// the "current instantiation" that D refers to.
|
// instantiation of the "current instantiation" that D refers
|
||||||
|
// to.
|
||||||
|
bool SawNonDependentContext = false;
|
||||||
for (DeclContext *DC = CurContext; !DC->isFileContext();
|
for (DeclContext *DC = CurContext; !DC->isFileContext();
|
||||||
DC = DC->getParent()) {
|
DC = DC->getParent()) {
|
||||||
if (ClassTemplateSpecializationDecl *Spec
|
if (ClassTemplateSpecializationDecl *Spec
|
||||||
= dyn_cast<ClassTemplateSpecializationDecl>(DC))
|
= dyn_cast<ClassTemplateSpecializationDecl>(DC))
|
||||||
if (isInstantiationOf(ClassTemplate,
|
if (isInstantiationOf(ClassTemplate,
|
||||||
Spec->getSpecializedTemplate()))
|
Spec->getSpecializedTemplate()))
|
||||||
return Spec;
|
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");
|
"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.,
|
// Fall through to deal with other dependent record types (e.g.,
|
||||||
// anonymous unions in class templates).
|
// anonymous unions in class templates).
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,3 +131,28 @@ namespace N0 {
|
||||||
x1.f(x0l);
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue