[cfe-commits] r71792 - in /cfe/trunk: 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

Douglas Gregor dgregor at apple.com
Thu May 14 14:06:32 PDT 2009


Author: dgregor
Date: Thu May 14 16:06:31 2009
New Revision: 71792

URL: http://llvm.org/viewvc/llvm-project?rev=71792&view=rev
Log:
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.

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

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=71792&r1=71791&r2=71792&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu May 14 16:06:31 2009
@@ -20,6 +20,7 @@
 
 namespace clang {
 class Expr;
+class FunctionTemplateDecl;
 class Stmt;
 class CompoundStmt;
 class StringLiteral;
@@ -524,6 +525,18 @@
 
   // 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 @@
       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 @@
 
   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;

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=71792&r1=71791&r2=71792&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu May 14 16:06:31 2009
@@ -236,15 +236,16 @@
   /// 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,

Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=71792&r1=71791&r2=71792&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Thu May 14 16:06:31 2009
@@ -155,6 +155,7 @@
   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);

Modified: cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterDecl.cpp?rev=71792&r1=71791&r2=71792&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Thu May 14 16:06:31 2009
@@ -155,6 +155,7 @@
   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)

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=71792&r1=71791&r2=71792&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu May 14 16:06:31 2009
@@ -80,8 +80,8 @@
   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 @@
   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 @@
     = 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 @@
     = 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 @@
                                 D->getLocation(),
              SemaRef.Context.DeclarationNames.getCXXDestructorName(ClassTy),
                                 T, D->isInline(), false);
+  Destructor->setInstantiationOfMemberFunction(D);
   if (InitMethodInstantiation(Destructor, D))
     Destructor->setInvalidDecl();
 
@@ -404,6 +407,7 @@
                                 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 @@
   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 @@
 /// \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

Modified: cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp?rev=71792&r1=71791&r2=71792&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-expr-2.cpp Thu May 14 16:06:31 2009
@@ -120,3 +120,16 @@
   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





More information about the cfe-commits mailing list