[cfe-commits] r67585 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/instantiate-method.cpp

Douglas Gregor dgregor at apple.com
Mon Mar 23 17:38:23 PDT 2009


Author: dgregor
Date: Mon Mar 23 19:38:23 2009
New Revision: 67585

URL: http://llvm.org/viewvc/llvm-project?rev=67585&view=rev
Log:
Cleanup template instantiation for methods, destructors

Modified:
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaTemplate/instantiate-method.cpp

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Mar 23 19:38:23 2009
@@ -47,10 +47,16 @@
     Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
     Decl *VisitParmVarDecl(ParmVarDecl *D);
     Decl *VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
+
     // Base case. FIXME: Remove once we can instantiate everything.
     Decl *VisitDecl(Decl *) { 
       return 0;
     }
+
+    // Helper functions for instantiating methods.
+    QualType InstantiateFunctionType(FunctionDecl *D,
+                             llvm::SmallVectorImpl<ParmVarDecl *> &Params);
+    bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
   };
 }
 
@@ -201,9 +207,8 @@
   if (D->getKind() != Decl::CXXMethod)
     return 0;
 
-  QualType T = SemaRef.InstantiateType(D->getType(), TemplateArgs,
-                                       NumTemplateArgs, D->getLocation(),
-                                       D->getDeclName());
+  llvm::SmallVector<ParmVarDecl *, 16> Params;
+  QualType T = InstantiateFunctionType(D, Params);
   if (T.isNull())
     return 0;
 
@@ -213,37 +218,14 @@
     = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(), 
                             D->getDeclName(), T, D->isStatic(), 
                             D->isInline());
-  Method->setAccess(D->getAccess());
-  // FIXME: Duplicates some logic in ActOnFunctionDeclarator.
-  if (D->isVirtual()) {
-    Method->setVirtual();
-    Record->setAggregate(false);
-    Record->setPOD(false);
-    Record->setPolymorphic(true);
-  }
-  if (D->isDeleted())
-    Method->setDeleted();
-  if (D->isPure()) {
-    Method->setPure();
-    Record->setAbstract(true);
-  }
-  // FIXME: attributes
-  // FIXME: Method needs a pointer referencing where it came from.
 
-  // Instantiate the function parameters
-  {
-    TemplateDeclInstantiator ParamInstantiator(SemaRef, Method,
-                                               TemplateArgs, NumTemplateArgs);
-    llvm::SmallVector<ParmVarDecl *, 16> Params;
-    for (FunctionDecl::param_iterator P = Method->param_begin(), 
-                                   PEnd = Method->param_end();
-         P != PEnd; ++P) {
-      if (ParmVarDecl *PInst = (ParmVarDecl *)ParamInstantiator.Visit(*P))
-        Params.push_back(PInst);
-      else 
-        Method->setInvalidDecl();
-    }
-  }
+  // Attach the parameters
+  for (unsigned P = 0; P < Params.size(); ++P)
+    Params[P]->setOwningFunction(Method);
+  Method->setParams(SemaRef.Context, &Params[0], Params.size());
+
+  if (InitMethodInstantiation(Method, D))
+    Method->setInvalidDecl();
 
   NamedDecl *PrevDecl 
     = SemaRef.LookupQualifiedName(Owner, Method->getDeclName(), 
@@ -266,12 +248,12 @@
 }
 
 Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
-  QualType T = SemaRef.InstantiateType(D->getType(), TemplateArgs,
-                                       NumTemplateArgs, D->getLocation(),
-                                       D->getDeclName());
+  llvm::SmallVector<ParmVarDecl *, 16> Params;
+  QualType T = InstantiateFunctionType(D, Params);
   if (T.isNull())
     return 0;
-  
+  assert(Params.size() == 0 && "Destructor with parameters?");
+
   // Build the instantiated destructor declaration.
   CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
   QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
@@ -280,22 +262,8 @@
                                 D->getLocation(),
              SemaRef.Context.DeclarationNames.getCXXDestructorName(ClassTy),
                                 T, D->isInline(), false);
-
-  Destructor->setAccess(D->getAccess());
-  // FIXME: Duplicates some logic in ActOnFunctionDeclarator,
-  // VisitCXXDestructorDecl.
-  if (D->isVirtual()) {
-    Destructor->setVirtual();
-    Record->setAggregate(false);
-    Record->setPOD(false);
-    Record->setPolymorphic(true);
-  }
-  if (D->isDeleted())
-    Destructor->setDeleted();
-  if (D->isPure()) {
-    Destructor->setPure();
-    Record->setAbstract(true);
-  }
+  if (InitMethodInstantiation(Destructor, D))
+    Destructor->setInvalidDecl();
 
   bool Redeclaration = false;
   bool OverloadableAttrRequired = false;
@@ -360,3 +328,89 @@
   return Instantiator.Visit(D);
 }
 
+/// \brief Instantiates the type of the given function, including
+/// instantiating all of the function parameters.
+///
+/// \param D The function that we will be instantiated
+///
+/// \param Params the instantiated parameter declarations
+
+/// \returns the instantiated function's type if successfull, a NULL
+/// type if there was an error.
+QualType 
+TemplateDeclInstantiator::InstantiateFunctionType(FunctionDecl *D,
+                              llvm::SmallVectorImpl<ParmVarDecl *> &Params) {
+  bool InvalidDecl = false;
+
+  // Instantiate the function parameters
+  TemplateDeclInstantiator ParamInstantiator(SemaRef, 0,
+                                             TemplateArgs, NumTemplateArgs);
+  llvm::SmallVector<QualType, 16> ParamTys;
+  for (FunctionDecl::param_iterator P = D->param_begin(), 
+                                 PEnd = D->param_end();
+       P != PEnd; ++P) {
+    if (ParmVarDecl *PInst = (ParmVarDecl *)ParamInstantiator.Visit(*P)) {
+      if (PInst->getType()->isVoidType()) {
+        SemaRef.Diag(PInst->getLocation(), diag::err_param_with_void_type);
+        PInst->setInvalidDecl();
+      }
+      else if (SemaRef.RequireNonAbstractType(PInst->getLocation(), 
+                                              PInst->getType(),
+                                              diag::err_abstract_type_in_decl,
+                                              1 /* parameter type */))
+        PInst->setInvalidDecl();
+
+      Params.push_back(PInst);
+      ParamTys.push_back(PInst->getType());
+
+      if (PInst->isInvalidDecl())
+        InvalidDecl = true;
+    } else 
+      InvalidDecl = true;
+  }
+
+  // FIXME: Deallocate dead declarations.
+  if (InvalidDecl)
+    return QualType();
+
+  const FunctionProtoType *Proto = D->getType()->getAsFunctionProtoType();
+  assert(Proto && "Missing prototype?");
+  QualType ResultType 
+    = SemaRef.InstantiateType(Proto->getResultType(),
+                              TemplateArgs, NumTemplateArgs,
+                              D->getLocation(), D->getDeclName());
+  if (ResultType.isNull())
+    return QualType();
+
+  return SemaRef.BuildFunctionType(ResultType, &ParamTys[0], ParamTys.size(),
+                                   Proto->isVariadic(), Proto->getTypeQuals(),
+                                   D->getLocation(), D->getDeclName());
+}
+
+/// \brief Initializes common fields of an instantiated method
+/// declaration (New) from the corresponding fields of its template
+/// (Tmpl).
+///
+/// \returns true if there was an error
+bool 
+TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, 
+                                                  CXXMethodDecl *Tmpl) {
+  CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
+  New->setAccess(Tmpl->getAccess());
+  if (Tmpl->isVirtual()) {
+    New->setVirtual();
+    Record->setAggregate(false);
+    Record->setPOD(false);
+    Record->setPolymorphic(true);
+  }
+  if (Tmpl->isDeleted())
+    New->setDeleted();
+  if (Tmpl->isPure()) {
+    New->setPure();
+    Record->setAbstract(true);
+  }
+
+  // FIXME: attributes
+  // FIXME: New needs a pointer to Tmpl
+  return false;
+}

Modified: cfe/trunk/test/SemaTemplate/instantiate-method.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-method.cpp?rev=67585&r1=67584&r2=67585&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-method.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-method.cpp Mon Mar 23 19:38:23 2009
@@ -2,9 +2,7 @@
 template<typename T>
 class X {
 public:
-  void f(T); // expected-error{{argument may not have 'void' type}}
-             // FIXME: source location isn't very good, because we're
-             // instantiating the type. Could we do better?
+  void f(T x); // expected-error{{argument may not have 'void' type}}
   void g(T*);
 
   static int h(T, T); // expected-error 2{{argument may not have 'void' type}}





More information about the cfe-commits mailing list