Diagnose when base classes and members to be intialized
with constructors don't have a matching constructor. llvm-svn: 76913
This commit is contained in:
parent
909f6001e9
commit
ca2f085a4e
|
@ -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
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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}}
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue