mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 03:56:16 +08:00
patch to mark use of implicit copy constructors.
llvm-svn: 73922
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user