зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
67a1eadcf7
Коммит
1eee0e753f
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче