зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
f9c10c70b3
Коммит
24bae92f08
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче