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/lib/Sema/Sema.h b/lib/Sema/Sema.h
index e5502a5..8604fe5 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1582,10 +1582,16 @@
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 9628074..c9c6626 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1878,7 +1878,7 @@
CXXRecordDecl *ClassDecl
= cast<CXXRecordDecl>(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 @@
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 @@
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 @@
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<CXXRecordDecl>(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<CXXRecordDecl>(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<CXXRecordDecl>(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 81765a5..56d3bfe 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -5515,10 +5515,16 @@
// Note that this declaration has been used.
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(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);