Template instantiation for constructors

llvm-svn: 67623
This commit is contained in:
Douglas Gregor 2009-03-24 16:43:20 +00:00
parent 9fc30d5c30
commit 4044d995c9
3 changed files with 68 additions and 0 deletions

View File

@ -1654,6 +1654,8 @@ void Sema::AddCXXDirectInitializerToDecl(DeclTy *Dcl, SourceLocation LParenLoc,
return;
}
// FIXME: Need to handle dependent types and expressions here.
// We will treat direct-initialization as a copy-initialization:
// int x(1); -as-> int x = 1;
// ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c);
@ -1672,6 +1674,13 @@ void Sema::AddCXXDirectInitializerToDecl(DeclTy *Dcl, SourceLocation LParenLoc,
if (const ArrayType *Array = Context.getAsArrayType(DeclInitType))
DeclInitType = Array->getElementType();
// FIXME: This isn't the right place to complete the type.
if (RequireCompleteType(VDecl->getLocation(), VDecl->getType(),
diag::err_typecheck_decl_incomplete_type)) {
VDecl->setInvalidDecl();
return;
}
if (VDecl->getType()->isRecordType()) {
CXXConstructorDecl *Constructor
= PerformInitializationByConstructor(DeclInitType,

View File

@ -44,6 +44,7 @@ namespace {
Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
Decl *VisitEnumDecl(EnumDecl *D);
Decl *VisitCXXMethodDecl(CXXMethodDecl *D);
Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
Decl *VisitParmVarDecl(ParmVarDecl *D);
Decl *VisitOriginalParmVarDecl(OriginalParmVarDecl *D);
@ -247,6 +248,50 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
return Method;
}
Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
llvm::SmallVector<ParmVarDecl *, 16> Params;
QualType T = InstantiateFunctionType(D, Params);
if (T.isNull())
return 0;
// Build the instantiated method declaration.
CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
DeclarationName Name
= SemaRef.Context.DeclarationNames.getCXXConstructorName(ClassTy);
CXXConstructorDecl *Constructor
= CXXConstructorDecl::Create(SemaRef.Context, Record, D->getLocation(),
Name, T, D->isExplicit(), D->isInline(),
false);
// Attach the parameters
for (unsigned P = 0; P < Params.size(); ++P)
Params[P]->setOwningFunction(Constructor);
Constructor->setParams(SemaRef.Context, &Params[0], Params.size());
if (InitMethodInstantiation(Constructor, D))
Constructor->setInvalidDecl();
NamedDecl *PrevDecl
= SemaRef.LookupQualifiedName(Owner, Name, Sema::LookupOrdinaryName, true);
// In C++, the previous declaration we find might be a tag type
// (class or enum). In this case, the new declaration will hide the
// tag type. Note that this does does not apply if we're declaring a
// typedef (C++ [dcl.typedef]p4).
if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
PrevDecl = 0;
bool Redeclaration = false;
bool OverloadableAttrRequired = false;
if (SemaRef.CheckFunctionDeclaration(Constructor, PrevDecl, Redeclaration,
/*FIXME:*/OverloadableAttrRequired))
Constructor->setInvalidDecl();
if (!Constructor->isInvalidDecl())
Owner->addDecl(Constructor);
return Constructor;
}
Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
llvm::SmallVector<ParmVarDecl *, 16> Params;
QualType T = InstantiateFunctionType(D, Params);

View File

@ -41,9 +41,23 @@ void test_ovl_bad() {
template<typename T>
class HasDestructor {
public:
virtual ~HasDestructor() = 0;
};
int i = sizeof(HasDestructor<int>); // FIXME: forces instantiation, but
// the code below should probably instantiate by itself.
int abstract_destructor[__is_abstract(HasDestructor<int>)? 1 : -1];
template<typename T>
class Constructors {
public:
Constructors(const T&);
Constructors(const Constructors &other);
};
void test_constructors() {
Constructors<int> ci1(17);
Constructors<int> ci2 = ci1;
}