Explicit instantiations of templates now instantiate the definitions
of class members (recursively). Only member classes are actually instantiated; the instantiation logic for member functions and variables are just stubs. llvm-svn: 71713
This commit is contained in:
parent
5879fbd933
commit
bbbb02d463
|
@ -2116,6 +2116,14 @@ public:
|
|||
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
||||
bool ExplicitInstantiation);
|
||||
|
||||
void InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
||||
CXXRecordDecl *Instantiation,
|
||||
const TemplateArgumentList &TemplateArgs);
|
||||
|
||||
void InstantiateClassTemplateSpecializationMembers(
|
||||
SourceLocation PointOfInstantiation,
|
||||
ClassTemplateSpecializationDecl *ClassTemplateSpec);
|
||||
|
||||
NestedNameSpecifier *
|
||||
InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,
|
||||
SourceRange Range,
|
||||
|
@ -2125,6 +2133,9 @@ public:
|
|||
InstantiateTemplateName(TemplateName Name, SourceLocation Loc,
|
||||
const TemplateArgumentList &TemplateArgs);
|
||||
|
||||
void InstantiateFunctionDefinition(FunctionDecl *Function);
|
||||
void InstantiateVariableDefinition(VarDecl *Var);
|
||||
|
||||
// Simple function for cloning expressions.
|
||||
template<typename T>
|
||||
OwningExprResult Clone(T *E) {
|
||||
|
|
|
@ -2335,9 +2335,10 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
|
|||
InstantiateClassTemplateSpecialization(Specialization, true))
|
||||
return true;
|
||||
|
||||
// FIXME: Instantiate all of the members of the template (that
|
||||
// haven't already been instantiated!).
|
||||
|
||||
// Instantiate the members of this class template specialization.
|
||||
InstantiatingTemplate Inst(*this, TemplateLoc, Specialization);
|
||||
InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization);
|
||||
|
||||
return DeclPtrTy::make(Specialization);
|
||||
}
|
||||
|
||||
|
|
|
@ -749,6 +749,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
|||
// Exit the scope of this instantiation.
|
||||
CurContext = PreviousContext;
|
||||
|
||||
// If this is an explicit instantiation, instantiate our members, too.
|
||||
if (!Invalid && ExplicitInstantiation)
|
||||
InstantiateClassMembers(PointOfInstantiation, Instantiation, TemplateArgs);
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
|
@ -787,6 +791,53 @@ Sema::InstantiateClassTemplateSpecialization(
|
|||
ExplicitInstantiation);
|
||||
}
|
||||
|
||||
/// \brief Instantiate the definitions of all of the member of the
|
||||
/// given class, which is an instantiation of a class template or a
|
||||
/// member class of a template.
|
||||
void
|
||||
Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
||||
CXXRecordDecl *Instantiation,
|
||||
const TemplateArgumentList &TemplateArgs) {
|
||||
for (DeclContext::decl_iterator D = Instantiation->decls_begin(Context),
|
||||
DEnd = Instantiation->decls_end(Context);
|
||||
D != DEnd; ++D) {
|
||||
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
|
||||
if (!Function->getBody(Context))
|
||||
InstantiateFunctionDefinition(Function);
|
||||
} else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
|
||||
const VarDecl *Def = 0;
|
||||
if (!Var->getDefinition(Def))
|
||||
InstantiateVariableDefinition(Var);
|
||||
} else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) {
|
||||
if (!Record->isInjectedClassName() && !Record->getDefinition(Context)) {
|
||||
assert(Record->getInstantiatedFromMemberClass() &&
|
||||
"Missing instantiated-from-template information");
|
||||
InstantiateClass(Record->getLocation(), Record,
|
||||
Record->getInstantiatedFromMemberClass(),
|
||||
TemplateArgs, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Instantiate the definitions of all of the members of the
|
||||
/// given class template specialization, which was named as part of an
|
||||
/// explicit instantiation.
|
||||
void Sema::InstantiateClassTemplateSpecializationMembers(
|
||||
SourceLocation PointOfInstantiation,
|
||||
ClassTemplateSpecializationDecl *ClassTemplateSpec) {
|
||||
// C++0x [temp.explicit]p7:
|
||||
// An explicit instantiation that names a class template
|
||||
// specialization is an explicit instantion of the same kind
|
||||
// (declaration or definition) of each of its members (not
|
||||
// including members inherited from base classes) that has not
|
||||
// been previously explicitly specialized in the translation unit
|
||||
// containing the explicit instantiation, except as described
|
||||
// below.
|
||||
InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
|
||||
ClassTemplateSpec->getTemplateArgs());
|
||||
}
|
||||
|
||||
/// \brief Instantiate a nested-name-specifier.
|
||||
NestedNameSpecifier *
|
||||
Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,
|
||||
|
|
|
@ -550,3 +550,20 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
|
|||
// FIXME: New needs a pointer to Tmpl
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Instantiate the definition of the given function from its
|
||||
/// template.
|
||||
///
|
||||
/// \param Function the already-instantiated declaration of a
|
||||
/// function.
|
||||
void Sema::InstantiateFunctionDefinition(FunctionDecl *Function) {
|
||||
// FIXME: Implement this!
|
||||
}
|
||||
|
||||
/// \brief Instantiate the definition of the given variable from its
|
||||
/// template.
|
||||
///
|
||||
/// \param Var the already-instantiated declaration of a variable.
|
||||
void Sema::InstantiateVariableDefinition(VarDecl *Var) {
|
||||
// FIXME: Implement this!
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify -pedantic %s
|
||||
// RUN: clang-cc -fsyntax-only -pedantic -verify %s
|
||||
//
|
||||
// Tests explicit instantiation of templates.
|
||||
template<typename T, typename U = T> class X0 { };
|
||||
|
@ -46,3 +46,28 @@ struct X2 {
|
|||
|
||||
template struct X2<int>; // okay
|
||||
template struct X2<int&>; // expected-note{{in instantiation of}}
|
||||
|
||||
// Check that explicit instantiations instantiate member classes.
|
||||
template<typename T> struct X3 {
|
||||
struct Inner { // expected-note{{here}}
|
||||
void f(T*); // expected-error{{pointer to a reference}}
|
||||
};
|
||||
};
|
||||
|
||||
void f1(X3<int&>); // okay, Inner, not instantiated
|
||||
|
||||
template struct X3<int&>; // expected-note{{instantiation}}
|
||||
|
||||
template<typename T> struct X4 {
|
||||
struct Inner { // expected-note 2{{here}}
|
||||
struct VeryInner { // expected-note 2{{here}}
|
||||
void f(T*); // expected-error 2{{pointer to a reference}}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
void f2(X4<int&>); // okay, Inner, not instantiated
|
||||
void f3(X4<int&>::Inner); // okay, Inner::VeryInner, not instantiated
|
||||
|
||||
template struct X4<int&>; // expected-note{{instantiation}}
|
||||
template struct X4<float&>; // expected-note{{instantiation}}
|
||||
|
|
Loading…
Reference in New Issue