From: Fariborz Jahanian Date: Mon, 22 Jun 2009 23:34:40 +0000 (+0000) Subject: patch to mark use of implicit copy constructors. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=485f087407849a8989053122f52b8c07d1191b45;p=clang patch to mark use of implicit copy constructors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73922 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 2db0ca2274..52ed0ec853 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -283,6 +283,10 @@ public: /// copy constructor that accepts a const-qualified argument. bool hasConstCopyConstructor(ASTContext &Context) const; + /// getCopyConstructor - Returns the copy constructor for this class + CXXConstructorDecl *getCopyConstructor(ASTContext &Context, + unsigned TypeQuals) const; + /// hasConstCopyAssignment - Determines whether this class has a /// copy assignment operator that accepts a const-qualified argument. bool hasConstCopyAssignment(ASTContext &Context) const; diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 7a930d78c1..25e4d19617 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -66,21 +66,29 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, } bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const { + return getCopyConstructor(Context, QualType::Const) != 0; +} + +CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context, + unsigned TypeQuals) const{ QualType ClassType = Context.getTypeDeclType(const_cast(this)); DeclarationName ConstructorName = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(ClassType)); - unsigned TypeQuals; + Context.getCanonicalType(ClassType)); + unsigned FoundTQs; DeclContext::lookup_const_iterator Con, ConEnd; for (llvm::tie(Con, ConEnd) = this->lookup(Context, ConstructorName); Con != ConEnd; ++Con) { - if (cast(*Con)->isCopyConstructor(Context, TypeQuals) && - (TypeQuals & QualType::Const) != 0) - return true; + if (cast(*Con)->isCopyConstructor(Context, + FoundTQs)) { + if (((TypeQuals & QualType::Const) == (FoundTQs & QualType::Const)) || + (!(TypeQuals & QualType::Const) && (FoundTQs & QualType::Const))) + return cast(*Con); + + } } - - return false; + return 0; } bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const { diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index e5502a5937..8604fe56a2 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1582,10 +1582,16 @@ public: QualType DeclInitType, Expr **Exprs, unsigned NumExprs); - /// DefineImplicitDefaultConstructor - Checks for feasibilityt of + /// DefineImplicitDefaultConstructor - Checks for feasibility of /// defining this constructor as the default constructor. void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *Constructor); + + /// DefineImplicitCopyConstructor - Checks for feasibility of + /// defining this constructor as the copy constructor. + void DefineImplicitCopyConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor, + unsigned TypeQuals); /// MaybeBindToTemporary - If the passed in expression has a record type with /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 962807450c..c9c662671c 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1878,7 +1878,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = cast(Constructor->getDeclContext()); - assert(ClassDecl && "InitializeVarWithConstructor - invalid constructor"); + assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); // Before the implicitly-declared default constructor for a class is // implicitly defined, all the implicitly-declared default constructors // for its base class and its non-static data members shall have been @@ -1891,7 +1891,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, if (!BaseClassDecl->hasTrivialConstructor()) { if (CXXConstructorDecl *BaseCtor = BaseClassDecl->getDefaultConstructor(Context)) { - if (BaseCtor->isImplicit()) + if (BaseCtor->isImplicit() && !BaseCtor->isUsed()) MarkDeclarationReferenced(CurrentLocation, BaseCtor); } else { @@ -1916,7 +1916,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, if (!FieldClassDecl->hasTrivialConstructor()) if (CXXConstructorDecl *FieldCtor = FieldClassDecl->getDefaultConstructor(Context)) { - if (FieldCtor->isImplicit()) + if (FieldCtor->isImplicit() && !FieldCtor->isUsed()) MarkDeclarationReferenced(CurrentLocation, FieldCtor); } else { @@ -1945,6 +1945,48 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, Constructor->setUsed(); } +void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *CopyConstructor, + unsigned TypeQuals) { + assert((CopyConstructor->isImplicit() && + CopyConstructor->isCopyConstructor(Context, TypeQuals) && + !CopyConstructor->isUsed()) && + "DefineImplicitCopyConstructor - call it for implicit copy ctor"); + + CXXRecordDecl *ClassDecl + = cast(CopyConstructor->getDeclContext()); + assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor"); + // Before the implicitly-declared copy constructor for a class is + // implicitly defined, all the implicitly-declared copy constructors + // for its base class and its non-static data members shall have been + // implicitly defined. + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + CXXRecordDecl *BaseClassDecl + = cast(Base->getType()->getAsRecordType()->getDecl()); + if (CXXConstructorDecl *BaseCopyCtor = + BaseClassDecl->getCopyConstructor(Context, TypeQuals)) + if (BaseCopyCtor->isImplicit() && !BaseCopyCtor->isUsed()) + MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor); + } + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context); + Field != ClassDecl->field_end(Context); + ++Field) { + QualType FieldType = Context.getCanonicalType((*Field)->getType()); + if (const ArrayType *Array = Context.getAsArrayType(FieldType)) + FieldType = Array->getElementType(); + if (const RecordType *FieldClassType = FieldType->getAsRecordType()) { + CXXRecordDecl *FieldClassDecl + = cast(FieldClassType->getDecl()); + if (CXXConstructorDecl *FieldCopyCtor = + FieldClassDecl->getCopyConstructor(Context, TypeQuals)) + if (FieldCopyCtor->isImplicit() && !FieldCopyCtor->isUsed()) + MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor); + } + } + CopyConstructor->setUsed(); +} + void Sema::InitializeVarWithConstructor(VarDecl *VD, CXXConstructorDecl *Constructor, QualType DeclInitType, diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 81765a57d6..56d3bfe690 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5515,10 +5515,16 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { // Note that this declaration has been used. if (CXXConstructorDecl *Constructor = dyn_cast(D)) { + unsigned TypeQuals; if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) { if (!Constructor->isUsed()) DefineImplicitDefaultConstructor(Loc, Constructor); } + else if (Constructor->isImplicit() && + Constructor->isCopyConstructor(Context, TypeQuals)) { + if (!Constructor->isUsed()) + DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals); + } // FIXME: more checking for other implicits go here. else Constructor->setUsed(true);