diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/AST/DeclCXX.h | 8 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-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 | ||||
-rw-r--r-- | clang/test/SemaCXX/constructor-initializer.cpp | 20 |
6 files changed, 74 insertions, 16 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 1d153eefd4a..ed08a60a884 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -736,7 +736,7 @@ class CXXBaseOrMemberInitializer { Expr **Args; unsigned NumArgs; - /// CtorToCall - For a base or mamber needing a constructor for their + /// CtorToCall - For a base or member needing a constructor for their /// initialization, this is the constructor to call. CXXConstructorDecl *CtorToCall; @@ -923,8 +923,10 @@ public: } void setBaseOrMemberInitializers(ASTContext &C, - CXXBaseOrMemberInitializer **Initializers, - unsigned NumInitializers); + CXXBaseOrMemberInitializer **Initializers, + unsigned NumInitializers, + llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases, + llvm::SmallVectorImpl<FieldDecl *>&Members); /// isDefaultConstructor - Whether this constructor is a default /// constructor (C++ [class.ctor]p5), which can be used to diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a8c4de57caf..ead116d8da5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -346,6 +346,9 @@ def err_implicit_object_parameter_init : Error< "cannot initialize object parameter of type %0 with an expression " "of type %1">; +def err_missing_default_constructor : Error< + "default constructor for %1 is missing in initialization of " + "%select{base class|mamber}0">; def err_illegal_union_member : Error< "union member %0 has a non-trivial %select{constructor|" "copy constructor|copy assignment operator|destructor}1">; 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 { diff --git a/clang/test/SemaCXX/constructor-initializer.cpp b/clang/test/SemaCXX/constructor-initializer.cpp index 66a5f57e1c1..71d38a1438b 100644 --- a/clang/test/SemaCXX/constructor-initializer.cpp +++ b/clang/test/SemaCXX/constructor-initializer.cpp @@ -96,3 +96,23 @@ struct Current : Derived { INT::NonExisting() {} // expected-error {{expected a class or namespace}} \ // expected-error {{member initializer 'NonExisting' does not name a non-static data member or}} }; + + // FIXME. This is bad message! +struct M { // expected-note {{candidate function}} \ + // expected-note {{candidate function}} + M(int i, int j); // expected-note {{candidate function}} \ + // // expected-note {{candidate function}} +}; + +struct N : M { + N() : M(1), // expected-error {{no matching constructor for initialization of 'M'}} + m1(100) { } // expected-error {{no matching constructor for initialization of 'm1'}} + M m1; +}; + +struct P : M { // expected-error {{default constructor for 'struct M' is missing in initialization of base class}} + P() { } + M m; // expected-error {{default constructor for 'struct M' is missing in initialization of mamber}} +}; + + |