summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/AST/DeclTemplate.h2
-rw-r--r--clang/lib/AST/DeclTemplate.cpp4
-rw-r--r--clang/lib/Sema/SemaCXXScopeSpec.cpp2
-rw-r--r--clang/lib/Sema/SemaExpr.cpp7
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp2
-rw-r--r--clang/lib/Sema/SemaTemplate.h31
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp12
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp30
-rw-r--r--clang/test/SemaTemplate/instantiate-member-template.cpp33
9 files changed, 95 insertions, 28 deletions
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 1fa596cccb2..135dd3ae78d 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -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.
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 9a7bc9105bd..f00eb0478a7 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -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());
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 42c346fbe83..f56573a8de2 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -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();
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 93cec73d038..66369674f25 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -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())
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index af1cb50006e..31823c72ead 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -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;
diff --git a/clang/lib/Sema/SemaTemplate.h b/clang/lib/Sema/SemaTemplate.h
index ca59e273551..b3f46519ab7 100644
--- a/clang/lib/Sema/SemaTemplate.h
+++ b/clang/lib/Sema/SemaTemplate.h
@@ -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();
}
};
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 897acf39cee..6db0916e445 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -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();
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 853f7c30944..5778a827fcf 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -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();
diff --git a/clang/test/SemaTemplate/instantiate-member-template.cpp b/clang/test/SemaTemplate/instantiate-member-template.cpp
index ae8425e716e..24a3f317e63 100644
--- a/clang/test/SemaTemplate/instantiate-member-template.cpp
+++ b/clang/test/SemaTemplate/instantiate-member-template.cpp
@@ -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;
+ };
+
+}
OpenPOWER on IntegriCloud