diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 19 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 35 |
3 files changed, 46 insertions, 13 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 0f2230116cc..7b5a29028c4 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -564,9 +564,11 @@ CXXDestructorDecl::computeBaseOrMembersToDestroy(ASTContext &C) { void CXXConstructorDecl::setBaseOrMemberInitializers( - ASTContext &C, - CXXBaseOrMemberInitializer **Initializers, - unsigned NumInitializers) { + ASTContext &C, + CXXBaseOrMemberInitializer **Initializers, + unsigned NumInitializers, + llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases, + llvm::SmallVectorImpl<FieldDecl *>&Fields) { // We need to build the initializer AST according to order of construction // and not what user specified in the Initializers list. CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(getDeclContext()); @@ -594,7 +596,9 @@ CXXConstructorDecl::setBaseOrMemberInitializers( CXXRecordDecl *VBaseDecl = cast<CXXRecordDecl>(VBase->getType()->getAsRecordType()->getDecl()); assert(VBaseDecl && "setBaseOrMemberInitializers - VBaseDecl null"); - // FIXME. Issue error if default ctor is missing. + if (!VBaseDecl->getDefaultConstructor(C) && + !VBase->getType()->isDependentType()) + Bases.push_back(VBase); CXXBaseOrMemberInitializer *Member = new (C) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0, VBaseDecl->getDefaultConstructor(C), @@ -617,7 +621,9 @@ CXXConstructorDecl::setBaseOrMemberInitializers( CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl()); assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null"); - // FIXME. Issue error if default ctor is missing. + if (!BaseDecl->getDefaultConstructor(C) && + !Base->getType()->isDependentType()) + Bases.push_back(Base); CXXBaseOrMemberInitializer *Member = new (C) CXXBaseOrMemberInitializer(Base->getType(), 0, 0, BaseDecl->getDefaultConstructor(C), @@ -643,7 +649,8 @@ CXXConstructorDecl::setBaseOrMemberInitializers( if (CXXRecordDecl *FieldClassDecl = dyn_cast<CXXRecordDecl>(FieldType->getAsRecordType()->getDecl())) Ctor = FieldClassDecl->getDefaultConstructor(C); - // FIXME. Issue error if default ctor is missing. + if (!Ctor && !FieldType->isDependentType()) + Fields.push_back(*Field); CXXBaseOrMemberInitializer *Member = new (C) CXXBaseOrMemberInitializer((*Field), 0, 0, Ctor, diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index d66e642af3a..5f504384454 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1482,6 +1482,11 @@ public: const FunctionProtoType *Proto, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc); + void BuildBaseOrMemberInitializers(ASTContext &C, + CXXConstructorDecl *Constructor, + CXXBaseOrMemberInitializer **Initializers, + unsigned NumInitializers + ); /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index c12878c7603..d5c8c3d3fce 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -810,6 +810,26 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, NumArgs, C, IdLoc); } +void +Sema::BuildBaseOrMemberInitializers(ASTContext &C, + CXXConstructorDecl *Constructor, + CXXBaseOrMemberInitializer **Initializers, + unsigned NumInitializers + ) { + llvm::SmallVector<CXXBaseSpecifier *, 4>Bases; + llvm::SmallVector<FieldDecl *, 4>Members; + + Constructor->setBaseOrMemberInitializers(C, + Initializers, NumInitializers, + Bases, Members); + for (unsigned int i = 0; i < Bases.size(); i++) + Diag(Bases[i]->getSourceRange().getBegin(), + diag::err_missing_default_constructor) << 0 << Bases[i]->getType(); + for (unsigned int i = 0; i < Members.size(); i++) + Diag(Members[i]->getLocation(), diag::err_missing_default_constructor) + << 1 << Members[i]->getType(); +} + static void *GetKeyForTopLevelField(FieldDecl *Field) { // For anonymous unions, use the class declaration as the key. if (const RecordType *RT = Field->getType()->getAsRecordType()) { @@ -872,11 +892,11 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, << 0; err = true; } - if (!err) { - Constructor->setBaseOrMemberInitializers(Context, - reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits), - NumMemInits); - } + if (!err) + BuildBaseOrMemberInitializers(Context, Constructor, + reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits), + NumMemInits); + if (!err && (Diags.getDiagnosticLevel(diag::warn_base_initialized) != Diagnostic::Ignored || Diags.getDiagnosticLevel(diag::warn_field_initialized) @@ -960,8 +980,9 @@ void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) { if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>())) - Constructor->setBaseOrMemberInitializers(Context, - (CXXBaseOrMemberInitializer **)0, 0); + BuildBaseOrMemberInitializers(Context, + Constructor, + (CXXBaseOrMemberInitializer **)0, 0); } namespace { |