Link FunctionDecls instantiated from the member functions of a class

template to the FunctionDecls from which they were instantiated. This
is a necessary first step to support instantiation of the definitions
of such functions, but by itself does essentially nothing.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71792 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2009-05-14 21:06:31 +00:00
Родитель 67a1eadcf7
Коммит 1eee0e753f
6 изменённых файлов: 107 добавлений и 10 удалений

Просмотреть файл

@ -20,6 +20,7 @@
namespace clang {
class Expr;
class FunctionTemplateDecl;
class Stmt;
class CompoundStmt;
class StringLiteral;
@ -524,6 +525,18 @@ private:
// Move to DeclGroup when it is implemented.
SourceLocation TypeSpecStartLoc;
/// \brief The template or declaration that this declaration
/// describes or was instantiated from, respectively.
///
/// For non-templates, this value will be NULL. For function
/// declarations that describe a function template, this will be a
/// pointer to a FunctionTemplateDecl. For member functions
/// of class template specializations, this will be the
/// FunctionDecl from which the member function was instantiated.
llvm::PointerUnion<FunctionTemplateDecl*, FunctionDecl*>
TemplateOrInstantiation;
protected:
FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T,
@ -534,7 +547,8 @@ protected:
ParamInfo(0), Body(), PreviousDeclaration(0),
SClass(S), IsInline(isInline), C99InlineDefinition(false),
IsVirtual(false), IsPure(false), InheritedPrototype(false),
HasPrototype(true), IsDeleted(false), TypeSpecStartLoc(TSSL) {}
HasPrototype(true), IsDeleted(false), TypeSpecStartLoc(TSSL),
TemplateOrInstantiation() {}
virtual ~FunctionDecl() {}
virtual void Destroy(ASTContext& C);
@ -711,6 +725,57 @@ public:
OverloadedOperatorKind getOverloadedOperator() const;
/// \brief If this function is an instantiation of a member function
/// of a class template specialization, retrieves the function from
/// which it was instantiated.
///
/// This routine will return non-NULL for (non-templated) member
/// functions of class templates and for instantiations of function
/// templates. For example, given:
///
/// \code
/// template<typename T>
/// struct X {
/// void f(T);
/// };
/// \endcode
///
/// The declaration for X<int>::f is a (non-templated) FunctionDecl
/// whose parent is the class template specialization X<int>. For
/// this declaration, getInstantiatedFromFunction() will return
/// the FunctionDecl X<T>::A. When a complete definition of
/// X<int>::A is required, it will be instantiated from the
/// declaration returned by getInstantiatedFromMemberFunction().
FunctionDecl *getInstantiatedFromMemberFunction() const {
return TemplateOrInstantiation.dyn_cast<FunctionDecl*>();
}
/// \brief Specify that this record is an instantiation of the
/// member function RD.
void setInstantiationOfMemberFunction(FunctionDecl *RD) {
TemplateOrInstantiation = RD;
}
/// \brief Retrieves the function template that is described by this
/// function declaration.
///
/// Every function template is represented as a FunctionTemplateDecl
/// and a FunctionDecl (or something derived from FunctionDecl). The
/// former contains template properties (such as the template
/// parameter lists) while the latter contains the actual
/// description of the template's
/// contents. FunctionTemplateDecl::getTemplatedDecl() retrieves the
/// FunctionDecl that describes the function template,
/// getDescribedFunctionTemplate() retrieves the
/// FunctionTemplateDecl from a FunctionDecl.
FunctionTemplateDecl *getDescribedFunctionTemplate() const {
return TemplateOrInstantiation.dyn_cast<FunctionTemplateDecl*>();
}
void setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
TemplateOrInstantiation = Template;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast;

Просмотреть файл

@ -236,15 +236,16 @@ class CXXRecordDecl : public RecordDecl {
/// CXXConversionDecl.
OverloadedFunctionDecl Conversions;
/// \brief The template or declaration that is declaration is
/// instantiated from.
/// \brief The template or declaration that this declaration
/// describes or was instantiated from, respectively.
///
/// For non-templates, this value will be NULL. For record
/// declarations that describe a class template, this will be a
/// pointer to a ClassTemplateDecl. For member
/// classes of class template specializations, this will be the
/// RecordDecl from which the member class was instantiated.
llvm::PointerUnion<ClassTemplateDecl*, CXXRecordDecl*>TemplateOrInstantiation;
llvm::PointerUnion<ClassTemplateDecl*, CXXRecordDecl*>
TemplateOrInstantiation;
protected:
CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,

Просмотреть файл

@ -155,6 +155,7 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->setHasPrototype(Record[Idx++]);
FD->setDeleted(Record[Idx++]);
FD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
// FIXME: C++ TemplateOrInstantiation
unsigned NumParams = Record[Idx++];
llvm::SmallVector<ParmVarDecl *, 16> Params;
Params.reserve(NumParams);

Просмотреть файл

@ -155,6 +155,7 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
Record.push_back(D->hasPrototype() && !D->inheritedPrototype());
Record.push_back(D->isDeleted());
Writer.AddSourceLocation(D->getTypeSpecStartLoc(), Record);
// FIXME: C++ TemplateOrInstantiation
Record.push_back(D->param_size());
for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
P != PEnd; ++P)

Просмотреть файл

@ -80,8 +80,8 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
bool Invalid = false;
QualType T = D->getUnderlyingType();
if (T->isDependentType()) {
T = SemaRef.InstantiateType(T, TemplateArgs, D->getLocation(),
D->getDeclName());
T = SemaRef.InstantiateType(T, TemplateArgs,
D->getLocation(), D->getDeclName());
if (T.isNull()) {
Invalid = true;
T = SemaRef.Context.IntTy;
@ -139,8 +139,8 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
bool Invalid = false;
QualType T = D->getType();
if (T->isDependentType()) {
T = SemaRef.InstantiateType(T, TemplateArgs, D->getLocation(),
D->getDeclName());
T = SemaRef.InstantiateType(T, TemplateArgs,
D->getLocation(), D->getDeclName());
if (!T.isNull() && T->isFunctionType()) {
// C++ [temp.arg.type]p3:
// If a declaration acquires a function type through a type
@ -290,6 +290,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
= CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(),
D->getDeclName(), T, D->isStatic(),
D->isInline());
Method->setInstantiationOfMemberFunction(D);
// Attach the parameters
for (unsigned P = 0; P < Params.size(); ++P)
@ -333,6 +334,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
= CXXConstructorDecl::Create(SemaRef.Context, Record, D->getLocation(),
Name, T, D->isExplicit(), D->isInline(),
false);
Constructor->setInstantiationOfMemberFunction(D);
// Attach the parameters
for (unsigned P = 0; P < Params.size(); ++P)
@ -375,6 +377,7 @@ Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
D->getLocation(),
SemaRef.Context.DeclarationNames.getCXXDestructorName(ClassTy),
T, D->isInline(), false);
Destructor->setInstantiationOfMemberFunction(D);
if (InitMethodInstantiation(Destructor, D))
Destructor->setInvalidDecl();
@ -404,6 +407,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
D->getLocation(),
SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(ConvTy),
T, D->isInline(), D->isExplicit());
Conversion->setInstantiationOfMemberFunction(D);
if (InitMethodInstantiation(Conversion, D))
Conversion->setInvalidDecl();
@ -513,7 +517,7 @@ TemplateDeclInstantiator::InstantiateFunctionType(FunctionDecl *D,
const FunctionProtoType *Proto = D->getType()->getAsFunctionProtoType();
assert(Proto && "Missing prototype?");
QualType ResultType
= SemaRef.InstantiateType(Proto->getResultType(), TemplateArgs,
= SemaRef.InstantiateType(Proto->getResultType(), TemplateArgs,
D->getLocation(), D->getDeclName());
if (ResultType.isNull())
return QualType();
@ -557,7 +561,19 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
/// \param Function the already-instantiated declaration of a
/// function.
void Sema::InstantiateFunctionDefinition(FunctionDecl *Function) {
// FIXME: Implement this!
// FIXME: make this work for function template specializations, too.
// Find the function body that we'll be substituting.
const FunctionDecl *PatternDecl
= Function->getInstantiatedFromMemberFunction();
Stmt *Pattern = 0;
if (PatternDecl)
Pattern = PatternDecl->getBody(Context, PatternDecl);
if (!Pattern)
return;
// FIXME: instantiate the pattern
}
/// \brief Instantiate the definition of the given variable from its

Просмотреть файл

@ -120,3 +120,16 @@ namespace N7 {
typedef Cond<true, int, double>::Type Type;
}
#if 0
// FIXME: Unable to handle general declaration references at this point.
template<typename T, unsigned long N> struct IntegralConstant { };
template<typename T>
struct X0 {
void f(T x, IntegralConstant<T, sizeof(x)>);
};
void test_X0(X0<int> x, IntegralConstant<int, sizeof(int)> ic) {
x.f(ic);
}
#endif