diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclCXX.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 79 |
4 files changed, 108 insertions, 4 deletions
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index f299ed1023..2fa5ed7919 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -184,10 +184,28 @@ void CXXRecordDecl::addConversionFunction(ASTContext &Context, Conversions.addOverload(ConvDecl); } + +CXXConstructorDecl * +CXXRecordDecl::getDefaultConstructor(ASTContext &Context) { + QualType ClassType = Context.getTypeDeclType(this); + DeclarationName ConstructorName + = Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(ClassType.getUnqualifiedType())); + + DeclContext::lookup_const_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = lookup(Context, ConstructorName); + Con != ConEnd; ++Con) { + CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); + if (Constructor->isDefaultConstructor()) + return Constructor; + } + return 0; +} + const CXXDestructorDecl * CXXRecordDecl::getDestructor(ASTContext &Context) { QualType ClassType = Context.getTypeDeclType(this); - + DeclarationName Name = Context.DeclarationNames.getCXXDestructorName(ClassType); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index cd18b969a4..bb9fa4b798 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1533,6 +1533,11 @@ public: CXXConstructorDecl *Constructor, QualType DeclInitType, Expr **Exprs, unsigned NumExprs); + + /// DefineImplicitDefaultConstructor - Checks for feasibilityt of + /// defining this constructor as the default constructor. + void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor); /// 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/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9e31bae79d..c4d1fe9983 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2732,8 +2732,12 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) { IK_Default); if (!Constructor) Var->setInvalidDecl(); - else if (!RD->hasTrivialConstructor()) - InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0); + else { + if (!RD->hasTrivialConstructor()) + InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0); + // Check for valid construction. + DefineImplicitDefaultConstructor(Var->getLocation(), Constructor); + } } } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index a37929cb67..fd1cc0406f 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1793,7 +1793,7 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, return DeclPtrTy(); } - NamespaceAliasDecl *AliasDecl = + NamespaceAliasDecl *AliasDecl = NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc, Alias, SS.getRange(), (NestedNameSpecifier *)SS.getScopeRep(), @@ -1803,6 +1803,80 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, return DeclPtrTy::make(AliasDecl); } +void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor) { + if (!Constructor->isDefaultConstructor() || + !Constructor->isImplicit() || Constructor->isImplicitMustBeDefined()) + return; + + CXXRecordDecl *ClassDecl + = cast<CXXRecordDecl>(Constructor->getDeclContext()); + assert(ClassDecl && "InitializeVarWithConstructor - 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 + // implicitly defined. + bool err = false; + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl()); + if (!BaseClassDecl->hasTrivialConstructor()) { + if (CXXConstructorDecl *BaseCtor = + BaseClassDecl->getDefaultConstructor(Context)) { + if (BaseCtor->isImplicit()) + BaseCtor->setImplicitMustBeDefined(); + } + else { + Diag(CurrentLocation, diag::err_defining_default_ctor) + << ClassDecl->getNameAsCString() << BaseClassDecl->getNameAsCString(); + Diag(BaseClassDecl->getLocation(), diag::not_previous_class_decl) + << BaseClassDecl->getNameAsCString(); + err = true; + } + } + } + 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 (!FieldClassDecl->hasTrivialConstructor()) + if (CXXConstructorDecl *FieldCtor = + FieldClassDecl->getDefaultConstructor(Context)) { + if (FieldCtor->isImplicit()) + FieldCtor->setImplicitMustBeDefined(); + } + else { + Diag(CurrentLocation, diag::err_defining_default_ctor) + << ClassDecl->getNameAsCString() << + FieldClassDecl->getNameAsCString(); + Diag(FieldClassDecl->getLocation(), diag::not_previous_class_decl) + << FieldClassDecl->getNameAsCString(); + err = true; + } + } + else if (FieldType->isReferenceType()) { + Diag(CurrentLocation, diag::err_unintialized_member) + << ClassDecl->getNameAsCString() << 0; + Diag((*Field)->getLocation(), diag::note_declared_at); + err = true; + } + else if (FieldType.isConstQualified()) { + Diag(CurrentLocation, diag::err_unintialized_member) + << ClassDecl->getNameAsCString() << 1; + Diag((*Field)->getLocation(), diag::note_declared_at); + err = true; + } + } + if (!err) + Constructor->setImplicitMustBeDefined(); +} + void Sema::InitializeVarWithConstructor(VarDecl *VD, CXXConstructorDecl *Constructor, QualType DeclInitType, @@ -1878,6 +1952,9 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, VDecl->setCXXDirectInitializer(true); InitializeVarWithConstructor(VDecl, Constructor, DeclInitType, (Expr**)Exprs.release(), NumExprs); + // An implicitly-declared default constructor for a class is implicitly + // defined when it is used to creat an object of its class type. + DefineImplicitDefaultConstructor(VDecl->getLocation(), Constructor); } return; } |