namespace clang {
class Expr;
+class FunctionTemplateDecl;
class Stmt;
class CompoundStmt;
class StringLiteral;
// 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,
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);
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;
/// 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,
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);
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)
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;
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
= 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)
= 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)
D->getLocation(),
SemaRef.Context.DeclarationNames.getCXXDestructorName(ClassTy),
T, D->isInline(), false);
+ Destructor->setInstantiationOfMemberFunction(D);
if (InitMethodInstantiation(Destructor, D))
Destructor->setInvalidDecl();
D->getLocation(),
SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(ConvTy),
T, D->isInline(), D->isExplicit());
+ Conversion->setInstantiationOfMemberFunction(D);
if (InitMethodInstantiation(Conversion, D))
Conversion->setInvalidDecl();
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();
/// \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
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