patch to mark use of implicit copy constructors.

llvm-svn: 73922
This commit is contained in:
Fariborz Jahanian
2009-06-22 23:34:40 +00:00
parent 214cdfea84
commit 477d242a2e
5 changed files with 77 additions and 11 deletions

View File

@@ -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;

View File

@@ -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<CXXRecordDecl*>(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<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
(TypeQuals & QualType::Const) != 0)
return true;
if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context,
FoundTQs)) {
if (((TypeQuals & QualType::Const) == (FoundTQs & QualType::Const)) ||
(!(TypeQuals & QualType::Const) && (FoundTQs & QualType::Const)))
return cast<CXXConstructorDecl>(*Con);
}
}
return false;
return 0;
}
bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {

View File

@@ -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

View File

@@ -1878,7 +1878,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
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 @@ 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<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,

View File

@@ -5515,10 +5515,16 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
// 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);