When performing substitution of template arguments within the body of

a template, be sure to include the template arguments from the
injected-class-name. Fixes PR7587.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107895 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2010-07-08 18:37:38 +00:00
Родитель f9c10c70b3
Коммит 24bae92f08
9 изменённых файлов: 95 добавлений и 28 удалений

Просмотреть файл

@ -1476,7 +1476,7 @@ public:
/// typedef array this_type; // "array" is equivalent to "array<T, N>"
/// };
/// \endcode
QualType getInjectedClassNameSpecialization(ASTContext &Context);
QualType getInjectedClassNameSpecialization();
/// \brief Retrieve the member class template that this class template was
/// derived from.

Просмотреть файл

@ -201,7 +201,7 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) {
}
QualType
ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) {
ClassTemplateDecl::getInjectedClassNameSpecialization() {
Common *CommonPtr = getCommonPtr();
if (!CommonPtr->InjectedClassNameType.isNull())
return CommonPtr->InjectedClassNameType;
@ -210,7 +210,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) {
// corresponding to template parameter packs should be pack
// expansions. We already say that in 14.6.2.1p2, so it would be
// better to fix that redundancy.
ASTContext &Context = getASTContext();
TemplateParameterList *Params = getTemplateParameters();
llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
TemplateArgs.reserve(Params->size());

Просмотреть файл

@ -96,7 +96,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
// injected class name of the named class template, we're entering
// into that class template definition.
QualType Injected
= ClassTemplate->getInjectedClassNameSpecialization(Context);
= ClassTemplate->getInjectedClassNameSpecialization();
if (Context.hasSameType(Injected, ContextType))
return ClassTemplate->getTemplatedDecl();

Просмотреть файл

@ -3317,9 +3317,10 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
MultiLevelTemplateArgumentList ArgList
= getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true);
InstantiatingTemplate Inst(*this, CallLoc, Param,
ArgList.getInnermost().getFlatArgumentList(),
ArgList.getInnermost().flat_size());
std::pair<const TemplateArgument *, unsigned> Innermost
= ArgList.getInnermost();
InstantiatingTemplate Inst(*this, CallLoc, Param, Innermost.first,
Innermost.second);
OwningExprResult Result = SubstExpr(UninstExpr, ArgList);
if (Result.isInvalid())

Просмотреть файл

@ -884,7 +884,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
NewClass->setDescribedClassTemplate(NewTemplate);
// Build the type for the class template declaration now.
QualType T = NewTemplate->getInjectedClassNameSpecialization(Context);
QualType T = NewTemplate->getInjectedClassNameSpecialization();
T = Context.getInjectedClassNameType(NewClass, T);
assert(T->isDependentType() && "Class template type is not dependent?");
(void)T;

Просмотреть файл

@ -36,10 +36,14 @@ namespace clang {
/// When instantiating X<int>::Y<17>::f, the multi-level template argument
/// list will contain a template argument list (int) at depth 0 and a
/// template argument list (17) at depth 1.
struct MultiLevelTemplateArgumentList {
class MultiLevelTemplateArgumentList {
public:
typedef std::pair<const TemplateArgument *, unsigned> ArgList;
private:
/// \brief The template argument lists, stored from the innermost template
/// argument list (first) to the outermost template argument list (last).
llvm::SmallVector<const TemplateArgumentList *, 4> TemplateArgumentLists;
llvm::SmallVector<ArgList, 4> TemplateArgumentLists;
public:
/// \brief Construct an empty set of template argument lists.
@ -48,7 +52,7 @@ namespace clang {
/// \brief Construct a single-level template argument list.
explicit
MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
TemplateArgumentLists.push_back(&TemplateArgs);
addOuterTemplateArguments(&TemplateArgs);
}
/// \brief Determine the number of levels in this template argument
@ -58,8 +62,8 @@ namespace clang {
/// \brief Retrieve the template argument at a given depth and index.
const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
assert(Depth < TemplateArgumentLists.size());
assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1]->size());
return TemplateArgumentLists[getNumLevels() - Depth - 1]->get(Index);
assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].second);
return TemplateArgumentLists[getNumLevels() - Depth - 1].first[Index];
}
/// \brief Determine whether there is a non-NULL template argument at the
@ -69,7 +73,7 @@ namespace clang {
bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
assert(Depth < TemplateArgumentLists.size());
if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1]->size())
if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].second)
return false;
return !(*this)(Depth, Index).isNull();
@ -78,12 +82,21 @@ namespace clang {
/// \brief Add a new outermost level to the multi-level template argument
/// list.
void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
TemplateArgumentLists.push_back(TemplateArgs);
TemplateArgumentLists.push_back(
ArgList(TemplateArgs->getFlatArgumentList(),
TemplateArgs->flat_size()));
}
/// \brief Add a new outmost level to the multi-level template argument
/// list.
void addOuterTemplateArguments(const TemplateArgument *Args,
unsigned NumArgs) {
TemplateArgumentLists.push_back(ArgList(Args, NumArgs));
}
/// \brief Retrieve the innermost template argument list.
const TemplateArgumentList &getInnermost() const {
return *TemplateArgumentLists.front();
const ArgList &getInnermost() const {
return TemplateArgumentLists.front();
}
};

Просмотреть файл

@ -63,7 +63,8 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
// We're done when we hit an explicit specialization.
if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization)
if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
!isa<ClassTemplatePartialSpecializationDecl>(Spec))
break;
Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
@ -104,6 +105,15 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
RelativeToPrimary = false;
continue;
}
} else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Ctx)) {
if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) {
QualType T = ClassTemplate->getInjectedClassNameSpecialization();
const TemplateSpecializationType *TST
= cast<TemplateSpecializationType>(Context.getCanonicalType(T));
Result.addOuterTemplateArguments(TST->getArgs(), TST->getNumArgs());
if (ClassTemplate->isMemberSpecialization())
break;
}
}
Ctx = Ctx->getParent();

Просмотреть файл

@ -820,7 +820,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// Trigger creation of the type for the instantiation.
SemaRef.Context.getInjectedClassNameType(RecordInst,
Inst->getInjectedClassNameSpecialization(SemaRef.Context));
Inst->getInjectedClassNameSpecialization());
// Finish handling of friends.
if (isFriend) {
@ -978,9 +978,10 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
void *InsertPos = 0;
if (FunctionTemplate && !TemplateParams) {
llvm::FoldingSetNodeID ID;
FunctionTemplateSpecializationInfo::Profile(ID,
TemplateArgs.getInnermost().getFlatArgumentList(),
TemplateArgs.getInnermost().flat_size(),
std::pair<const TemplateArgument *, unsigned> Innermost
= TemplateArgs.getInnermost();
FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first,
Innermost.second,
SemaRef.Context);
FunctionTemplateSpecializationInfo *Info
@ -1089,8 +1090,12 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
}
} else if (FunctionTemplate) {
// Record this function template specialization.
std::pair<const TemplateArgument *, unsigned> Innermost
= TemplateArgs.getInnermost();
Function->setFunctionTemplateSpecialization(FunctionTemplate,
&TemplateArgs.getInnermost(),
new (SemaRef.Context) TemplateArgumentList(SemaRef.Context,
Innermost.first,
Innermost.second),
InsertPos);
} else if (isFriend && D->isThisDeclarationADefinition()) {
// TODO: should we remember this connection regardless of whether
@ -1227,9 +1232,10 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
// template. Check whether there is already a function template
// specialization for this particular set of template arguments.
llvm::FoldingSetNodeID ID;
FunctionTemplateSpecializationInfo::Profile(ID,
TemplateArgs.getInnermost().getFlatArgumentList(),
TemplateArgs.getInnermost().flat_size(),
std::pair<const TemplateArgument *, unsigned> Innermost
= TemplateArgs.getInnermost();
FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first,
Innermost.second,
SemaRef.Context);
FunctionTemplateSpecializationInfo *Info
@ -1374,8 +1380,12 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Method->setDescribedFunctionTemplate(FunctionTemplate);
} else if (FunctionTemplate) {
// Record this function template specialization.
std::pair<const TemplateArgument *, unsigned> Innermost
= TemplateArgs.getInnermost();
Method->setFunctionTemplateSpecialization(FunctionTemplate,
&TemplateArgs.getInnermost(),
new (SemaRef.Context) TemplateArgumentList(SemaRef.Context,
Innermost.first,
Innermost.second),
InsertPos);
} else if (!isFriend) {
// Record that this is an instantiation of a member function.
@ -2597,7 +2607,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
if (ClassTemplate) {
T = ClassTemplate->getInjectedClassNameSpecialization(Context);
T = ClassTemplate->getInjectedClassNameSpecialization();
} else if (ClassTemplatePartialSpecializationDecl *PartialSpec
= dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
ClassTemplate = PartialSpec->getSpecializedTemplate();

Просмотреть файл

@ -156,3 +156,36 @@ namespace PR6239 {
};
}
namespace PR7587 {
template<typename> class X0;
template<typename> struct X1;
template<typename> class X2;
template<typename T> class X3
{
template<
template<typename> class TT,
typename U = typename X1<T>::type
>
struct Inner {
typedef X2<TT<typename X1<T>::type> > Type;
};
const typename Inner<X0>::Type minCoeff() const;
};
template<typename T> class X3<T*>
{
template<
template<typename> class TT,
typename U = typename X1<T>::type
>
struct Inner {
typedef X2<TT<typename X1<T>::type> > Type;
};
const typename Inner<X0>::Type minCoeff() const;
};
}