/// HasPublicFields - True when there are private non-static data members.
bool HasPublicFields : 1;
- /// HasTrivialConstructor - True when this class has a trivial constructor.
+ /// HasTrivialDefaultConstructor - True when this class has a trivial
+ /// default constructor.
///
- /// C++ [class.ctor]p5. A constructor is trivial if it is an
- /// implicitly-declared default constructor and if:
- /// * its class has no virtual functions and no virtual base classes, and
- /// * all the direct base classes of its class have trivial constructors, and
- /// * for all the nonstatic data members of its class that are of class type
- /// (or array thereof), each such class has a trivial constructor.
- bool HasTrivialConstructor : 1;
+ /// C++0x [class.ctor]p5
+ /// A default constructor is trivial if it is not user-provided and if
+ /// -- its class has no virtual functions and no virtual base classes,
+ /// and
+ /// -- no non-static data member of its class has a
+ /// brace-or-equal-initializer, and
+ /// -- all the direct base classes of its class have trivial
+ /// default constructors, and
+ /// -- for all the nonstatic data members of its class that are of class
+ /// type (or array thereof), each such class has a trivial
+ /// default constructor.
+ bool HasTrivialDefaultConstructor : 1;
/// HasConstExprNonCopyMoveConstructor - True when this class has at least
/// one constexpr constructor which is neither the copy nor move
///
/// C++0x [class.copy]p13:
/// A copy/move constructor for class X is trivial if it is neither
- /// user-provided nor deleted and if
+ /// user-provided and if
/// -- class X has no virtual functions and no virtual base classes, and
/// -- the constructor selected to copy/move each direct base class
/// subobject is trivial, and
///
/// C++0x [class.copy]p13:
/// A copy/move constructor for class X is trivial if it is neither
- /// user-provided nor deleted and if
+ /// user-provided and if
/// -- class X has no virtual functions and no virtual base classes, and
/// -- the constructor selected to copy/move each direct base class
/// subobject is trivial, and
/// (C++ [class]p7)
bool isStandardLayout() const { return data().IsStandardLayout; }
- // hasTrivialConstructor - Whether this class has a trivial constructor
- // (C++ [class.ctor]p5)
- bool hasTrivialConstructor() const { return data().HasTrivialConstructor; }
+ // hasTrivialDefaultConstructor - Whether this class has a trivial default
+ // constructor
+ // (C++0x [class.ctor]p5)
+ bool hasTrivialDefaultConstructor() const {
+ return data().HasTrivialDefaultConstructor;
+ }
// hasConstExprNonCopyMoveConstructor - Whether this class has at least one
// constexpr constructor other than the copy or move constructors
}
// isTriviallyCopyable - Whether this class is considered trivially copyable
- // (C++0x [class]p5).
+ // (C++0x [class]p6).
bool isTriviallyCopyable() const;
+ // isTrivial - Whether this class is considered trivial
+ //
+ // C++0x [class]p6
+ // A trivial class is a class that has a trivial default constructor and
+ // is trivially copiable.
+ bool isTrivial() const {
+ return isTriviallyCopyable() && hasTrivialDefaultConstructor();
+ }
+
/// \brief If this record is an instantiation of a member class,
/// retrieves the member class from which it was instantiated.
///
UTT_HasNothrowConstructor,
UTT_HasTrivialAssign,
UTT_HasTrivialCopy,
- UTT_HasTrivialConstructor,
+ UTT_HasTrivialDefaultConstructor,
UTT_HasTrivialDestructor,
UTT_HasVirtualDestructor,
UTT_IsAbstract,
// Structs that have non-trivial constructors or destructors are required.
// FIXME: Handle references.
+ // FIXME: Be more selective about which constructors we care about.
if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
- if (RD->hasDefinition() &&
- (!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor()))
+ if (RD->hasDefinition() && !(RD->hasTrivialDefaultConstructor() &&
+ RD->hasTrivialCopyConstructor() &&
+ RD->hasTrivialMoveConstructor() &&
+ RD->hasTrivialDestructor()))
return true;
}
}
Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true),
HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false),
- HasTrivialConstructor(true), HasConstExprNonCopyMoveConstructor(false),
- HasTrivialCopyConstructor(true), HasTrivialMoveConstructor(true),
- HasTrivialCopyAssignment(true), HasTrivialMoveAssignment(true),
- HasTrivialDestructor(true), HasNonLiteralTypeFieldsOrBases(false),
- ComputedVisibleConversions(false),
+ HasTrivialDefaultConstructor(true),
+ HasConstExprNonCopyMoveConstructor(false), HasTrivialCopyConstructor(true),
+ 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(),
data().Empty = false;
// C++ [class.ctor]p5:
- // A constructor is trivial if its class has no virtual base classes.
- data().HasTrivialConstructor = false;
+ // A default constructor is trivial [...] if:
+ // -- its class has [...] no virtual bases
+ data().HasTrivialDefaultConstructor = false;
// C++0x [class.copy]p13:
// A copy/move constructor for class X is trivial if it is neither
data().IsStandardLayout = false;
} else {
// C++ [class.ctor]p5:
- // A constructor is trivial if all the direct base classes of its
- // class have trivial constructors.
- if (!BaseClassDecl->hasTrivialConstructor())
- data().HasTrivialConstructor = false;
+ // A default constructor is trivial [...] if:
+ // -- all the direct base classes of its class have trivial default
+ // constructors.
+ if (!BaseClassDecl->hasTrivialDefaultConstructor())
+ data().HasTrivialDefaultConstructor = false;
// C++0x [class.copy]p13:
// A copy/move constructor for class X is trivial if [...]
// polymorphic class.
data().Polymorphic = true;
- // None of the special member functions are trivial.
- data().HasTrivialConstructor = false;
+ // C++0x [class.ctor]p5
+ // A default constructor is trivial [...] if:
+ // -- its class has no virtual functions [...]
+ data().HasTrivialDefaultConstructor = false;
// C++0x [class.copy]p13:
// A copy/move constructor for class X is trivial if [...]
// A POD-struct is an aggregate class [...]
data().PlainOldData = false;
- // C++ [class.ctor]p5:
- // A constructor is trivial if it is an implicitly-declared default
- // constructor.
- // FIXME: C++0x: don't do this for "= default" default constructors.
- data().HasTrivialConstructor = false;
+ // C++0x [class.ctor]p5:
+ // A default constructor is trivial if it is not user-provided [...]
+ if (Constructor->isUserProvided())
+ data().HasTrivialDefaultConstructor = false;
// Note when we have a user-declared copy or move constructor, which will
// suppress the implicit declaration of those constructors.
data().DeclaredCopyConstructor = true;
// C++0x [class.copy]p13:
- // A copy/move constructor for class X is trivial if it is neither
- // user-provided nor deleted
- // FIXME: C++0x: don't do this for "= default" copy constructors.
- data().HasTrivialCopyConstructor = false;
+ // A copy/move constructor for class X is trivial if it is not
+ // user-provided [...]
+ if (Constructor->isUserProvided())
+ data().HasTrivialCopyConstructor = false;
} else if (Constructor->isMoveConstructor()) {
// C++0x [class.copy]p13:
- // A copy/move constructor for class X is trivial if it is neither
- // user-provided nor deleted
- // FIXME: C++0x: don't do this for "= default" move constructors.
- data().HasTrivialMoveConstructor = false;
+ // A copy/move constructor for class X is trivial if it is not
+ // user-provided [...]
+ if (Constructor->isUserProvided())
+ data().HasTrivialMoveConstructor = false;
}
}
if (Constructor->isConstExpr() &&
if (!T->isPODType())
data().PlainOldData = false;
if (T->isReferenceType()) {
- data().HasTrivialConstructor = false;
+ data().HasTrivialDefaultConstructor = false;
// C++0x [class]p7:
// A standard-layout class is a class that:
if (const RecordType *RecordTy = T->getAs<RecordType>()) {
CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
if (FieldRec->getDefinition()) {
- if (!FieldRec->hasTrivialConstructor())
- data().HasTrivialConstructor = false;
+ // C++0x [class.ctor]p5:
+ // A defulat constructor is trivial [...] if:
+ // -- for all the non-static data members of its class that are of
+ // class type (or array thereof), each such class has a trivial
+ // default constructor.
+ if (!FieldRec->hasTrivialDefaultConstructor())
+ data().HasTrivialDefaultConstructor = false;
// C++0x [class.copy]p13:
// A copy/move constructor for class X is trivial if [...]
case UTT_HasNothrowConstructor: return "__has_nothrow_constructor";
case UTT_HasNothrowCopy: return "__has_nothrow_copy";
case UTT_HasTrivialAssign: return "__has_trivial_assign";
- case UTT_HasTrivialConstructor: return "__has_trivial_constructor";
+ case UTT_HasTrivialDefaultConstructor: return "__has_trivial_constructor";
case UTT_HasTrivialCopy: return "__has_trivial_copy";
case UTT_HasTrivialDestructor: return "__has_trivial_destructor";
case UTT_HasVirtualDestructor: return "__has_virtual_destructor";
if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
if (const CXXRecordDecl *ClassDecl =
dyn_cast<CXXRecordDecl>(RT->getDecl())) {
- // C++0x [class]p5:
- // A trivial class is a class that has a trivial default constructor
- if (!ClassDecl->hasTrivialConstructor()) return false;
- // and is trivially copyable.
- if (!ClassDecl->isTriviallyCopyable()) return false;
+ if (!ClassDecl->isTrivial()) return false;
}
return true;
dyn_cast<CXXRecordDecl>(RT->getDecl())) {
// C++11 [class]p10:
// A POD struct is a non-union class that is both a trivial class [...]
- // C++11 [class]p5:
- // A trivial class is a class that has a trivial default constructor
- if (!ClassDecl->hasTrivialConstructor()) return false;
- // and is trivially copyable.
- if (!ClassDecl->isTriviallyCopyable()) return false;
+ if (!ClassDecl->isTrivial()) return false;
// C++11 [class]p10:
// A POD struct is a non-union class that is both a trivial class and
if (const RecordType *RT = CGF.getContext()
.getBaseElementType(ElementType)->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- hasNonTrivialCXXConstructor = !RD->hasTrivialConstructor();
+ hasNonTrivialCXXConstructor = !RD->hasTrivialDefaultConstructor();
}
// FIXME: were we intentionally ignoring address spaces and GC attributes?
if (E->isArray()) {
if (CXXConstructorDecl *Ctor = E->getConstructor()) {
bool RequiresZeroInitialization = false;
- if (Ctor->getParent()->hasTrivialConstructor()) {
+ if (Ctor->getParent()->hasTrivialDefaultConstructor()) {
// If new expression did not specify value-initialization, then there
// is no initialization.
if (!E->hasInitializer() || Ctor->getParent()->isEmpty())
const CXXRecordDecl *classDecl = IVART->getAsCXXRecordDecl();
if (PID->getGetterCXXConstructor() &&
- classDecl && !classDecl->hasTrivialConstructor()) {
+ classDecl && !classDecl->hasTrivialDefaultConstructor()) {
ReturnStmt *Stmt =
new (getContext()) ReturnStmt(SourceLocation(),
PID->getGetterCXXConstructor(),
case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign;
- case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
+ case tok::kw___has_trivial_constructor:
+ return UTT_HasTrivialDefaultConstructor;
case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy;
case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor;
case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor;
CXXSpecialMember member = CXXInvalid;
if (!RDecl->hasTrivialCopyConstructor())
member = CXXCopyConstructor;
- else if (!RDecl->hasTrivialConstructor())
+ else if (!RDecl->hasTrivialDefaultConstructor())
member = CXXConstructor;
else if (!RDecl->hasTrivialCopyAssignment())
member = CXXCopyAssignment;
bool (CXXRecordDecl::*hasTrivial)() const;
switch (member) {
case CXXConstructor:
- hasTrivial = &CXXRecordDecl::hasTrivialConstructor; break;
+ hasTrivial = &CXXRecordDecl::hasTrivialDefaultConstructor; break;
case CXXCopyConstructor:
hasTrivial = &CXXRecordDecl::hasTrivialCopyConstructor; break;
case CXXCopyAssignment:
/*isImplicitlyDeclared=*/true);
DefaultCon->setAccess(AS_public);
DefaultCon->setImplicit();
- DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor());
+ DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor());
// Note that we have declared this constructor.
++ASTContext::NumImplicitDefaultConstructorsDeclared;
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
unsigned TypeQuals;
if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) {
- if (Constructor->getParent()->hasTrivialConstructor())
+ if (Constructor->getParent()->hasTrivialDefaultConstructor())
return;
if (!Constructor->isUsed(false))
DefineImplicitDefaultConstructor(Loc, Constructor);
case UTT_HasNothrowConstructor:
case UTT_HasNothrowCopy:
case UTT_HasTrivialAssign:
- case UTT_HasTrivialConstructor:
+ case UTT_HasTrivialDefaultConstructor:
case UTT_HasTrivialCopy:
case UTT_HasTrivialDestructor:
case UTT_HasVirtualDestructor:
//
// 1: http://gcc.gnu/.org/onlinedocs/gcc/Type-Traits.html
// 2: http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index
- case UTT_HasTrivialConstructor:
+ case UTT_HasTrivialDefaultConstructor:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
// If __is_pod (type) is true then the trait is true, else if type is
// a cv class or union type (or array thereof) with a trivial default
return true;
if (const RecordType *RT =
C.getBaseElementType(T)->getAs<RecordType>())
- return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialConstructor();
+ return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDefaultConstructor();
return false;
case UTT_HasTrivialCopy:
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
return true;
if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- if (RD->hasTrivialConstructor())
+ if (RD->hasTrivialDefaultConstructor())
return true;
DeclContext::lookup_const_iterator Con, ConEnd;
CXXRecordDecl *ClassDecl = Constructor->getParent();
assert(ClassDecl && "No parent class for constructor.");
if (Constructor->isImplicit() && Constructor->isDefaultConstructor() &&
- ClassDecl->hasTrivialConstructor() && !Constructor->isUsed(false))
+ ClassDecl->hasTrivialDefaultConstructor() &&
+ !Constructor->isUsed(false))
S.DefineImplicitDefaultConstructor(Loc, Constructor);
}
Data.HasPrivateFields = Record[Idx++];
Data.HasProtectedFields = Record[Idx++];
Data.HasPublicFields = Record[Idx++];
- Data.HasTrivialConstructor = Record[Idx++];
+ Data.HasTrivialDefaultConstructor = Record[Idx++];
Data.HasConstExprNonCopyMoveConstructor = Record[Idx++];
Data.HasTrivialCopyConstructor = Record[Idx++];
Data.HasTrivialMoveConstructor = Record[Idx++];
Record.push_back(Data.HasPrivateFields);
Record.push_back(Data.HasProtectedFields);
Record.push_back(Data.HasPublicFields);
- Record.push_back(Data.HasTrivialConstructor);
+ Record.push_back(Data.HasTrivialDefaultConstructor);
Record.push_back(Data.HasConstExprNonCopyMoveConstructor);
Record.push_back(Data.HasTrivialCopyConstructor);
Record.push_back(Data.HasTrivialMoveConstructor);