[cfe-commits] r76913 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/DeclCXX.cpp lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp test/SemaCXX/constructor-initializer.cpp
Fariborz Jahanian
fjahanian at apple.com
Thu Jul 23 16:33:20 PDT 2009
Author: fjahanian
Date: Thu Jul 23 18:32:59 2009
New Revision: 76913
URL: http://llvm.org/viewvc/llvm-project?rev=76913&view=rev
Log:
Diagnose when base classes and members to be intialized
with constructors don't have a matching constructor.
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/SemaCXX/constructor-initializer.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=76913&r1=76912&r2=76913&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Jul 23 18:32:59 2009
@@ -736,7 +736,7 @@
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 @@
}
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
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=76913&r1=76912&r2=76913&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jul 23 18:32:59 2009
@@ -346,6 +346,9 @@
"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">;
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=76913&r1=76912&r2=76913&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Jul 23 18:32:59 2009
@@ -564,9 +564,11 @@
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 @@
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 @@
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 @@
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,
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=76913&r1=76912&r2=76913&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Jul 23 18:32:59 2009
@@ -1482,6 +1482,11 @@
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
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=76913&r1=76912&r2=76913&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Jul 23 18:32:59 2009
@@ -810,6 +810,26 @@
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 @@
<< 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 @@
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>()))
- Constructor->setBaseOrMemberInitializers(Context,
- (CXXBaseOrMemberInitializer **)0, 0);
+ BuildBaseOrMemberInitializers(Context,
+ Constructor,
+ (CXXBaseOrMemberInitializer **)0, 0);
}
namespace {
Modified: cfe/trunk/test/SemaCXX/constructor-initializer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor-initializer.cpp?rev=76913&r1=76912&r2=76913&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constructor-initializer.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor-initializer.cpp Thu Jul 23 18:32:59 2009
@@ -96,3 +96,23 @@
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}}
+};
+
+
More information about the cfe-commits
mailing list