]> granicus.if.org Git - clang/commitdiff
Link FunctionDecls instantiated from the member functions of a class
authorDouglas Gregor <dgregor@apple.com>
Thu, 14 May 2009 21:06:31 +0000 (21:06 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 14 May 2009 21:06:31 +0000 (21:06 +0000)
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

include/clang/AST/Decl.h
include/clang/AST/DeclCXX.h
lib/Frontend/PCHReaderDecl.cpp
lib/Frontend/PCHWriterDecl.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/instantiate-expr-2.cpp

index 79d04b338e04d8c26d1694cfe7c91446be862587..b2f18a73c5d225bb8f98d5cf5a0a93e6a1cd62f1 100644 (file)
@@ -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;
index f8e92bd40793078e0abf0b253c0f2f96d474bad0..d7f268fc6a0526efe91400d8755145388a842df4 100644 (file)
@@ -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,
index 3db00ec1b71f86dbd67abdcdc7e7e3e9ac0667fa..9dd156589033951b4f4e4b4c2c6163aac8fcd48c 100644 (file)
@@ -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);
index 799c77b03fc18fba083c49c8407470c3d525e97e..96045f94c53592078e7add568455f7a2da183d6a 100644 (file)
@@ -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)
index 92d253d3ba72222669a51725fe938a7557539af9..6ae6b2240b25afb04b3322217bcbddb9a7b04fba 100644 (file)
@@ -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
index aa898dd05652bc8d86da2faedb65ffbc9545a788..ea1e0af21a6d1c6f2d20d0ce032a39a0df38f035 100644 (file)
@@ -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