diff options
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/Sema.h | 8 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 48 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 6 |
3 files changed, 58 insertions, 4 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index e5502a59378..8604fe56a27 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 962807450c5..c9c662671c1 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 81765a57d60..56d3bfe690b 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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<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); |

