[cfe-commits] r107895 - in /cfe/trunk: include/clang/AST/DeclTemplate.h lib/AST/DeclTemplate.cpp lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplate.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/instantiate-member-template.cpp
Douglas Gregor
dgregor at apple.com
Thu Jul 8 11:37:38 PDT 2010
Author: dgregor
Date: Thu Jul 8 13:37:38 2010
New Revision: 107895
URL: http://llvm.org/viewvc/llvm-project?rev=107895&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/AST/DeclTemplate.h
cfe/trunk/lib/AST/DeclTemplate.cpp
cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplate.h
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp
Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Thu Jul 8 13:37:38 2010
@@ -1476,7 +1476,7 @@
/// 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.
Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Thu Jul 8 13:37:38 2010
@@ -201,7 +201,7 @@
}
QualType
-ClassTemplateDecl::getInjectedClassNameSpecialization(ASTContext &Context) {
+ClassTemplateDecl::getInjectedClassNameSpecialization() {
Common *CommonPtr = getCommonPtr();
if (!CommonPtr->InjectedClassNameType.isNull())
return CommonPtr->InjectedClassNameType;
@@ -210,7 +210,7 @@
// 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());
Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Thu Jul 8 13:37:38 2010
@@ -96,7 +96,7 @@
// 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();
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jul 8 13:37:38 2010
@@ -3317,9 +3317,10 @@
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())
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Jul 8 13:37:38 2010
@@ -884,7 +884,7 @@
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;
Modified: cfe/trunk/lib/Sema/SemaTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.h?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.h (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.h Thu Jul 8 13:37:38 2010
@@ -36,10 +36,14 @@
/// 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 @@
/// \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 @@
/// \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 @@
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 @@
/// \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();
}
};
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Jul 8 13:37:38 2010
@@ -63,7 +63,8 @@
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 @@
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();
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Jul 8 13:37:38 2010
@@ -820,7 +820,7 @@
// 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 @@
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 @@
}
} 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 @@
// 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 @@
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 @@
ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
if (ClassTemplate) {
- T = ClassTemplate->getInjectedClassNameSpecialization(Context);
+ T = ClassTemplate->getInjectedClassNameSpecialization();
} else if (ClassTemplatePartialSpecializationDecl *PartialSpec
= dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
ClassTemplate = PartialSpec->getSpecializedTemplate();
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=107895&r1=107894&r2=107895&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp Thu Jul 8 13:37:38 2010
@@ -156,3 +156,36 @@
};
}
+
+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;
+ };
+
+}
More information about the cfe-commits
mailing list