IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified),
IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
+ IsDefaulted(false), IsExplicitlyDefaulted(false),
HasImplicitReturnZero(false), IsLateTemplateParsed(false),
EndRangeLoc(NameInfo.getEndLoc()),
TemplateOrSpecialization(),
/// HasPublicFields - True when there are private non-static data members.
bool HasPublicFields : 1;
- /// HasTrivialDefaultConstructor - True when this class has a trivial
- /// default constructor.
+ /// HasTrivialDefaultConstructor - True when, if this class has a default
+ /// constructor, this default constructor is trivial.
///
/// C++0x [class.ctor]p5
/// A default constructor is trivial if it is not user-provided and if
/// \brief Whether we have already declared the default constructor or
/// do not need to have one declared.
+ bool NeedsImplicitDefaultConstructor : 1;
+
+ /// \brief Whether we have already declared the default constructor.
bool DeclaredDefaultConstructor : 1;
/// \brief Whether we have already declared the copy constructor.
/// declared implicitly or does not need one declared implicitly.
///
/// This value is used for lazy creation of default constructors.
- bool hasDeclaredDefaultConstructor() const {
- return data().DeclaredDefaultConstructor;
+ bool needsImplicitDefaultConstructor() const {
+ return data().NeedsImplicitDefaultConstructor;
}
/// hasConstCopyConstructor - Determines whether this class has a
// constructor
// (C++0x [class.ctor]p5)
bool hasTrivialDefaultConstructor() const {
- return data().HasTrivialDefaultConstructor;
+ return data().HasTrivialDefaultConstructor &&
+ (!data().UserDeclaredConstructor ||
+ data().DeclaredDefaultConstructor);
}
// hasConstExprNonCopyMoveConstructor - Whether this class has at least one
HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialMoveAssignment(true), HasTrivialDestructor(true),
HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
- DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false),
- DeclaredCopyAssignment(false), DeclaredDestructor(false),
- NumBases(0), NumVBases(0), Bases(), VBases(),
- Definition(D), FirstFriend(0) {
+ NeedsImplicitDefaultConstructor(false), DeclaredDefaultConstructor(false),
+ DeclaredCopyConstructor(false), DeclaredCopyAssignment(false),
+ DeclaredDestructor(false), NumBases(0), NumVBases(0), Bases(), VBases(),
+ Definition(D), FirstFriend(0) {
}
CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
// If this is the implicit default constructor, note that we have now
// declared it.
- if (Constructor->isDefaultConstructor())
+ if (Constructor->isDefaultConstructor()) {
data().DeclaredDefaultConstructor = true;
+ data().NeedsImplicitDefaultConstructor = true;
+ }
// If this is the implicit copy constructor, note that we have now
// declared it.
else if (Constructor->isCopyConstructor())
data().UserDeclaredConstructor = true;
// Note that we have no need of an implicitly-declared default constructor.
- data().DeclaredDefaultConstructor = true;
+ data().NeedsImplicitDefaultConstructor = true;
- // C++ [dcl.init.aggr]p1:
- // An aggregate is an array or a class (clause 9) with no
- // user-declared constructors (12.1) [...].
- data().Aggregate = false;
-
- // C++ [class]p4:
- // A POD-struct is an aggregate class [...]
- data().PlainOldData = false;
+ // FIXME: Under C++0x, /only/ special member functions may be user-provided.
+ // This is probably a defect.
+ bool UserProvided = false;
// C++0x [class.ctor]p5:
// A default constructor is trivial if it is not user-provided [...]
- if (Constructor->isUserProvided())
- data().HasTrivialDefaultConstructor = false;
+ if (Constructor->isDefaultConstructor()) {
+ data().DeclaredDefaultConstructor = true;
+ if (Constructor->isUserProvided()) {
+ data().HasTrivialDefaultConstructor = false;
+ UserProvided = true;
+ }
+ }
// Note when we have a user-declared copy or move constructor, which will
// suppress the implicit declaration of those constructors.
// C++0x [class.copy]p13:
// A copy/move constructor for class X is trivial if it is not
// user-provided [...]
- if (Constructor->isUserProvided())
+ if (Constructor->isUserProvided()) {
data().HasTrivialCopyConstructor = false;
+ UserProvided = true;
+ }
} else if (Constructor->isMoveConstructor()) {
// C++0x [class.copy]p13:
// A copy/move constructor for class X is trivial if it is not
// user-provided [...]
- if (Constructor->isUserProvided())
+ if (Constructor->isUserProvided()) {
data().HasTrivialMoveConstructor = false;
+ UserProvided = true;
+ }
}
}
if (Constructor->isConstExpr() &&
data().HasConstExprNonCopyMoveConstructor = true;
}
+ // C++ [dcl.init.aggr]p1:
+ // An aggregate is an array or a class with no user-declared
+ // constructors [...].
+ // C++0x [dcl.init.aggr]p1:
+ // An aggregate is an array or a class with no user-provided
+ // constructors [...].
+ if (!getASTContext().getLangOptions().CPlusPlus0x || UserProvided)
+ data().Aggregate = false;
+
+ // C++ [class]p4:
+ // A POD-struct is an aggregate class [...]
+ // Since the POD bit is meant to be C++03 POD-ness, clear it even if the
+ // type is technically an aggregate in C++0x since it wouldn't be in 03.
+ data().PlainOldData = false;
+
return;
}
if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
- if (!BaseClassDecl->hasDeclaredDefaultConstructor())
+ if (!BaseClassDecl->needsImplicitDefaultConstructor())
ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
else if (CXXConstructorDecl *Constructor
= getDefaultConstructorUnsafe(*this, BaseClassDecl))
B != BEnd; ++B) {
if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
- if (!BaseClassDecl->hasDeclaredDefaultConstructor())
+ if (!BaseClassDecl->needsImplicitDefaultConstructor())
ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
else if (CXXConstructorDecl *Constructor
= getDefaultConstructorUnsafe(*this, BaseClassDecl))
if (const RecordType *RecordTy
= Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
- if (!FieldClassDecl->hasDeclaredDefaultConstructor())
+ if (!FieldClassDecl->needsImplicitDefaultConstructor())
ExceptSpec.CalledDecl(
DeclareImplicitDefaultConstructor(FieldClassDecl));
else if (CXXConstructorDecl *Constructor
return;
// If the default constructor has not yet been declared, do so now.
- if (!Class->hasDeclaredDefaultConstructor())
+ if (!Class->needsImplicitDefaultConstructor())
DeclareImplicitDefaultConstructor(Class);
// If the copy constructor has not yet been declared, do so now.
if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
if (Record->getDefinition() &&
CanDeclareSpecialMemberFunction(S.Context, Record)) {
- if (!Record->hasDeclaredDefaultConstructor())
+ if (!Record->needsImplicitDefaultConstructor())
S.DeclareImplicitDefaultConstructor(
const_cast<CXXRecordDecl *>(Record));
if (!Record->hasDeclaredCopyConstructor())
DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
// If the copy constructor has not yet been declared, do so now.
if (CanDeclareSpecialMemberFunction(Context, Class)) {
- if (!Class->hasDeclaredDefaultConstructor())
+ if (!Class->needsImplicitDefaultConstructor())
DeclareImplicitDefaultConstructor(Class);
if (!Class->hasDeclaredCopyConstructor())
DeclareImplicitCopyConstructor(Class);
Data.HasTrivialDestructor = Record[Idx++];
Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++];
Data.ComputedVisibleConversions = Record[Idx++];
+ Data.NeedsImplicitDefaultConstructor = Record[Idx++];
Data.DeclaredDefaultConstructor = Record[Idx++];
Data.DeclaredCopyConstructor = Record[Idx++];
Data.DeclaredCopyAssignment = Record[Idx++];
Record.push_back(Data.HasTrivialDestructor);
Record.push_back(Data.HasNonLiteralTypeFieldsOrBases);
Record.push_back(Data.ComputedVisibleConversions);
+ Record.push_back(Data.NeedsImplicitDefaultConstructor);
Record.push_back(Data.DeclaredDefaultConstructor);
Record.push_back(Data.DeclaredCopyConstructor);
Record.push_back(Data.DeclaredCopyAssignment);
// Verify that we can't initialize non-aggregates with an initializer
// list.
+// FIXME: Note that due to a (likely) standard bug, this is technically an
+// aggregate.
struct NonAggr1 {
NonAggr1(int) { }
virtual void f();
};
-NonAggr1 na1 = { 17 }; // expected-error{{non-aggregate type 'NonAggr1' cannot be initialized with an initializer list}}
+NonAggr1 na1 = { 17 };
NonAggr2 na2 = { 17 }; // expected-error{{non-aggregate type 'NonAggr2' cannot be initialized with an initializer list}}
NonAggr3 na3 = { 17 }; // expected-error{{non-aggregate type 'NonAggr3' cannot be initialized with an initializer list}}
NonAggr4 na4 = { 17 }; // expected-error{{non-aggregate type 'NonAggr4' cannot be initialized with an initializer list}}