From 54be33925ab9ff0d3428f462789b2c80c9f826ef Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 1 Jul 2010 17:57:27 +0000 Subject: [PATCH] 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 --- clang/lib/Sema/Sema.h | 12 +++ clang/lib/Sema/SemaDeclCXX.cpp | 185 ++++++++++++++++++--------------- 2 files changed, 111 insertions(+), 86 deletions(-) diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 2e52bfcb945d..1c9e77143fd2 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -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, diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 9d18e177fd5f..4b7015caec57 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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(Base->getType()->getAs()->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()) { - const CXXRecordDecl *FieldClassDecl - = cast(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()); } +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(Base->getType()->getAs()->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()) { + const CXXRecordDecl *FieldClassDecl + = cast(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) {