forked from OSchip/llvm-project
Move declaration of a class's implicit copy constructor into a
separate function. Aside from making the loops infinitely faster, no functionality change. llvm-svn: 107407
This commit is contained in:
parent
68e1136585
commit
54be33925a
|
@ -2230,6 +2230,18 @@ public:
|
|||
void DefineImplicitDestructor(SourceLocation CurrentLocation,
|
||||
CXXDestructorDecl *Destructor);
|
||||
|
||||
/// \brief Declare the implicit copy constructor for the given class.
|
||||
///
|
||||
/// \param S The scope of the class, which may be NULL if this is a
|
||||
/// template instantiation.
|
||||
///
|
||||
/// \param ClassDecl The class declaration into which the implicit
|
||||
/// copy constructor will be added.
|
||||
///
|
||||
/// \returns The implicitly-declared copy constructor.
|
||||
CXXConstructorDecl *DeclareImplicitCopyConstructor(Scope *S,
|
||||
CXXRecordDecl *ClassDecl);
|
||||
|
||||
/// DefineImplicitCopyConstructor - Checks for feasibility of
|
||||
/// defining this constructor as the copy constructor.
|
||||
void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
|
||||
|
|
|
@ -2692,92 +2692,8 @@ void Sema::AddImplicitlyDeclaredMembersToClass(Scope *S,
|
|||
ClassDecl->addDecl(DefaultCon);
|
||||
}
|
||||
|
||||
if (!ClassDecl->hasUserDeclaredCopyConstructor()) {
|
||||
// C++ [class.copy]p4:
|
||||
// If the class definition does not explicitly declare a copy
|
||||
// constructor, one is declared implicitly.
|
||||
|
||||
// C++ [class.copy]p5:
|
||||
// The implicitly-declared copy constructor for a class X will
|
||||
// have the form
|
||||
//
|
||||
// X::X(const X&)
|
||||
//
|
||||
// if
|
||||
bool HasConstCopyConstructor = true;
|
||||
|
||||
// -- each direct or virtual base class B of X has a copy
|
||||
// constructor whose first parameter is of type const B& or
|
||||
// const volatile B&, and
|
||||
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
|
||||
HasConstCopyConstructor && Base != ClassDecl->bases_end(); ++Base) {
|
||||
const CXXRecordDecl *BaseClassDecl
|
||||
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
||||
HasConstCopyConstructor
|
||||
= BaseClassDecl->hasConstCopyConstructor(Context);
|
||||
}
|
||||
|
||||
// -- for all the nonstatic data members of X that are of a
|
||||
// class type M (or array thereof), each such class type
|
||||
// has a copy constructor whose first parameter is of type
|
||||
// const M& or const volatile M&.
|
||||
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin();
|
||||
HasConstCopyConstructor && Field != ClassDecl->field_end();
|
||||
++Field) {
|
||||
QualType FieldType = (*Field)->getType();
|
||||
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
|
||||
FieldType = Array->getElementType();
|
||||
if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
|
||||
const CXXRecordDecl *FieldClassDecl
|
||||
= cast<CXXRecordDecl>(FieldClassType->getDecl());
|
||||
HasConstCopyConstructor
|
||||
= FieldClassDecl->hasConstCopyConstructor(Context);
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, the implicitly declared copy constructor will have
|
||||
// the form
|
||||
//
|
||||
// X::X(X&)
|
||||
QualType ArgType = ClassType;
|
||||
if (HasConstCopyConstructor)
|
||||
ArgType = ArgType.withConst();
|
||||
ArgType = Context.getLValueReferenceType(ArgType);
|
||||
|
||||
// An implicitly-declared copy constructor is an inline public
|
||||
// member of its class.
|
||||
DeclarationName Name
|
||||
= Context.DeclarationNames.getCXXConstructorName(ClassType);
|
||||
CXXConstructorDecl *CopyConstructor
|
||||
= CXXConstructorDecl::Create(Context, ClassDecl,
|
||||
ClassDecl->getLocation(), Name,
|
||||
Context.getFunctionType(Context.VoidTy,
|
||||
&ArgType, 1,
|
||||
false, 0,
|
||||
/*FIXME: hasExceptionSpec*/false,
|
||||
false, 0, 0,
|
||||
FunctionType::ExtInfo()),
|
||||
/*TInfo=*/0,
|
||||
/*isExplicit=*/false,
|
||||
/*isInline=*/true,
|
||||
/*isImplicitlyDeclared=*/true);
|
||||
CopyConstructor->setAccess(AS_public);
|
||||
CopyConstructor->setImplicit();
|
||||
CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
|
||||
|
||||
// Add the parameter to the constructor.
|
||||
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
|
||||
ClassDecl->getLocation(),
|
||||
/*IdentifierInfo=*/0,
|
||||
ArgType, /*TInfo=*/0,
|
||||
VarDecl::None,
|
||||
VarDecl::None, 0);
|
||||
CopyConstructor->setParams(&FromParam, 1);
|
||||
if (S)
|
||||
PushOnScopeChains(CopyConstructor, S, true);
|
||||
else
|
||||
ClassDecl->addDecl(CopyConstructor);
|
||||
}
|
||||
if (!ClassDecl->hasUserDeclaredCopyConstructor())
|
||||
DeclareImplicitCopyConstructor(S, ClassDecl);
|
||||
|
||||
if (!ClassDecl->hasUserDeclaredCopyAssignment())
|
||||
DeclareImplicitCopyAssignment(S, ClassDecl);
|
||||
|
@ -4993,6 +4909,103 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
|
|||
CopyAssignOperator->setBody(Body.takeAs<Stmt>());
|
||||
}
|
||||
|
||||
CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(Scope *S,
|
||||
CXXRecordDecl *ClassDecl) {
|
||||
// C++ [class.copy]p4:
|
||||
// If the class definition does not explicitly declare a copy
|
||||
// constructor, one is declared implicitly.
|
||||
|
||||
// FIXME: virtual bases!
|
||||
|
||||
// C++ [class.copy]p5:
|
||||
// The implicitly-declared copy constructor for a class X will
|
||||
// have the form
|
||||
//
|
||||
// X::X(const X&)
|
||||
//
|
||||
// if
|
||||
bool HasConstCopyConstructor = true;
|
||||
|
||||
// -- each direct or virtual base class B of X has a copy
|
||||
// constructor whose first parameter is of type const B& or
|
||||
// const volatile B&, and
|
||||
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
|
||||
BaseEnd = ClassDecl->bases_end();
|
||||
HasConstCopyConstructor && Base != BaseEnd;
|
||||
++Base) {
|
||||
const CXXRecordDecl *BaseClassDecl
|
||||
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
||||
HasConstCopyConstructor
|
||||
= BaseClassDecl->hasConstCopyConstructor(Context);
|
||||
}
|
||||
|
||||
// -- for all the nonstatic data members of X that are of a
|
||||
// class type M (or array thereof), each such class type
|
||||
// has a copy constructor whose first parameter is of type
|
||||
// const M& or const volatile M&.
|
||||
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
|
||||
FieldEnd = ClassDecl->field_end();
|
||||
HasConstCopyConstructor && Field != FieldEnd;
|
||||
++Field) {
|
||||
QualType FieldType = (*Field)->getType();
|
||||
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
|
||||
FieldType = Array->getElementType();
|
||||
if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
|
||||
const CXXRecordDecl *FieldClassDecl
|
||||
= cast<CXXRecordDecl>(FieldClassType->getDecl());
|
||||
HasConstCopyConstructor
|
||||
= FieldClassDecl->hasConstCopyConstructor(Context);
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, the implicitly declared copy constructor will have
|
||||
// the form
|
||||
//
|
||||
// X::X(X&)
|
||||
QualType ClassType = Context.getTypeDeclType(ClassDecl);
|
||||
QualType ArgType = ClassType;
|
||||
if (HasConstCopyConstructor)
|
||||
ArgType = ArgType.withConst();
|
||||
ArgType = Context.getLValueReferenceType(ArgType);
|
||||
|
||||
// An implicitly-declared copy constructor is an inline public
|
||||
// member of its class.
|
||||
DeclarationName Name
|
||||
= Context.DeclarationNames.getCXXConstructorName(
|
||||
Context.getCanonicalType(ClassType));
|
||||
CXXConstructorDecl *CopyConstructor
|
||||
= CXXConstructorDecl::Create(Context, ClassDecl,
|
||||
ClassDecl->getLocation(), Name,
|
||||
Context.getFunctionType(Context.VoidTy,
|
||||
&ArgType, 1,
|
||||
false, 0,
|
||||
/*FIXME: hasExceptionSpec*/false,
|
||||
false, 0, 0,
|
||||
FunctionType::ExtInfo()),
|
||||
/*TInfo=*/0,
|
||||
/*isExplicit=*/false,
|
||||
/*isInline=*/true,
|
||||
/*isImplicitlyDeclared=*/true);
|
||||
CopyConstructor->setAccess(AS_public);
|
||||
CopyConstructor->setImplicit();
|
||||
CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
|
||||
|
||||
// Add the parameter to the constructor.
|
||||
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
|
||||
ClassDecl->getLocation(),
|
||||
/*IdentifierInfo=*/0,
|
||||
ArgType, /*TInfo=*/0,
|
||||
VarDecl::None,
|
||||
VarDecl::None, 0);
|
||||
CopyConstructor->setParams(&FromParam, 1);
|
||||
if (S)
|
||||
PushOnScopeChains(CopyConstructor, S, true);
|
||||
else
|
||||
ClassDecl->addDecl(CopyConstructor);
|
||||
|
||||
return CopyConstructor;
|
||||
}
|
||||
|
||||
void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
|
||||
CXXConstructorDecl *CopyConstructor,
|
||||
unsigned TypeQuals) {
|
||||
|
|
Loading…
Reference in New Issue