forked from OSchip/llvm-project
parent
30584ea4a4
commit
87a44eb98a
|
@ -1061,6 +1061,8 @@ protected:
|
|||
/// \brief Data that is common to all of the declarations of a given
|
||||
/// class template.
|
||||
struct Common {
|
||||
Common() : InstantiatedFromMember(0) {}
|
||||
|
||||
/// \brief The class template specializations for this class
|
||||
/// template, including explicit specializations and instantiations.
|
||||
llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
|
||||
|
@ -1072,6 +1074,10 @@ protected:
|
|||
|
||||
/// \brief The injected-class-name type for this class template.
|
||||
QualType InjectedClassNameType;
|
||||
|
||||
/// \brief The templated member class from which this was most
|
||||
/// directly instantiated (or null).
|
||||
ClassTemplateDecl *InstantiatedFromMember;
|
||||
};
|
||||
|
||||
/// \brief Previous declaration of this class template.
|
||||
|
@ -1151,6 +1157,35 @@ public:
|
|||
/// \endcode
|
||||
QualType getInjectedClassNameType(ASTContext &Context);
|
||||
|
||||
/// \brief Retrieve the member class template that this class template was
|
||||
/// derived from.
|
||||
///
|
||||
/// This routine will return non-NULL for templated member classes of
|
||||
/// class templates. For example, given:
|
||||
///
|
||||
/// \code
|
||||
/// template <typename T>
|
||||
/// struct X {
|
||||
/// template <typename U> struct A {};
|
||||
/// };
|
||||
/// \endcode
|
||||
///
|
||||
/// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent
|
||||
/// is X<int>, also a CTSD) for which getSpecializedTemplate() will
|
||||
/// return X<int>::A<U>, a TemplateClassDecl (whose parent is again
|
||||
/// X<int>) for which getInstantiatedFromMemberTemplate() will return
|
||||
/// X<T>::A<U>, a TemplateClassDecl (whose parent is X<T>, also a TCD).
|
||||
///
|
||||
/// \returns null if this is not an instantiation of a member class template.
|
||||
ClassTemplateDecl *getInstantiatedFromMemberTemplate() const {
|
||||
return CommonPtr->InstantiatedFromMember;
|
||||
}
|
||||
|
||||
void setInstantiatedFromMemberTemplate(ClassTemplateDecl *CTD) {
|
||||
assert(!CommonPtr->InstantiatedFromMember);
|
||||
CommonPtr->InstantiatedFromMember = CTD;
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast support
|
||||
static bool classof(const Decl *D)
|
||||
{ return D->getKind() == ClassTemplate; }
|
||||
|
|
|
@ -2846,6 +2846,10 @@ public:
|
|||
CXXRecordDecl *Pattern,
|
||||
const TemplateArgumentList &TemplateArgs);
|
||||
|
||||
bool
|
||||
InstantiateTemplatePattern(SourceLocation PointOfInstantiation,
|
||||
CXXRecordDecl *Pattern);
|
||||
|
||||
bool
|
||||
InstantiateClass(SourceLocation PointOfInstantiation,
|
||||
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
|
||||
|
|
|
@ -568,6 +568,38 @@ Sema::InstantiateBaseSpecifiers(CXXRecordDecl *Instantiation,
|
|||
return Invalid;
|
||||
}
|
||||
|
||||
/// \brief Force a template's pattern class to be instantiated.
|
||||
///
|
||||
/// \returns true if an error occurred
|
||||
bool Sema::InstantiateTemplatePattern(SourceLocation PointOfInstantiation,
|
||||
CXXRecordDecl *Pattern) {
|
||||
if (Pattern->getDefinition(Context)) return false;
|
||||
|
||||
ClassTemplateDecl *PatternTemp = Pattern->getDescribedClassTemplate();
|
||||
if (!PatternTemp) return false;
|
||||
|
||||
// Check whether this template is a lazy instantiation of a
|
||||
// dependent member template, e.g. Inner<U> in
|
||||
// Outer<int>::Inner<U>.
|
||||
ClassTemplateDecl *PatternPatternTemp
|
||||
= PatternTemp->getInstantiatedFromMemberTemplate();
|
||||
if (!PatternPatternTemp) return false;
|
||||
|
||||
ClassTemplateSpecializationDecl *Spec = 0;
|
||||
for (DeclContext *Parent = Pattern->getDeclContext();
|
||||
Parent && !Spec; Parent = Parent->getParent())
|
||||
Spec = dyn_cast<ClassTemplateSpecializationDecl>(Parent);
|
||||
assert(Spec && "Not a member of a class template specialization?");
|
||||
|
||||
// TODO: the error message from a nested failure here is probably
|
||||
// not ideal.
|
||||
return InstantiateClass(PointOfInstantiation,
|
||||
Pattern,
|
||||
PatternPatternTemp->getTemplatedDecl(),
|
||||
Spec->getTemplateArgs(),
|
||||
/* ExplicitInstantiation = */ false);
|
||||
}
|
||||
|
||||
/// \brief Instantiate the definition of a class from a given pattern.
|
||||
///
|
||||
/// \param PointOfInstantiation The point of instantiation within the
|
||||
|
@ -591,6 +623,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
|||
const TemplateArgumentList &TemplateArgs,
|
||||
bool ExplicitInstantiation) {
|
||||
bool Invalid = false;
|
||||
|
||||
// Lazily instantiate member templates here.
|
||||
if (InstantiateTemplatePattern(PointOfInstantiation, Pattern))
|
||||
return true;
|
||||
|
||||
CXXRecordDecl *PatternDef
|
||||
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
|
||||
|
|
|
@ -53,6 +53,8 @@ namespace {
|
|||
Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
|
||||
ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D);
|
||||
Decl *VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
|
||||
Decl *VisitClassTemplateDecl(ClassTemplateDecl *D);
|
||||
Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
|
||||
|
||||
// Base case. FIXME: Remove once we can instantiate everything.
|
||||
Decl *VisitDecl(Decl *) {
|
||||
|
@ -69,6 +71,9 @@ namespace {
|
|||
llvm::SmallVectorImpl<ParmVarDecl *> &Params);
|
||||
bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
|
||||
bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
|
||||
|
||||
TemplateParameterList *
|
||||
InstantiateTemplateParams(TemplateParameterList *List);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -322,6 +327,28 @@ Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
||||
TemplateParameterList *TempParams = D->getTemplateParameters();
|
||||
TemplateParameterList *InstParams = InstantiateTemplateParams(TempParams);
|
||||
if (!InstParams) return NULL;
|
||||
|
||||
CXXRecordDecl *Pattern = D->getTemplatedDecl();
|
||||
CXXRecordDecl *RecordInst
|
||||
= CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), Owner,
|
||||
Pattern->getLocation(), Pattern->getIdentifier(),
|
||||
Pattern->getTagKeywordLoc(), /*PrevDecl=*/ NULL);
|
||||
|
||||
ClassTemplateDecl *Inst
|
||||
= ClassTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(),
|
||||
D->getIdentifier(), InstParams, RecordInst, 0);
|
||||
RecordInst->setDescribedClassTemplate(Inst);
|
||||
Inst->setAccess(D->getAccess());
|
||||
Inst->setInstantiatedFromMemberTemplate(D);
|
||||
|
||||
Owner->addDecl(Inst);
|
||||
return Inst;
|
||||
}
|
||||
|
||||
Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
|
||||
CXXRecordDecl *PrevDecl = 0;
|
||||
if (D->isInjectedClassName())
|
||||
|
@ -639,12 +666,79 @@ TemplateDeclInstantiator::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) {
|
|||
return VisitParmVarDecl(D);
|
||||
}
|
||||
|
||||
Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
|
||||
TemplateTypeParmDecl *D) {
|
||||
// TODO: don't always clone when decls are refcounted.
|
||||
const Type* T = D->getTypeForDecl();
|
||||
assert(T->isTemplateTypeParmType());
|
||||
const TemplateTypeParmType *TTPT = T->getAs<TemplateTypeParmType>();
|
||||
|
||||
TemplateTypeParmDecl *Inst =
|
||||
TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
|
||||
TTPT->getDepth(), TTPT->getIndex(),
|
||||
TTPT->getName(),
|
||||
D->wasDeclaredWithTypename(),
|
||||
D->isParameterPack());
|
||||
|
||||
if (D->hasDefaultArgument()) {
|
||||
QualType DefaultPattern = D->getDefaultArgument();
|
||||
QualType DefaultInst
|
||||
= SemaRef.InstantiateType(DefaultPattern, TemplateArgs,
|
||||
D->getDefaultArgumentLoc(),
|
||||
D->getDeclName());
|
||||
|
||||
Inst->setDefaultArgument(DefaultInst,
|
||||
D->getDefaultArgumentLoc(),
|
||||
D->defaultArgumentWasInherited() /* preserve? */);
|
||||
}
|
||||
|
||||
return Inst;
|
||||
}
|
||||
|
||||
Decl *Sema::InstantiateDecl(Decl *D, DeclContext *Owner,
|
||||
const TemplateArgumentList &TemplateArgs) {
|
||||
TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
|
||||
return Instantiator.Visit(D);
|
||||
}
|
||||
|
||||
/// \brief Instantiates a nested template parameter list in the current
|
||||
/// instantiation context.
|
||||
///
|
||||
/// \param L The parameter list to instantiate
|
||||
///
|
||||
/// \returns NULL if there was an error
|
||||
TemplateParameterList *
|
||||
TemplateDeclInstantiator::InstantiateTemplateParams(TemplateParameterList *L) {
|
||||
// Get errors for all the parameters before bailing out.
|
||||
bool Invalid = false;
|
||||
|
||||
unsigned N = L->size();
|
||||
typedef llvm::SmallVector<Decl*,8> ParamVector;
|
||||
ParamVector Params;
|
||||
Params.reserve(N);
|
||||
for (TemplateParameterList::iterator PI = L->begin(), PE = L->end();
|
||||
PI != PE; ++PI) {
|
||||
Decl *D = Visit(*PI);
|
||||
Params.push_back(D);
|
||||
Invalid = Invalid || !D;
|
||||
}
|
||||
|
||||
// Clean up if we had an error.
|
||||
if (Invalid) {
|
||||
for (ParamVector::iterator PI = Params.begin(), PE = Params.end();
|
||||
PI != PE; ++PI)
|
||||
if (*PI)
|
||||
(*PI)->Destroy(SemaRef.Context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TemplateParameterList *InstL
|
||||
= TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
|
||||
L->getLAngleLoc(), &Params.front(), N,
|
||||
L->getRAngleLoc());
|
||||
return InstL;
|
||||
}
|
||||
|
||||
/// \brief Instantiates the type of the given function, including
|
||||
/// instantiating all of the function parameters.
|
||||
///
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
template <class T> struct A {
|
||||
static T cond;
|
||||
|
||||
template <class U> struct B {
|
||||
static T twice(U value) {
|
||||
return (cond ? value + value : value);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
int foo() {
|
||||
A<bool>::cond = true;
|
||||
return A<bool>::B<int>::twice(4);
|
||||
}
|
Loading…
Reference in New Issue