summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-03-24 00:38:23 +0000
committerDouglas Gregor <dgregor@apple.com>2009-03-24 00:38:23 +0000
commit5545e166a956a20d7a6b58408e251a1119025485 (patch)
treeb583de7622c70cb496e0b5ac819e4ec343f20452
parentc63c885734fa60a091e9f96a77e2f6b1489ae9fc (diff)
downloadclang-5545e166a956a20d7a6b58408e251a1119025485.tar.gz
Cleanup template instantiation for methods, destructors
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67585 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp160
-rw-r--r--test/SemaTemplate/instantiate-method.cpp4
2 files changed, 108 insertions, 56 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index d924713349..b7a8f7a515 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -47,10 +47,16 @@ namespace {
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 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
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 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
= 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::VisitCXXMethodDecl(CXXMethodDecl *D) {
}
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 @@ Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
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 @@ Decl *Sema::InstantiateDecl(Decl *D, DeclContext *Owner,
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;
+}
diff --git a/test/SemaTemplate/instantiate-method.cpp b/test/SemaTemplate/instantiate-method.cpp
index a6a6235465..3497cbec02 100644
--- a/test/SemaTemplate/instantiate-method.cpp
+++ b/test/SemaTemplate/instantiate-method.cpp
@@ -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}}